PROGRAMMING WORKSHOP

Access와 Excel의 연동_6|
억세스 DB와 UserForm의 연결

만들어진 억세스테이블중, 진료를 진행하는 메인테이블을 열어보니,
기본키값만 있다...



DB의 개념에서 제일 중요한 것이다
키값으로 연결된 것을 사용자가 이해하기 편한 정보로 재구성하여 보여주어야 한다
테이블에서는 기본적인 정보만 보관하고..
보여주는 것은 다른 어떤형식의 테이블이 있어야 하지 않을까??
이것은 Access에서는 쿼리(Query)테이블이라고 하고
다른 SQL서버같은 DB에서는 View 테이블이라고 한다

Query테이블을 만들어도 좋지만 그냥 SQL로 각테이블에서 필요한 것만
불러서 메모리상에 테이블을 만들어서 사용하는 것도 좋다

DB를 불러 오는 작업을 하려고 보니까
앞페이지에서 진료테이블의 휠드를 만드는데
진료날짜만 있고 시간휠드를 빼먹었다
진료시간도 추가하여야 엑셀테이블에서 만들었던 것을 그대로 구현하게 된다
테이블 만드는 부분을 아래와 같이 수정한다..
시간은 휠드를 만드는지 궁금하신분은 아래의 수정부분을 보시면 된다


Set oTable = New ADOX.Table
oTable.Name = WORKS
With oTable.Columns
    .Append "WorkID", adInteger
    .Append "PetID", adInteger
    .Append "TreatID", adInteger
    .Append "WorkDate", adDate
    '' 추가.../////////////////////////////
    .Append "WorkTime", adDate
    ''/////////////////////////////////
    With !WorkID
        Set .ParentCatalog = oCatalog
        .Properties("Autoincrement") = True
    End With
End With

Set oKey = New ADOX.Key
oKey.Name = "PRIMARY"
oKey.Type = adKeyPrimary
oKey.Columns.Append "WorkID"
oTable.Keys.Append oKey
oCatalog.Tables.Append oTable
Dim iTreat As Integer
Dim iCustomer As Integer
Dim iPet As Integer
Dim datWork As Date
For iX = 1 To WORK_NUMS
    iTreat = Int(Rnd() * TREAT_NUMS) + 1
    iPet = 2
    datWork = DateSerial(2016, Int(Rnd() * 12 + 1), Int(Rnd() * 30 + 1))
    sSQL = "INSERT INTO " & WORKS & " (PetID,TreatID,WorkDate,WorkTime) values " & _
 "(" & iPet & "," & iTreat & ",#" & datWork & "#, #" & Int(Rnd() * 8) + 9 & ":" & Int(Rnd() * 60) & ":" & Int(Rnd() * 60) & "#)"
    oConn.Execute sSQL
    
Next


 

진료시간휠드를 WorkTime이라고 하고 타입은 Date타입으로 하고
정보는 시간값을 전달하면 된다
문자열정보로 #2016/3/3#이라고 하면 날짜값으로 전달되고
#9:13:20#이라고 하면 시간정보가 전달되는 것이니
진료시간을 9시부터 오후 5시까지라고 치면 문자열을
"#" & Int(Rnd() * 8) + 9 & ":" & Int(Rnd() * 60) & ":" & Int(Rnd() * 60) & "#"
와 같이 SQL문에 엮어서 전달하면 되는 것..

UserForm을 띄울때 DB가 없으면 만들고 데이타를 채워넣은후
아래의 그림과 같이 각 콘트롤에 해당 테이블의 정보를 DB에서 가져다가 채운다




'' 애완동물과 진료타입은 아래의 같은 프로시져를 사용하고 테이블만 바꾸면 된다
Sub fillCombo(oCombo As MSForms.ComboBox, sTable As String)
On Error Resume Next
Dim oRST As ADODB.Recordset
Dim sSQL As String
Dim iRow As Integer
Dim iCol As Integer
Dim iColNums As Integer


