|
楼主 |
发表于 2019-1-1 00:02
|
显示全部楼层
2.11 拖曳行列、排序和滚动条提示
DragRow方法以编程方式启用拖动行操作(下面介绍的ExplorerBar属性也可拖动行,且无需使用代码)。然后,用户可以将该行移动到一个新的位置,之后将收到BeforeMoveRow和AfterMoveRow事件通知。该方法返回行的新位置。其语法为:
[form!]VSFlexGrid.DragRow Row As Long
下面的代码在用户单击鼠标右键时启用拖动行操作。代码通过设置背景颜色来突出显示正在拖动的行,并在拖动过程结束后恢复背景色:
Private Sub fg_BeforeMouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single, Cancel As Boolean)
With fg
If Button = 2 Then
Cancel = True
Dim r%
r = .Row
.Cell(flexcpBackColor, r, 1, r, .Cols - 1) = vbRed
r = .DragRow(r)
.Cell(flexcpCustomFormat, r, 1, r, .Cols - 1) = False
Debug.Print "Dragged to "; r
End If
End With
End Sub
要拖曳列的位置,需要使用ExplorerBar属性,该属性返回或设置列标题是否用于排序或移动列。
ExplorerBar属性允许用户使用列标题在无需任何代码的情况下对列进行排序和移动。以下是其有效设置的描述:
表13
注意,这些值是二进制位的组合,可用Or操作符进行组合设置。例如要运行排序、移动行和移动列,可以这样设置:
fg.ExplorerBar = flexExMoveRows Or flexExSortShowAndMove.
需要注意的是,必须具有至少一行固定行才能够使用ExplorerBar移动和排序列的功能,并且至少有一列固定列才能够使用移动行的功能,且每次只能移动一行或一列。还要注意的是,如果使用ExplorerBar移动行,将不能同时使用固定列来选择整行,只能通过选择可滚动列的单元格实现选择多行。
排序的时候要注意每列的数据类型,我在2.1节已经说过,这里再次说一下。绑定数据到数据库的网格,无需指定每列的数据类型,如果不是绑定模式,默认按照字符串排序,数字、日期很可能无法正确排序,这时需要指定需要排序列的数据类型。
在2.3节还讲过用Cell属性排序,只要在网格单击事件中加一句代码,选择网格的任意区域都会排序,在需要为局部行区域排序时是很有用的:
fg.Cell(flexcpSort, fg.Row, fg.Col, fg.RowSel, fg.ColSel) = 1'升序
点击ExplorerBar一次只能对一列排序, Cell属性也差不多,只对当前单元格所在列排序。这往往无法满足排序需求,这个时候就需要使用Sort属性了。
Sort属性使用所选列作为键设置所选行的排序顺序。Sort属性允许根据一个或多个列中的值按升序或降序对一个区域或行区域进行排序。要排序的行的范围是通过设置Row和RowSel属性指定的。如果Row和RowSel相同,则该控件对所有非固定行进行排序。用于排序的键由Col和ColSel属性决定,总是从左到右。例如,如果Col=3和ColSel=1,也是根据列1、列2、列3的内容进行排序。这个规定挺坑爹的,规避该设置的唯一的办法就是每次只排序一列,先把最不重要的排序,然后把最重要的列排在最后,跟Excel中的Sort排序一样。我们知道,Excel中每次只能指定3个关键字列,要多个列排序,只能按列的重要性依次降低进行多次使用Sort。
VSFlexGrid控件使用的排序算法是稳定算法:这意味着当排序键相同时,排序保持记录的相对顺序。Sort属性的有效设置描述如下:
表14
flexSortCustom是最灵活的设置。它触发一个Compare事件,允许您以任何方式比较行,以任何顺序使用任何列。但是,它也比其他的慢得多,所以只有在真正需要的时候或者网格只有少量行时才应该使用它。要排序日期,请确保包含日期的列将其ColDataType属性设置为flexDTDate(7)。
假如我们设计一个窗体用来做排序设置,这样每次都可以方便的按任意列排序了。新建窗体要获取要排序的列和列的重要性,还要获取排序设置的值。注意ColComboLis属性的设置进行了转换,因为Sort属性接收的字符串常数是数字不是字符串。网格控件剪贴字符串的列默认分隔符为Chr(9),行默认分隔符为Chr(13),我们不修改分隔符属性。新建窗体中代码如下:
Private Sub CommandButton1_Click() '取消排序
Unload Me
End Sub
Private Sub CommandButton2_Click() '确定排序
With fg
For i = .Rows - 1 To .FixedRows Step -1
If .Cell(flexcpChecked, i, 1) = flexChecked Then
If .Cell(flexcpTextDisplay, i, 2) <> "flexSortNone" Then
s = s & Chr(13) & .Cell(flexcpText, i, 1, i, 2)
End If
End If
Next
End With
UserForm1.SortSettings = Mid(s, 2)
Unload Me
End Sub
Private Sub UserForm_Initialize()
With UserForm1.fg
fg.Rows = .Cols - .FixedCols + 1
fg.Cols = 3
fg.TextMatrix(0, 1) = "排序字段"
fg.TextMatrix(0, 2) = "排序顺序"
For i = .FixedCols To .Cols - 1
j = j + 1
fg.TextMatrix(j, 1) = .TextMatrix(.FixedRows - 1, i)
Next
fg.Cell(flexcpText, 1, 2, fg.Rows - 1, 2) = "flexSortNone"
fg.ColAlignment(-1) = flexAlignCenterCenter
fg.Cell(flexcpChecked, 1, 1, fg.Rows - 1, 1) = flexUnchecked
fg.Cell(flexcpPictureAlignment, 1, 1, fg.Rows - 1, 1) = flexAlignRightCenter
fg.ColComboList(2) = "#0;flexSortNone|#1;flexSortGenericAscending|#2;flexSortGenericDescending|#3;flexSortNumericAscending|" & _
"#4;flexSortNumericDescending|#5;flexSortStringNoCaseAscending|#6;flexSortStringNoCaseDescending|" & _
"#7;flexSortStringAscending|#8;FlexSortStringDescending"
fg.Editable = flexEDKbdMouse
fg.SelectionMode = flexSelectionByRow
fg.AllowSelection = False
fg.ExplorerBar = flexExMoveRows
fg.AutoSize 0, 1
fg.ExtendLastCol = True
End With
Me.Caption = "排序设置"
End Sub
在主窗体中定义一个排序的子过程即可:
Private Sub gridsort(ByVal s As String)
With fg
If Len(s) = 0 Then Exit Sub '没有设置排序参数退出
If .Rows = .FixedRows Then Exit Sub '没有数据退出
For Each c In Split(s, Chr(13))
.Row = 1
a = Split(c, Chr(9))
.Col = .ColIndex(a(0))
.Sort = a(1)
Next
End With
End Sub
如果网格绑定数据库,排序就不需要自己写代码了,可直接在数据集中排序。下面简单介绍一下记录集的Sort属性:
Sort属性指示一个或多个作为 Recordset 排序基准的字段名,并指示按升序还是降序对每个字段进行排序。
设置和返回值
设置或返回 String 值,指示要作为 Recordset 排序基准的字段名称。每个名称均由逗号隔开,(可选)后面跟空格和关键字 ASC(按升序对字段进行排序)或 DESC(按降序对字段进行排序)。如果未指定关键字,默认情况下将按升序对字段进行排序。
说明一点,Sort属性要求将 CursorLocation 属性设置为 adUseClient。如果索引已不存在,则将为 Sort 属性中指定的每个字段创建临时索引。由于并没有对数据进行物理上的重新排列,因此排序操作仍有效,只不过是按索引指定的顺序进行访问。将 Sort 属性设置为空字符串将会把行重置为原始顺序并删除临时索引。现有的索引不会被删除。
上例中,假设我们按OrderID降序排序,ProductID升序排序,可以将 Sort 属性设置为字符串“OrderID DESC, ProductID ASC”,其他字段会被忽略。如果绑定模式为非零值,网格控件会自动刷新数据,不然请用DataRefresh方法刷新。
不能将字段命名为“ASC”或“DESC”,因为这些名称与关键字 ASC 和 DESC 相冲突。请使用返回 Recordset 的查询中的 AS 关键字来为有名称冲突的字段设置别名。
在滚动垂直滚动条的时候,可以显示提示信息,比如想显示放开滚动条之后,网格最上一行的行内容,可以这样写:
Private Sub fg_BeforeScrollTip(ByVal Row As Long)
fg.ScrollTipText = "顶行OrderID:" & fg.TextMatrix(Row, 1)
End Sub
图15
|
|