我有一个包含要完成的作业的表子表单。我正在VBA中创建一个算法,以最有效的顺序组织作业。
有没有办法在记录集中移动单个记录,还是我坚持使用OrderBy?
修改 为了增加一些清晰度,我希望能够将记录移动到同一个表中的任何其他索引。我打算运行我的算法,将记录移动到他们要完成的顺序。然后设置每个记录的“处理日期”字段以跟踪订单。
答案 0 :(得分:2)
简答题是“否”,记录集中记录的索引无法直接更新。只能通过设置不同的ORDER BY子句并重新查询数据库,或者通过设置Recordset.Sort属性或Form.OrderBy属性(绑定到表单时)来更改记录集中行的顺序。
假设有一个名为[JobOrder]的可更新记录集字段。 SQL源查询可以包含类似... ORDER BY [JobOrder] ASC
的排序顺序,它首先从数据库中检索数据时对数据进行排序。作为基本数据库概念的问题,应该假设如果没有指定ORDER BY子句,则数据库可以以随机顺序返回数据。 (实际情况通常不是这样。默认情况下,它会按一些索引的主键排序,但如果订单很重要则不应该假设。)
可以设置和更改表单(或子表单)的排序顺序,而无需再次从数据库中重新获取数据。这是通过设置OrderBy属性并确保OrderByOn = True
来完成的。 (仅供参考:除非您采取措施隐藏默认工具条(即工具栏)和快捷菜单,否则用户可以更改此排序顺序。)
现在,您的VBA代码可以使用各种技术来设置JobOrder值。您也许可以使用Me.RecordsetClone
方法使用记录集对象枚举和更新值。使用RecordsetClone将避免更新绑定主记录集的某些副作用。最后,以下假设所有记录都已具有有效的唯一JobOrder值,但它假定JobOrder不是 required 是唯一的(因为交换技术暂时将两行设置为相同的值)。您可以编写自己的聪明实现来保证JobOrder值保持有效且唯一。
Private Sub MoveCurrentUp()
Dim rs As Recordset2
Dim thisID As Long
Dim thisSort As Long
Dim previousID As Long
Dim previousSort As Long
On Error Resume Next
'* Error handling to avoid cases where recordset is empty
'* and/or the current record is not valid (i.e. new record)
If Not IsNull(Me.ID.Value) Then
thisID = Me.ID.Value
If Err.Number = 0 Then
On Error GoTo Catch
'* Any errors from this point should be
'* handled specifically rather than ignored
Set rs = Me.RecordsetClone
rs.FindFirst "ID=" & thisID
If Not rs.NoMatch Then
thisSort = rs!JobOrder
rs.MovePrevious
If Not rs.BOF Then
previousID = rs!ID
previousSort = rs!JobOrder
rs.Edit
rs!JobOrder = thisSort
rs.Update
rs.MoveNext
rs.Edit
rs!JobOrder = previousSort
rs.Update
Set rs = Nothing
RefreshSort
End If
End If
Set rs = Nothing
Debug.Print Me.Sort
End If
End If
Exit Sub
Catch:
MsgBox "Error updating order." & vbNewLine & vbNewLine & _
" " & Err.Number & ": " & Err.Description, vbOKOnly Or vbExclamation, "Error"
End Sub
Aferward,您可以使用以下内容刷新表单的排序顺序:
Private Sub RefreshSort(Optional restoreCurrentRecord As Boolean = True)
Dim rs As Recordset2
Dim saveID As Long
saveID = Me.ID.Value
Me.OrderBy = "[JobOrder] ASC"
Me.OrderByOn = True
If restoreCurrentRecord Then
Set rs = Me.RecordsetClone
rs.FindFirst "ID=" & saveID
If Not rs.NoMatch Then
Me.Bookmark = rs.Bookmark
End If
Set rs = Nothing
End If
End Sub
或者您可以使用SQL查询更新行,然后调用Me.OrderByOn = False
然后调用Me.Requery
以强制整个记录集以正确的顺序重新加载(假设记录源具有正确的ORDER BY子句)。这种技术的好处是可以将事务中的所有更改包装起来,这些更改可以完全提交或回滚,这是绑定表单的记录集对象无法做到的。