sSQL = "SELECT * FROM " & sTable
Set oRST = getRecordset(sSQL)
iColNums = oRST.Fields.Count
With oCombo
    .ColumnCount = iColNums
    If sTable = PETS Then
'' ID열은 숫자값이라서 사용자에게 별의미 없으니 열폭을 0으로 하여 눈에 보이지 않게 한다
        .ColumnWidths = "0;0;100;100;100"
    ElseIf sTable = TREAT_TYPES Then
        .ColumnWidths = "0;100;100"
    End If
    Do Until oRST.EOF
            For iCol = 0 To iColNums - 1
                If iCol = 0 Then
                    .AddItem oRST.Fields(iCol).Value
                Else
                    .List(iRow, iCol) = oRST.Fields(iCol).Value
                End If
            Next
            iRow = iRow + 1
         oRST.MoveNext
Loop
End With
oRST.Close
Set oRST = Nothing

End Sub

'' 진료테이블
Sub fillWorksList(oList As MSForms.ListBox)
On Error Resume Next
Dim oRST As ADODB.Recordset
Dim sSQL As String
sSQL = "SELECT *  FROM " & WORKS
Set oRST = getRecordset(sSQL)
Dim iRow As Integer
Dim iCol As Integer
Dim iColNums As Integer
iColNums = oRST.Fields.Count

With oList
    .ColumnCount = iColNums
    .ColumnWidths = "0;0;0;100;100"

    Do Until oRST.EOF
            For iCol = 0 To iColNums - 1
                If iCol = 0 Then
                    .AddItem oRST.Fields(iCol).Value
                Else
                    .List(iRow, iCol) = oRST.Fields(iCol).Value
                End If
            Next
            iRow = iRow + 1
         oRST.MoveNext
    Loop
    .ListIndex = 0
End With

oRST.Close
Set oRST = Nothing
End Sub

   

진료테이블을 채운후에 진료테이블의 첫째행을 선택해주고
진료테이블의 목록상자의 행선택이벤트(Change이벤트)에서 아래와 같이 작성하여
진료테이블과 두개의 콤보상자의 값이 동기화되게 유지한다

Private Sub lstTreatingProcess_Change()
On Error Resume Next
Dim iPetIndex As Integer
Dim iTreatTypeIndex As Integer
Dim iIndex As Integer
'' 숨겨진 각 ID열의 해당 값을 읽어서 두개의 콤보상자의 값과 동기화한다

iPetIndex = lstTreatingProcess.List(lstTreatingProcess.ListIndex, WORK_PET_ID_COL)
iTreatTypeIndex = lstTreatingProcess.List(lstTreatingProcess.ListIndex, WORK_TREAT_ID_COL)
For iIndex = 0 To Me.cboPets.ListCount - 1
    If Me.cboPets.List(iIndex, 0) = iPetIndex Then
        Me.cboPets.ListIndex = iIndex
        Exit For
    End If
Next

For iIndex = 0 To Me.cboTreats.ListCount - 1
    If Me.cboTreats.List(iIndex, 0) = iPetIndex Then
        Me.cboTreats.ListIndex = iIndex
        Exit For
    End If
Next

'' 진료일자와 진료시간을 읽어서 텍스트상자에 해당 진료행과 일치하게 유지한다
Me.txtDateAndTime.Text = lstTreatingProcess.List(lstTreatingProcess.ListIndex, WORK_DATE_COL) & " " & _
                                         lstTreatingProcess.List(lstTreatingProcess.ListIndex, WORK_TIME_COL)

End Sub

    

위와 같이 하면 진료테이블의 행을 바꿀때마다 관련된 콘트롤의 값이 같은 값을 유지하게 된다
위의 내용까지 아래의 화일에서 챙겨보시고...

***[LOG-IN]***

위에서 DB에서 가져온 정보는 모두 단일 테이블에서 가져 왔다
다음 페이지에서는 여러개의 정보를 가져 오기 위하여 여러개의 테이블을 연결하여
가져다가 정보를 뿌려줘 보도록 하자