Is It possible to know indexes of all selected rows (without mouse properties)?
Printable View
Is It possible to know indexes of all selected rows (without mouse properties)?
Hi Krool,
Is there a way to disable horizontal scrolling of the VBFlexGrid? When I click on the last (right most) column it shifts my first column off the grid screen and displays a dark grey area as a next column that doesn't exist. Attached is how I would like to keep the grid positioned.
Attachment 179229
This is a bug. I see in the screen that you have the .ScrollBars property set to 'Vertical'.
In the normal MS(H)FlexGrid this will result that the LeftCol will not change upon mouse clicks and key movements. (Even not when changing by code - very strict therefore)
Currently the VBFlexGrid will behave always as if .ScrollBars is set to 'Both'.
I noted it down and will be fixed soon. Thanks!
EDIT:
Bugfix done. Small change done in the internal SetRowColParams method with a big effect. (marked as blue)
It's a very strict way of disabling it but it seems the MS(H)FlexGrid doing the same thing. (Not even allowing .LeftCol changed by code when .ScrollBars is set to 'Vertical' for instance)
Code:Private Sub SetRowColParams(ByRef RCP As TROWCOLPARAMS)
[...]
Select Case PropScrollBars
Case vbSBNone
If (.Mask And RCPM_TOPROW) = RCPM_TOPROW Then .Mask = .Mask And Not RCPM_TOPROW
If (.Mask And RCPM_LEFTCOL) = RCPM_LEFTCOL Then .Mask = .Mask And Not RCPM_LEFTCOL
Case vbHorizontal
If (.Mask And RCPM_TOPROW) = RCPM_TOPROW Then .Mask = .Mask And Not RCPM_TOPROW
Case vbVertical
If (.Mask And RCPM_LEFTCOL) = RCPM_LEFTCOL Then .Mask = .Mask And Not RCPM_LEFTCOL
End Select
[...]
Update related to yesterday's bugfix.
Included new flags RCPF_FORCETOPROWMASK and RCPF_FORCELEFTCOLMASK which is used in the internal SetRowColParams method.
This way there is a internal way of forcing a scroll, even if there is no scrollbar. (of course the 'Scroll' event will not be fired as no scrollbar exist)Code:Private Sub SetRowColParams(ByRef RCP As TROWCOLPARAMS)
[...]
Select Case PropScrollBars
Case vbSBNone
If Not (.Flags And RCPF_FORCETOPROWMASK) = RCPF_FORCETOPROWMASK Then
If (.Mask And RCPM_TOPROW) = RCPM_TOPROW Then .Mask = .Mask And Not RCPM_TOPROW
End If
If Not (.Flags And RCPF_FORCELEFTCOLMASK) = RCPF_FORCELEFTCOLMASK Then
If (.Mask And RCPM_LEFTCOL) = RCPM_LEFTCOL Then .Mask = .Mask And Not RCPM_LEFTCOL
End If
Case vbHorizontal
If Not (.Flags And RCPF_FORCETOPROWMASK) = RCPF_FORCETOPROWMASK Then
If (.Mask And RCPM_TOPROW) = RCPM_TOPROW Then .Mask = .Mask And Not RCPM_TOPROW
End If
Case vbVertical
If Not (.Flags And RCPF_FORCELEFTCOLMASK) = RCPF_FORCELEFTCOLMASK Then
If (.Mask And RCPM_LEFTCOL) = RCPM_LEFTCOL Then .Mask = .Mask And Not RCPM_LEFTCOL
End If
End Select
[...]
Reason for such a forcing is that when changing the Rows/Cols property and the current TopRow/LeftCol is > Rows/Cols and the scrollbar do not exist accordingly then no cells are visible anymore (only fixed cells)
The MS(H)FlexGrid behaves in this way to "scroll" so that at least one row/column is shown. (even if there is no scrollbar)
Therefore such flags are now used in the Rows/Cols property.
Who knows, maybe somebody finds out that another property also needs such exception. Then the flag is already available and easy fix-able.
Attachment 179260
Sorry:
Compile Error
Subroutine or function is not defined
Use Set VBFlexGrid1.DataSource = rst
Must use assignment code: ColKey(i) = strKey,
Otherwise, an error will be prompted: Invalid col Value
Is my usage method wrong?
Test1:Code:Option Explicit
Public Cnn As New ADODB.Connection
Private Sub Form_Load()
Dim i As Long
Dim strSQL As String
Dim strKey As String
Dim rst As ADODB.Recordset
OpenConn App.Path & "\Data.mdb"
strSQL = "SELECT * FROM Sys_tblUsers"
Set rst = GetRs(strSQL)
Set VBFlexGrid1.DataSource = rst
Set rst = GetRs(strSQL)
i = VBFlexGrid1.Cols - 1
With VBFlexGrid1
For i = 0 To i - 1
strKey = rst.Fields(i).Name
' .ColKey(i) = strKey'Invalid col Value
Debug.Print "VBFlexGrid2 i=" & i & " = " & .ColKey(.ColIndex(strKey)); ""
Next
End With
End Sub
Public Sub OpenConn(mdbFileName As String)
Cnn.CursorLocation = adUseClient
Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & mdbFileName
End Sub
Public Function GetRs(Query As String) As ADODB.Recordset
Set GetRs = New ADODB.Recordset
GetRs.Open Query, Cnn, adOpenStatic, adLockOptimistic
End Function
Attachment 179262
Test2:
Attachment 179263
Test3:
Attachment 179261
Demo File:
Attachment 179264
Code:Public Property Set DataSource(ByVal Value As MSDATASRC.DataSource)
Set PropDataSource = Value
If VBFlexGridDesignMode = False Then
If Not PropDataSource Is Nothing Then
If PropRecordset Is Nothing Then Set PropRecordset = CreateObject("ADODB.Recordset")
With PropRecordset
If .State <> 0 Then .Close
If StrPtr(PropDataMember) = 0 Then .DataMember = "" Else .DataMember = PropDataMember
Set .DataSource = PropDataSource
If .State <> 0 Then
If .RecordCount > -1 Then ' The cursor type of the Recordset affects whether the number of records can be determined.
Me.Rows = PropFixedRows + .RecordCount
Me.Cols = PropFixedCols + .Fields.Count
Dim iRow As Long, iCol As Long
If PropFixedRows > 0 Then
For iCol = 0 To (.Fields.Count - 1)
Me.TextMatrix(0, iCol + PropFixedCols) = .Fields(iCol).Name
'''''''''''''''''''''''''Add'''''''''''''''''''''''''''''''''''
VBFlexGridColsInfo(iCol + PropFixedCols).Key = .Fields(iCol).Name
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Next iCol
End If
If .RecordCount > 0 Then
Dim ArrRows As Variant
ArrRows = .GetRows(, 1) ' adBookmarkFirst
Dim LBoundCols As Long, UBoundCols As Long
LBoundCols = LBound(ArrRows, 1)
UBoundCols = UBound(ArrRows, 1)
Dim LBoundRows As Long, UBoundRows As Long
LBoundRows = LBound(ArrRows, 2)
UBoundRows = UBound(ArrRows, 2)
For iRow = LBoundRows To UBoundRows
For iCol = LBoundCols To UBoundCols
If Not IsNull(ArrRows(iCol, iRow)) Then
Me.TextMatrix((iRow + (0 - LBoundRows)) + PropFixedRows, (iCol + (0 - LBoundCols)) + PropFixedCols) = ArrRows(iCol, iRow)
Else
Me.TextMatrix((iRow + (0 - LBoundRows)) + PropFixedRows, (iCol + (0 - LBoundCols)) + PropFixedCols) = vbNullString
End If
Next iCol
Next iRow
End If
End If
End If
End With
Else
Set PropRecordset = Nothing
End If
End If
UserControl.PropertyChanged "DataSource"
End Property
When you use .ColIndex and did not assign .ColKey before then you get the error.
Your Test 2 is the correct approach.
Test 3 is also ok. But on each update you need to keep your changes in mind.
thank you very much
VSFLEXGRID.ocx defaults to the TEST3 scheme.
Is MSFLEXGRID.ocx the TEST2 solution by default?
If the TEST3 scheme is used by default in the project, will there be any incompatibility with MSFLEXGRID.ocx?
If there is no compatibility problem, then using the Test3 solution in the project should be easier and more convenient to use.
Krool, thank you very much
If it can be updated to the project, it will be more convenient to use.
Add VSFlexGrid1 Test:
Attachment 179273
Code:Option Explicit
Public Cnn As New ADODB.Connection
Private Sub Form_Load()
Dim i As Long
Dim strSQL As String
Dim strKey As String
Dim rst As ADODB.Recordset
OpenConn App.Path & "\Data.mdb"
strSQL = "SELECT * FROM Sys_tblUsers"
Set rst = GetRs(strSQL)
Set VBFlexGrid1.DataSource = rst
i = VBFlexGrid1.Cols - 1
With VBFlexGrid1
For i = 0 To i - 1
strKey = rst.Fields(i).Name
.ColKey(i) = strKey 'VBFlexGrid2
Debug.Print "VBFlexGrid2 i=" & i & " = " & .ColKey(.ColIndex(strKey)); ""
Next
End With
''''''''''''Add New VSFlexGrid1 Test ''''
Set VSFlexGrid1.DataSource = rst '
i = VSFlexGrid1.Cols - 1
With VSFlexGrid1
For i = 0 To i - 1
strKey = rst.Fields(i).Name
''' .ColKey(i) = strKey '''VSFlexGrid1 No need for this line of code
Debug.Print "VSFlexGrid1 i=" & i & " = " & .ColKey(.ColIndex(strKey)); ""
Next
End With
End Sub
Attachment 179272
A bit late, but just stumbled over it (post #336 and following ones, about Sorting Data in the VBFlex)
That's possible, by using the Sort-Property of the (bound) SQLite-Rs ... in the same way as with ADO-Rs
This way one can avoid additional roundtrips over the DB (or the DB-Server) just for ordering-purposes.
To be able to reach the Sort-Property (behind your Binding-Class), one can simply expose the internal mRs via a Property Get:
A "sort-switching by ColumnName" would then be possible in the Form-Code via a Helper like the one below:Code:Option Explicit
Implements IVBFlexDataSource
Private mRs As cRecordset
'a Public Method, to allow Binding to an outside DataSource (in this case an SQLite-cRecordset)
Public Function BindTo(Rs As cRecordset) As IVBFlexDataSource
Set mRs = Rs
Set BindTo = Me 'return a reference of our Class-instance to the outside
End Function
Public Property Get Rs() As cRecordset 'expose mRs to the outside
Set Rs = mRs
End Property
'*** Ok, finally the 5 method Implementations of IVBFlexDataSource
Private Function IVBFlexDataSource_GetFieldCount() As Long
IVBFlexDataSource_GetFieldCount = mRs.Fields.Count
End Function
Private Function IVBFlexDataSource_GetFieldName(ByVal Field As Long) As String
IVBFlexDataSource_GetFieldName = mRs(Field).Name
End Function
Private Function IVBFlexDataSource_GetRecordCount() As Long
IVBFlexDataSource_GetRecordCount = mRs.RecordCount
End Function
Private Function IVBFlexDataSource_GetData(ByVal Field As Long, ByVal Record As Long) As String
If Record < mRs.RecordCount Then IVBFlexDataSource_GetData = mRs.ValueMatrix(Record, Field)
End Function
Private Sub IVBFlexDataSource_SetData(ByVal Field As Long, ByVal Record As Long, ByVal NewData As String)
If Record < mRs.RecordCount Then mRs.ValueMatrix(Record, Field) = NewData
End Sub
(passing an empty String, to restore the original Sort-Order, as it was coming from the DB-Select)
HTHCode:Private Sub SwitchSorting(FieldName As String, Optional ByVal Descending As Boolean)
myDataSource.Rs.Sort = FieldName & IIf(Descending, " Desc", "")
myVBFlexGrid.Refresh
End Sub
Olaf
Done. :)
The blue marked code was now inserted into the DataSource property.
Code:If PropFixedRows > 0 Then
For iCol = 0 To (PropFixedCols - 1)
VBFlexGridColsInfo(iCol).Key = vbNullString
Next iCol
For iCol = 0 To (.Fields.Count - 1)
Me.TextMatrix(0, iCol + PropFixedCols) = .Fields(iCol).Name
VBFlexGridColsInfo(iCol + PropFixedCols).Key = .Fields(iCol).Name
Next iCol
End If
Krool,
Thanks for the fix for horizontal scrolling!
Hating to add a question given your substantial contributions already made, but my search through the thread did not yield an answer. In short, is there a way to land on a cell that has been set as a dropdown combo and have it not drop the list, just shot the text and the button. (We are hoping to use this as a container for editable fields of a variety of different types. Thanks!
Don
To avoid the "flash" catch the "EditSetupWindow" event and set the .ComboButtonValue to 'FlexComboButtonValueDisabled'.
This will avoid that the drop-down list will be shown initially. Then at the "EnterEdit" event change the .ComboButtonValue property back to 'FlexComboButtonValueUnpressed'.
Thanks again. That did the trick. I am now struggling with capturing text during editing. For background, I am implementing a migration from a very old control (Protoview DataTable) to VBFlexGrid. So far, things are going well. However, we require a bit of key press trapping for a numeric properties check on data entry, such as restricting only numbers, decimals, and math operators (for an inline equation editor). This works great for all of our other controls, but the behavior in VBFlexGrid is not allowing me to do this, so I am hoping that you can provide a little advice. Here is a typical scenario:
We are calling the checking function in Grid_EditKeyPress and are getting the correct key. However, if you select an entire editable text field (say that was originally "0000") then typed the number two, the Text property is still "0000" but the EditSelStart and EditSelLength are both zero at that point. I would have assumed that the Text would either be null at that point or the Sel properties would indicate zero and four for the selected text that was being over-written. Also, I see no way to identify the cursor position at the point of EditKeyPress, which I could then use to work around the above.
Thx.
Just replaced Text with EditText and it looks like things are back on track! I cannot do any debugging within the IDE (per the comments above), but given that the function was already fully worked out for the other controls with luck we won't need to do any. Thanks!
Hi,Krool:
is there a simple way to add a Checkbox or DTpicker to the VBFlexGrid just like this
Attachment 179753
Hi, Krool:
how about to add some methods like MSHFlexgrid which can Expand or Collapse it's Items
Attachment 179768
Attachment 179769
this attachment didn't have the "NotrhWind.mdb" file you can download it from "http://down2.opdown.com:8019/opdown/northwind.mdb.zip"
Dear Krool,
Thanks a TON, as ever, for your wonderful contributions to the society.
Well, you have written as follows in your above quoted post (Dt. Nov 14th, 2020)
// This way there is a internal way of forcing a scroll, even if there is no scrollbar. (of course the 'Scroll' event will not be fired as no scrollbar exist) //
But then Krool, I did not know how to force the scroll by studying your code. Can you kindly show me an example code snippet please, to force a scroll, even if there there are no visible scrollbars (both vertical and horizontal).
Basically, I wish to allow my users to use the mouse to scroll up and down the VBFlexgrid, fully, even when the 'ScrollBars' property is set to vbSBNone(0) in the 'Properties' sheet. Actually I achieved this by writing suitable code (under Case WM_MOUSEWHEEL) in the WindowProcControl function of the FlexGrid control and it works well too but what you have written seems to suggest a very simple and straightforward method. So, kindly let me know how to effect the same. Thanks in advance.
Prayers and Kind Regards.
Update released.
Bugfix in the Rows/Cols/FixedRows/FixedCols property.
The effect is mostly when having the ScrollBars property set to 0 - None.
FixedRows/FixedCols need the RCPF_FORCETOPROWMASK/RCPF_FORCELEFTCOLMASK flag due to the 13-Nov-2020 update.
The other flag RCPF_FORCEREDRAW existed already before and is now applied to those properties to "ensure" redrawing.
Is VBFlexGrid Control - .Net upgraded version available ?
(Or is there any other .net version like grid without any events).
We are trying to inherit grid into our class to store data.
Hello
I would like to know if there a way i can change the Height the VBFlexGrid Control rows without increasing the font size
thanks
Nice job man thank you
Hi krool
Is it possible to auto adjust the row height depending on the content of the cell?
thank you
I love it when somebody wants to be spoon-feeded.
I don't know what you exactly need. So below some possible scenarios.
1. Only single row auto-size. In this example row #5
2. All scrollable rows. (two methods)Code:VBFlexGrid1.AutoSize 5, , FlexAutoSizeModeRowHeight
either
orCode:VBFlexGrid1.AutoSize VBFlexGrid1.FixedRows, VBFlexGrid1.Rows - 1, FlexAutoSizeModeRowHeight
3. All rowsCode:VBFlexGrid1.AutoSize 0, VBFlexGrid1.Rows - 1, FlexAutoSizeModeRowHeight, FlexAutoSizeScopeScrollable
EDIT:Code:VBFlexGrid1.AutoSize 0, VBFlexGrid1.Rows - 1, FlexAutoSizeModeRowHeight
Sometimes a grid is filtered using the RowHidden() function. You can exclude the hidden rows in the auto-sizing as well.
Example:
Code:VBFlexGrid1.AutoSize 0, VBFlexGrid1.Rows - 1, FlexAutoSizeModeRowHeight, ExcludeHidden:=True
thank you Krool
Please excuse my ignorance
I tested all methods but unfortunately no success. Perhaps because I'm not using the last version.
This method is throwing Mismatch error.Code:VBFlexGrid1.AutoSize 0, VBFlexGrid1.Rows - 1, FlexAutoSizeModeRowHeight, FlexAutoSizeScopeScrollable
Besides I'm not using any RowHidden() function.
In fact what I'm asking about is something like this:
Attachment 180329
Attachment 180330
@Krool (regarding AutoSize)
It might be worth mentioning, that samer22 is probably using your Grid in bound mode
(via IVBFlexDataSource).
On my system, when I use such a Binding - and then call AutoSize in this way (for Col-Autosizing, after setting the Binding):
FG.AutoSize 0, FG.Cols - 1, FlexAutoSizeModeColWidth, FlexAutoSizeScopeAll
It seems to use the right "internal Measurement-Texts" only for the Header-Row
(probably because it did buffer these texts internally already, after retrieving them via IVBFlexDataSource_GetFieldName).
The "CellTexts below the Header" (corresponding with IVBFlexDataSource_GetData) -
are apparently not requested when it comes to further Text-measurings "down the lines".
On another note (not really related to the IVBFlexDataSource-problems above)...
Is it intentional, that an AutoSize-Call like:
FG.AutoSize 0 'which leaves the second optional Param at -1
currently does have the same effect as: FG.AutoSize 0, 0
I'm aware that this is probably meant to work this way (to affect only a single column).
What "threw me off" is the "-1" in the optional second param, which usually means "all of them".
so, the behaviour I expected, leaving the second param out, was: FG.AutoSize 0, FG.Cols - 1
Olaf