【问题标题】:Sort ADO Recordset Fields based on Custom Order根据自定义顺序对 ADO 记录集字段进行排序
【发布时间】:2021-11-21 13:44:32
【问题描述】:

我已经从工作表的范围创建了一个 ADO 记录集,如下所示,我想在 Groups 字段上自定义排序,然后在 Type 字段上进行自定义排序。排序顺序应该是,Groups 列的值应该按照另一个工作表范围列 Status1 中给出的自定义顺序排列,Type 列的值应该按照下面给出的自定义顺序排列另一个工作表范围列 Status2 例如:

+====+===========+================+
|    |     A     |       B        |
+====+===========+================+
| 1  | Type      | Groups         |
+----+-----------+----------------+
| 2  | Restage 2 | Target Group 6 |
+----+-----------+----------------+
| 3  | Restage 3 | Target Group 6 |
+----+-----------+----------------+
| 4  | Restage 1 | Target Group 6 |
+----+-----------+----------------+
| 5  | Current   | Target Group 6 |
+----+-----------+----------------+
| 6  | Restage 1 | Target Group 4 |
+----+-----------+----------------+
| 7  | Current   | Target Group 4 |
+----+-----------+----------------+
| 8  | Restage 2 | Target Group 4 |
+----+-----------+----------------+
| 9  | Restage 3 | Target Group 4 |
+----+-----------+----------------+
| 10 | Restage 3 | Target Group 2 |
+----+-----------+----------------+
| 11 | Restage 1 | Target Group 2 |
+----+-----------+----------------+
| 12 | Restage 2 | Target Group 2 |
+----+-----------+----------------+
| 13 | Current   | Target Group 2 |
+----+-----------+----------------+
| 14 | Current   | Non Buyers     |
+----+-----------+----------------+
| 15 | Restage 1 | Non Buyers     |
+----+-----------+----------------+
| 16 | Restage 3 | Non Buyers     |
+----+-----------+----------------+
| 17 | Restage 2 | Non Buyers     |
+----+-----------+----------------+
| 18 | Current   | GP             |
+----+-----------+----------------+
| 19 | Restage 3 | GP             |
+----+-----------+----------------+
| 20 | Restage 2 | GP             |
+----+-----------+----------------+
| 21 | Restage 1 | GP             |
+----+-----------+----------------+
| 22 | Restage 2 | Buyers         |
+----+-----------+----------------+
| 23 | Restage 1 | Buyers         |
+----+-----------+----------------+
| 24 | Current   | Buyers         |
+----+-----------+----------------+
| 25 | Restage 3 | Buyers         |
+====+===========+================+

喜欢这个:

+====+===========+================+
|    |     A     |       B        |
+====+===========+================+
| 1  | Type      | Groups         |
+----+-----------+----------------+
| 2  | Current   | GP             |
+----+-----------+----------------+
| 3  | Restage 1 | GP             |
+----+-----------+----------------+
| 4  | Restage 2 | GP             |
+----+-----------+----------------+
| 5  | Restage 3 | GP             |
+----+-----------+----------------+
| 6  | Current   | Buyers         |
+----+-----------+----------------+
| 7  | Restage 1 | Buyers         |
+----+-----------+----------------+
| 8  | Restage 2 | Buyers         |
+----+-----------+----------------+
| 9  | Restage 3 | Buyers         |
+----+-----------+----------------+
| 10 | Current   | Non Buyers     |
+----+-----------+----------------+
| 11 | Restage 1 | Non Buyers     |
+----+-----------+----------------+
| 12 | Restage 2 | Non Buyers     |
+----+-----------+----------------+
| 13 | Restage 3 | Non Buyers     |
+----+-----------+----------------+
| 14 | Current   | Target Group 2 |
+----+-----------+----------------+
| 15 | Restage 1 | Target Group 2 |
+----+-----------+----------------+
| 16 | Restage 2 | Target Group 2 |
+----+-----------+----------------+
| 17 | Restage 3 | Target Group 2 |
+----+-----------+----------------+
| 18 | Current   | Target Group 4 |
+----+-----------+----------------+
| 19 | Restage 1 | Target Group 4 |
+----+-----------+----------------+
| 20 | Restage 2 | Target Group 4 |
+----+-----------+----------------+
| 21 | Restage 3 | Target Group 4 |
+----+-----------+----------------+
| 22 | Current   | Target Group 6 |
+----+-----------+----------------+
| 23 | Restage 1 | Target Group 6 |
+----+-----------+----------------+
| 24 | Restage 2 | Target Group 6 |
+----+-----------+----------------+
| 25 | Restage 3 | Target Group 6 |
+====+===========+================+

两列的自定义顺序将从 2 个单列 Excel 范围(可以是 转换为数组)如下图:

状态1:

+===+================+
|   |       A        |
+===+================+
| 1 | GP             |
+---+----------------+
| 2 | Buyers         |
+---+----------------+
| 3 | Non Buyers     |
+---+----------------+
| 4 | Target Group 1 |
+---+----------------+
| 5 | Target Group 2 |
+---+----------------+
| 6 | Target Group 3 |
+---+----------------+
| 7 | Target Group 4 |
+---+----------------+
| 8 | Target Group 5 |
+---+----------------+
| 9 | Target Group 6 |
+===+================+

和:

状态2:

+====+============+
|    |     A      |
+====+============+
| 1  | Current    |
+----+------------+
| 2  | Restage 1  |
+----+------------+
| 3  | Restage 2  |
+----+------------+
| 4  | Restage 3  |
+----+------------+
| 5  | Restage 4  |
+----+------------+
| 6  | Restage 5  |
+----+------------+
| 7  | Restage 6  |
+----+------------+
| 8  | Restage 7  |
+----+------------+
| 9  | Restage 8  |
+----+------------+
| 10 | Restage 9  |
+----+------------+
| 11 | Restage 10 |
+====+============+

例如:

Set oRS = CreateObject("ADODB.Recordset")
....
With oRS
  .Sort = "Groups <customorder>,Types <customorder>"
End With

有谁知道如何使用 Recordset 对象进行自定义顺序排序?

编辑:

@CDP1802 感谢您的回复!它有效,但我忽略了一些我必须编辑我的帖子的东西。希望你能弄清楚如何处理它。

最初,基表中的 A.[Groups] 列是空白的,我正在根据另一列 [segment] 中的值在记录集中对其进行更新。所以排序完全错了!

这是代码的主要快照供您检查:

' Grab `Groups` Filters from Study Details
With shtStudyDetails
  xLastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
  If xLastRow <= 18 Then Exit Sub
  
  ' first check if `Assign` column has been filled in too
  Set xRg = .Range(.Cells(19, "B"), .Cells(xLastRow, "B"))
  If WorksheetFunction.CountA(xRg.Offset(0, 1).Cells) < WorksheetFunction.CountA(xRg.Cells) Then Exit Sub
  
  Set sRg = xRg.Resize(xRg.Rows.Count, 2)
  vArr = sRg.Value2
  
  ' Get Segment values excluding `Assign : Not Assigned`
  xStr = ""
  For j = 1 To UBound(vArr)
    If Not InStr(1, vArr(j, 2), "Not Assigned", vbTextCompare) > 0 Then xStr = xStr & "_" & j
  Next j
  If xStr = "" Then
    vIncludeArr = vArr
  Else
    vIncludeArr = Application.Index(vArr, Application.Transpose(Split(Mid(xStr, 2), "_")), Application.Transpose([row(1:2)]))
  End If
  If UBound(vIncludeArr) <= 1 And vIncludeArr(UBound(vIncludeArr), 1) = vbEmpty Then Exit Sub
    
  
  Set KeyValues1 = shtStudyDetails.Cells.Range("E45:F55") ' range1 table on whose values order to sort Groups
  Set KeyValues2 = shtStudyDetails.Cells.Range("G45:H106") ' range2 table on whose values order to sort Type

End With



With shtSummaryOfData
    xLastColumn = .Range("1:1").Cells(.Columns.Count).End(xlToLeft).Column
    If xLastColumn = 1 Then Exit Sub

    Set xRng = .Range(.Cells(1, 1), .Cells(1, xLastColumn))
    
    ' clear Summary of data sheet
    xLastRow = .Cells.SpecialCells(xlCellTypeLastCell).Row
    If xLastRow < 2 Then Exit Sub
    
    .Range(.Cells(2, 1), .Cells(xLastRow, xLastColumn)).ClearContents

    strSQL = ""
    xStr = ""
    strSQL = "SELECT "
    
    For Each xCell In xRng
      With xCell
          xStr = xCell.Value2
          If InStr(1, xStr, " ", vbTextCompare) > 0 Then xStr = WorksheetFunction.Substitute(xStr, " ", " ")
          If InStr(1, xStr, ".", vbTextCompare) > 0 Then xStr = WorksheetFunction.Substitute(xStr, ".", "#")
      End With
      strSQL = strSQL & "A.[" & xStr & "],"
      
    Next xCell

    strSQL = Left(strSQL, Len(strSQL) - 1)
    strSQL = strSQL & " FROM (([" & shtPasteData.Name & "$" & xRg.Address(False, False, xlA1) & "] AS A "
    
    strSQL = strSQL & " LEFT JOIN [" & shtStudyDetails.Name & "$" & KeyValues1.Address(False, False, xlA1) & "] AS G ON G.[Groups] = A.[Groups])"
    strSQL = strSQL & " LEFT JOIN [" & shtStudyDetails.Name & "$" & KeyValues2.Address(False, False, xlA1) & "] AS T ON T.[Type] = A.[Type])"
    
    ' Join Segments in `vIncludeArr` that did not have Assign:Not Assigned
    With Application
      xStr = "'" & Join(.Transpose(.Index(vIncludeArr, 0, 1)), "','") & "'"
    End With
    strSQL = strSQL & " WHERE A.[segment] IN (" & xStr & ")"
    
    strSQL = strSQL & " ORDER BY G.ITEM, T.ITEM "

