FILE: Dbgridub.exe Uses DBGRID in an Unbound ModeID: Q140021
|
Visual Basic version 4.0 for Windows ships with a full-featured grid that
allows in-place editing of items in a table. This grid, the Data Bound Grid
(DBGRID), was designed to be used to edit and display records in a database
table. This article includes a document that was written by Apex Software
Corporation, the designers of the control, that discusses how to use this
control in an unbound mode.
The Microsoft Knowledge Base article Q113902 also contains the text of the
document.
The following file is available for download from the Microsoft Software
Library:
~ Dbgridub.exe
For more information about downloading files from the Microsoft Software
Library, please see the following article in the Microsoft Knowledge Base:
Q119591 : How to Obtain Microsoft Support Files from Online Services
' Declare grid data as global array in some global module
Global GridArray(0 to 1, 0 to 2) As String
' Initialize array data in Main() or Form_Load()
For i% = 0 To 1
For j% = 0 To 2
GridArray(i%, j%) = "Row " & Str$(j%) & ", Col " & Str$(i%)
Next j%
Next i%
' For the sake of efficiency, we use Column objects to reference
' column properties, instead of repeatedly going through the
' grid's Columns collection object.
Dim Col0, Col1 as Column
' Assuming the control name of the grid is DBGrid1, initialize
' grid properties in Form_Load():
' Assign the Column objects
Set Col0 = DBGrid1.Columns(0)
Set Col1 = DBGrid1.Columns(1)
' Define column heading text. This can be done in code at
' runtime or in the Columns property page during design time.
Col0.Caption = "Column 0"
Col1.Caption = "Column 1"
' Columns display widths (in container units).
Col0.Width = 1500
Col1.Width = 1500
' Column alignment. Specify left, center, or right justified.
Col0.Alignment = 0 ' Left
Col1.Alignment = 1 ' Right
' Column Locking. Specifies if a column is read-only
' (i.e., user cannot edit that column).
Col0.Locked = False
Col1.Locked = True
' Initialize current cell position to upper left corner:
DBGrid1.Row = 0
DBGrid1.Col = 0
' Assume 5 columns are desired, and we wish to remove the
' existing columns since we do not know the property settings
' or even how many columns exist
Dim oldcnt, newcnt as Integer
' Save how many columns initially exist in the grid, so we can
' remove them later. Also initialize the new column counter.
oldcnt = DBGrid1.Columns.Count
newcnt = 0
' Now add the new columns. New columns are inserted before (and
' to the left of) the existing column number passed to the
' Columns collection Add method.
For i% = 0 To 4
DBGrid1.Columns.Add newcnt
DBGrid1.Columns(newcnt).Caption = "Col " & newcnt
DBGrid1.Columns(newcnt).Visible = True
newcnt = newcnt + 1
Next i%
' Now remove the original existing columns. As grid columns are
' removed from the collection, columns with higher indexes just
' move down, so we just keep removing the same column the
' appropriate number of times.
While oldcnt > 0
DBGrid1.Columns.Remove newcnt
oldcnt = oldcnt - 1
Wend
Define the UnboundReadData Event
Sub DBGrid1_UnboundReadData (ByVal RowBuf As RowBuffer, StartLocation
As Variant, ByVal ReadPriorRows as Boolean)
' ColumnName (ByVal Col As Integer) As String
' Value (ByVal Row As Long, ByVal Col As Integer) As Variant
RowBuf.Value(0, col) = data for 45th row
RowBuf.Value(1, col) = data for 44th row
RowBuf.Value(2, col) = data for 43rd row
RowBuf.Value(3, col) = data for 42nd row
RowBuf.Value(4, col) = data for 41st row
RowBuf.Value(0, col) = data for 47th row
RowBuf.Value(1, col) = data for 48th row
RowBuf.Value(2, col) = data for 49th row
RowBuf.Value(3, col) = data for 50th row
RowBuf.Value(4, col) = data for 51st row
RowBuf.RowCount = 10
RowBuf.ColumnCount = number of columns.
StartLocation = bookmark for the 3rd Row.
ReadPriorRows = False
RowBuf.Value(0,col) = data for the 4th row
RowBuf.Value(1,col) = data for the 5th row
...
RowBuf.Value(9,col) = data for the 13th row
RowBuf.RowCount is set = 10, since all 10 rows could be processed.
RowBuf.RowCount = 10
RowBuf.ColumnCount = number of columns.
StartLocation = bookmark for the 4th Row.
ReadPriorRows = True
RowBuf.Value(0,col) = data for the 3rd row
RowBuf.Value(1,col) = data for the 2nd row
RowBuf.Value(2,col) = data for the 1st row
RowBuf.Value(3,col) = data for the 0th row
If IsNull(StartLocation) Then
If ReadPriorRows Then
' StartLocation indicates EOF, because the grid is
' requesting data in rows prior, and prior rows only
' exist for EOF.
Else
' StartLocation indicates BOF, because the grid is
' requesting data in rows after, and rows after only
' exist for BOF.
Endif
Else
' StartLocation is an actual bookmark passed to the grid
' in the RowBuffer, an event argument (UnboundAddData) or
' the setting of a grid bookmark. It is up to the VB
' programmer to ensure the bookmark is valid, and to take
' the appropriate action if it is not.
End If
Private Sub DBGrid1_UnboundWriteData(ByVal RowBuf As RowBuffer,
WriteLocation As Variant)
' Assume that a Visual Basic for Applications function
' StoreUserData(bookm, col, value)
' takes a row bookmark, a column index, and a variant with
' the appropriate data to be stored in an array or database. The
' StoreUserData() function returns True if the data is acceptable and
' can be stored, False otherwise.
'
' Loop over all the columns of the row, storing non-Null values
For i% = 0 To RowBuf.ColumnCount - 1
If Not IsNull(RowBuf.Value(0, i%)) Then
If Not StoreUserData(WriteLocation, i%,
RowBuf.Value(0, i%)) Then
' storage of the data has failed. Fail the update
RowBuf.RowCount = 0 ' tell the grid the
' update failed
Exit Sub ' it failed, so exit the event
End If
End If
Next i%
Private Sub DBGrid1_UnboundAddData(ByVal RowBuf As RowBuffer,
NewRowBookmark As Variant)
' Assume that a Visual Basic for Applications function
' StoreUserData(bookm, col, value)
' takes a row bookmark, a column index, and a variant with the
' appropriate data to be stored in an array or database. The
' StoreUserData() function returns True if the data is acceptable and
' can be stored, False otherwise.
' First, get a bookmark for the new row. Do this with a Visual Basic for
' Applications function GetNewBookmark(), which allocates a new row of
' data in the storage media (array or database), and returns a
' variant containing a bookmark for that added row.
NewRowBookmark = GetNewBookmark()
' Loop over all the columns of the row, storing non-Null values
Dim newval as Variant
For i% = 0 To RowBuf.ColumnCount - 1
If Not IsNull(RowBuf.Value(0, i%)) Then
' A value is specified in the RowBuffer, so use it.
newval = RowBuf.Value(0, i%)
Else
' the RowBuf does not contain a value for this column.
' A default value should be set. A convenient value
' is the default value for the column.
newval = DBGrid1.Column(i%).DefaultValue
End If
' Now store the new value.
If Not StoreUserData(NewRowBookmark, i%, newval) Then
' storage of the data has failed. Delete the added row
' using a Visual Basic for Applications subroutine DeleteRow,
' which takes a bookmark as and argument. Also, fail the
' update by clearing the RowCount.
DeleteRow NewRowBookmark
RowBuf.RowCount = 0 ' tell the grid the update failed
Exit Sub ' it failed, so exit the event
End If
Next i%
Private Sub DBGrid1_UnboundDeleteRow(bookMark As Variant)
' changes current cell value in code
DataVal(DBGrid1.Row, DBGrid1.Col) = NewValue$
' Using the Refresh method to repaint the entire grid
DBGrid1.Refresh
Dim MaxCol As Integer 'Number of columns
Dim MaxRow As Long 'Number of rows
Dim GridArray() As Variant 'Place to store the data
Private Sub Form_Load()
' Declare grid data as global array in some global module
' Initialize array data in Main() or Form_Load()
MaxCol = 2
MaxRow = 3
ReDim GridArray(0 To MaxCol - 1, 0 To MaxRow - 1)
For i% = 0 To MaxCol - 1
For j% = 0 To MaxRow - 1
GridArray(i%, j%) = "Row" + Str$(j%) + ", Col" + Str$(i%)
Next j%
Next i%
' For the sake of efficiency, we use Column objects to
' reference column properties, instead of repeatedly going
' through the grid's Columns collection object.
Dim Col0, Col1 As Column
' Assuming the control name of the grid is DBGrid1, initialize
' grid properties in Form_Load():
' Assign the Column objects
Set Col0 = DBGrid1.Columns(0)
Set Col1 = DBGrid1.Columns(1)
' Define column heading text. This can be done in code at
' runtime or in the Columns property page at design time.
Col0.Caption = "Column 0"
Col1.Caption = "Column 1"
' Columns display widths (in container units)
Col0.Width = 1500
Col1.Width = 1500
' Column alignment Specify left, center, or right justified.
Col0.Alignment = 0 'Left
Col1.Alignment = 1 'Right
' Column Locking - specifies if a column is read-only (i.e.,
' user cannot edit that column).
Col0.Locked = False 'Column 0 is editable
Col1.Locked = True 'Column 1 is read-only
' Initialize current cell position to upper left corner:
DBGrid1.Row = 0
DBGrid1.Col = 0
End Sub
'
' Visual Basic for Applications support functions
'
' The first two functions below, MakeBookmark() and
' IndexFromBookmark are used by the remaining support
' functions only.
'
' The latter four Visual Basic for Applications support functions
' are used directly by the Unbound event procedures.
'
Private Function MakeBookmark(index As Long) As Variant
MakeBookmark = Str$(index)
End Function
Private Function IndexFromBookmark(bookm As Variant, ReadPriorRows As
Boolean) As Long
If IsNull(bookm) Then
If ReadPriorRows Then
IndexFromBookmark = MaxRow
Else
IndexFromBookmark = -1
End If
Else
Dim index As Long
index = Val(bookm)
If index < 0 Or index >= MaxRow Then index = -2000
IndexFromBookmark = index
End If
End Function
Private Function GetUserData(bookm As Variant, colm As Integer)_
As Variant
Dim index As Long
index = IndexFromBookmark(bookm, False)
If index < 0 Or index >= MaxRow Or colm < 0 Or colm >= MaxCol _
Then
GetUserData = Null
Else
GetUserData = GridArray(colm, index)
End If
End Function
Private Function StoreUserData(bookm As Variant, colm As _ Integer,
userval As Variant) As Boolean
Dim index As Long
index = IndexFromBookmark(bookm, False)
If index < 0 Or index >= MaxRow Or colm < 0 Or colm >= MaxCol _
Then
StoreUserData = False
Else
StoreUserData = True
GridArray(colm, index) = userval
End If
End Function
Private Function GetRelativeBookmark(bookm As Variant, relpos As
Integer) As Variant
Dim index As Long
index = IndexFromBookmark(bookm, False) + relpos
If index < 0 Or index >= MaxRow Then
GetRelativeBookmark = Null
Else
GetRelativeBookmark = MakeBookmark(index)
End If
End Function
Private Function GetNewBookmark() As Variant
ReDim Preserve GridArray(0 To MaxCol - 1, 0 To MaxRow)
GetNewBookmark = MakeBookmark(MaxRow)
MaxRow = MaxRow + 1
End Function
Private Function DeleteRow(bookm As Variant) As Boolean
Dim index As Long
index = IndexFromBookmark(bookm, False)
If index < 0 Or index >= MaxRow Then
DeleteRow = False
Exit Function
End If
MaxRow = MaxRow - 1
'Shift the data in the array
For i% = index To MaxRow - 1
For j% = 0 To MaxCol - 1
GridArray(j%, i%) = GridArray(j%, i% + 1)
Next j%
Next i%
ReDim Preserve GridArray(0 To MaxCol - 1, 0 To MaxRow - 1)
DeleteRow = True
End Function
'
' The Unbound Grid Events
'
' These events make calls to GetUserData(), StoreUserData(),
' GetRelativeBookmark, GetNewBookmark() and DeleteRow(),
' all of which are defined above. By replacing those routines
' with appropriate code, any Unbound grid application could
' be supported by the following Unbound event procedures.
'
Private Sub DBGrid1_UnboundReadData(ByVal RowBuf As RowBuffer, _
StartLocation As Variant, ByVal ReadPriorRows As Boolean)
Dim bookm As Variant
bookm = StartLocation
Dim relpos As Integer
If ReadPriorRows Then
' the grid is requesting data in rows prior to
' StartLocation
relpos = -1
Else
' the grid is requesting data in rows after to
' StartLocation
relpos = 1
End If
Dim rowsFetched As Integer
rowsFetched = 0
For i% = 0 To RowBuf.RowCount - 1
' Get the bookmark of the next available row
bookm = GetRelativeBookmark(bookm, relpos)
' If the next is BOF or EOF, then done
If IsNull(bookm) Then Exit For
For j% = 0 To RowBuf.ColumnCount - 1
RowBuf.Value(i%, j%) = GetUserData(bookm, j%)
Next j%
' Set the bookmark for the row
RowBuf.Bookmark(i%) = bookm
' Increment the count of fetched rows
rowsFetched = rowsFetched + 1
Next i%
' tell the grid how many rows were fetched
RowBuf.RowCount = rowsFetched
End Sub
Private Sub DBGrid1_UnboundWriteData(ByVal RowBuf As RowBuffer,
WriteLocation As Variant)
' Assume that a Visual Basic for Applications function
' StoreUserData(bookm, col, value)
' takes a row bookmark, a column index, and a variant with the
' appropriate data to be stored in an array or database. The
' returns True if the data is acceptable and can be stored,
' False otherwise.
' Loop over all the columns of the row, storing non-Null
' values
For i% = 0 To RowBuf.ColumnCount - 1
If Not IsNull(RowBuf.Value(0, i%)) Then
If Not StoreUserData(WriteLocation, i%, RowBuf.Value(0, i%))
Then
' storage of the data has failed. Fail the update
RowBuf.RowCount = 0 ' tell the grid the update
failed
Exit Sub ' it failed, so exit the event
End If
End If
Next i%
End Sub
Private Sub DBGrid1_UnboundAddData(ByVal RowBuf As RowBuffer,
NewRowBookmark As Variant)
' Assume that a Visual Basic for Applications function
' StoreUserData(bookm, col, value) takes a row bookmark,
' a column index, and a variant with the appropriate data to be
' stored in an array or database. The StoreUserData()function
' returns True if the data is acceptable and can be stored ,
' False otherwise.
' First, get a bookmark for the new row. Do this with a VB
' for Applications function GetNewBookmark(), which allocates
' a new row of data in the storage media (array or database),
' and returns a variant containing a bookmark for that added row.
NewRowBookmark = GetNewBookmark()
' Loop over all the columns of the row, storing non-Null
' values
Dim newval As Variant
For i% = 0 To RowBuf.ColumnCount - 1
newval = RowBuf.Value(0, i%)
If IsNull(newval) Then
' the RowBuf does not contain a value for this column.
' A default value should be set. A convenient value
' is the default value for the column.
newval = DBGrid1.Columns(i%).DefaultValue
End If
' Now store the new values.
If Not StoreUserData(NewRowBookmark, i%, newval) Then
' storage of the data has failed. Delete the added
' row using a Visual Basic for Applications function
'DeleteRow, which takes a bookmark as an argument.
' Also, fail the update by clearing the RowCount.
DeleteRow NewRowBookmark
RowBuf.RowCount = 0 ' tell the grid the update failed
Exit Sub ' it failed, so exit the event
End If
Next i%
End Sub
Private Sub DBGrid1_UnboundDeleteRow(Bookmark As Variant)
If Not DeleteRow(Bookmark) Then Bookmark = Null
End Sub
Additional query words:
Keywords : kbVBp400 IAPThird VB4WIN
Version : WINDOWS:4.0
Platform : WINDOWS
Issue type :
Last Reviewed: May 13, 1999