End With


Set oCon = CreateObject("ADODB.Connection")
Set oRec = CreateObject("ADODB.Recordset")

With oCon
    .Mode = adModeReadWrite
    .CursorLocation = adUseClient
    .Open Join$(Array("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & _
    sPath$ & ";Extended Properties=""Excel 12.0 Xml; HDR=YES;IMEX=0"";"), vbNullString)
End With

With oRec
    .CursorLocation = adUseClient
    .CursorType = adOpenDynamic
    .LockType = adLockOptimistic
    Set .ActiveConnection = oCon
    .Open (strSQL)
    
    Set .ActiveConnection = Nothing
    
    ' updating Groups column based on values in `vIncludeArr`
    Do While Not .EOF
        For j = 1 To UBound(vIncludeArr, 1)
          If .Fields("segment").Value = vIncludeArr(j, 1) Then .Fields("Groups").Value = vIncludeArr(j, 2)
        Next j
      .MoveNext
    Loop
  
  .MoveLast
  .MoveFirst
'  .Sort = .Fields("Groups").Name & " ASC," & .Fields("Type").Name & " ASC"
  
  .MoveLast
  .MoveFirst
  shtSummaryOfData.Range("A2").CopyFromRecordset .DataSource
  .Close
End With

这里是唯一段表,它用于根据唯一段名称使用分配的组填充空白Groups 列:

╔══════════════════════╤════════════════╗
║ Segments             │ Assign Groups  ║
╠══════════════════════╪════════════════╣
║ ALL RESPONSES        │ GP             ║
╟──────────────────────┼────────────────╢
║ Some xx Target Group │ Target Group 1 ║
╟──────────────────────┼────────────────╢
║ Some Buyer1          │ Buyers         ║
╟──────────────────────┼────────────────╢
║ Some Non-Buyer1      │ Target Group 2 ║
╟──────────────────────┼────────────────╢
║ Some yy Target Group │ Target Group 3 ║
╟──────────────────────┼────────────────╢
║ Some zz Target Group │ Target Group 5 ║
╚══════════════════════╧════════════════╝

【问题讨论】:

  • 你应该在组和类型表中添加一个 ID,在你的 sql 语句中将它们加入到基表中,然后按它们的 ID 排序
  • 你能分享一个如何做的例子吗?我认为您的意思与recordset. Sort 无关,而是与SQL 查询本身有关。如何使用 2 个范围连接主查询?
  • .Range(.Cells(19, "B"), .Cells(xLastRow, "B")) 这个范围内是什么?
  • 这是另一个 2 列范围,在第一列中具有唯一的 [segment] 值,例如Some Buyer, 'Some Non-Buyer, Some Target 1, Some Target 2, Some Target 3` 等,其中可以使用下拉菜单在第二列中设置相应的 [Groups] 值,例如Some Buyer --> Buyers, Some Non-Buyer --> Non-Buyers, Some Target 1 --> Target Group 1 等等等等。所以第一列和第二列的值包含在 vIncludeArr 中在查询中过滤基表 A.[segment] 并更新记录集空白 [Groups] 列。
  • 更新帖子

标签: excel vba ado recordset custom-sort


【解决方案1】:

在 2 个自定义订单表中添加一个项目列,然后将它们连接到数据表并在排序顺序中使用项目字段。

Option Explicit

Sub test()

   Dim con As ADODB.Connection, sCon As String
   sCon = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
           "Data Source=" & ThisWorkbook.FullName & ";" & _
           "Extended Properties='Excel 12.0 Macro;HDR=YES';"

   Set con = New ADODB.Connection
   With con
      .ConnectionString = sCon
      .Open
   End With
   
   Const SQL = " SELECT A.Type, A.Groups FROM (([Sheet1$] AS A" & _
               " LEFT JOIN [Sheet2$] AS T ON T.Type   = A.Type)" & _
               " LEFT JOIN [Sheet3$] AS G ON G.Groups = A.Groups)" & _
               " ORDER BY G.Item, T.Item"
               
   With Sheet4
       .Cells.Clear
       .Range("A1").CopyFromRecordset con.Execute(SQL)
   End With
   
End Sub

【讨论】:

  • 我更新了我的帖子。我忽略了一些事情,因为排序没有正确发生。希望您能帮助弄清楚如何在 SQL 本身中执行此操作,而无需稍后求助于 updating Recordset 字段。
  • 这太棒了!感人的。小而干净的代码,但影响如此之大!非常感谢你。我还没有仔细阅读您编写的 SQL 查询,但我喜欢您的编码风格。再次非常感谢您! :)
猜你喜欢
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
相关资源
最近更新 更多