8

我一直在对这个主题进行一些研究,但似乎找不到可行的解决方案,或者一个解释得足够好让我实施的解决方案。

如果您曾经在 Access 中创建过交叉表查询,您就会知道默认情况下 Access 按字母顺序对列进行排序。您可以通过转到“属性”对话框并按照您喜欢的顺序输入列标题来更改此顺序。这是一个真正的痛苦,但正如另一个网站上的一位回答者所说,“这只是一次痛苦

好吧...如果您的列是动态的,则情况并非如此。就我而言,我在表格中有第二列,其中包含我想使用该字段进行排序的列标题。我想我可以将排序列的详细信息附加到描述列的前面(在其他地方已经建议),但我不认为这是解决问题的最优雅的方法。这尤其是一个问题,因为排序信息是系统数据,对交叉表的最终用户无用。

有谁知道这个问题的解决方案?如果是这样,您能否详细说明对交叉表查询的动态列进行排序的步骤?

我认为这个问题在所有常用的 Access 版本(Access 2003+)中都存在,但为了以防万一,我使用的是 Access 2010。


更新

这是一些非常简单的示例数据,有助于表达问题。在我的现场场景周围还有一些其他的复杂性,但这个数据集肯定能说明问题。

表#1 这是标题的来源。Key是列顺序的排序,是Descriptions交叉表中的输出标题。

+---------+---------------------------------------+
| Key     | Descriptions                          |
+---------+---------------------------------------+
| Kfsg2E  | Hey, this is accounting code X!       |
+---------+---------------------------------------+
| abR3    | This is yet another accounting code!  |
+---------+---------------------------------------+
| Gruu!   | Yet another accounting code           |
+---------+---------------------------------------+

表#2这是数据的存储 P_Key + F_Key是唯一的,这两个是表上的主键。

+---------+---------+-------+
| P_Key   | F_Key   | Value |
+---------+---------+-------+
| 1001    |Kfsg2E   | 1.0   |
+---------+---------+-------+
| 1001    |abR3     | 1.1   |
+---------+---------+-------+
| 1001    |Gruu!    | 1.2   |
+---------+---------+-------+
| 1002    |Kfsg2E   | 2.0   |
+---------+---------+-------+
| 1002    |abR3     | 2.1   |
+---------+---------+-------+
| 1002    |Gruu!    | 2.2   |
+---------+---------+-------+
| 2001    |Kfsg2E   | 3.0   |
+---------+---------+-------+
| 2001    |abR3     | 3.1   |
+---------+---------+-------+
| 2001    |Gruu!    | 3.2   |
+---------+---------+-------+

交叉表结果 这些被导出到 Excel 供用户更新。

+---------+---------------------------------+--------------------------------------+-----------------------------+
| P_Key   | Hey, this is accounting code X! | This is yet another accounting code! | Yet another accounting code |
+---------+---------------------------------+--------------------------------------+-----------------------------+
| 1001    | 1.0                             | 1.1                                  | 1.2                         |
+---------+---------------------------------+--------------------------------------+-----------------------------+
| 1001    | 2.0                             | 2.1                                  | 2.2                         |
+---------+---------------------------------+--------------------------------------+-----------------------------+
| 1001    | 3.0                             | 3.1                                  | 3.2                         |
+---------+---------------------------------+--------------------------------------+-----------------------------+

这就是 Access 对这些列进行排序的方式。但是,我需要它看起来像下表,它是根据 中的键排序的Table #1,而不是Description.

+---------+--------------------------------------+-----------------------------+---------------------------------+
| P_Key   | This is yet another accounting code! | Yet another accounting code | Hey, this is accounting code X! |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001    | 1.1                                  | 1.2                         | 1.0                             |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001    | 2.1                                  | 2.2                         | 2.0                             |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001    | 3.1                                  | 3.2                         | 3.0                             |
+---------+--------------------------------------+-----------------------------+---------------------------------+
4

3 回答 3

11

多次遇到相同的场景后,我准备了一种可重复的方式来将 In 列表添加到 PIVOT 子句的末尾。这样做将按照数据透视字段In 列表中元素的顺序对交叉表查询中的列进行排序。 此构造的文档可从 MSDN 获得。解决方案是需要由表单或其他事件上的命令按钮触发的过程。请查看 Sub 下方的屏幕截图。

Public Sub SortPivotColumns(querynameSource As String, queryname As String, SortName As String, SortColumnNameField As String, SortIndexName As String, NonPivotFieldCount As Integer, ParamArray ParamArr() As Variant)

' This sub goes through several steps to effectively adds an In list that sorts the 'Columns' of a crosstab query in MS Access
' 13 November 2012
' E Easterly
'
' This technique uses several components.
' 1) The original unmodified cross tab query (querynameSource)
' 2) The resulting, columns-have-been-sorted query (query)
' 3) An index table which has two columns, a numeric index used for sorting and the column name
' 4) A table or query that can be joined on the column names of the cross tab query to update the index table
'    The name of the table or query would be 'SortName'
'    The field in 'SortName' that the crosstab query columns are joined against is the 'SortColumnNameField'
'    The field in 'SortName' that has the desired order is the SortIndexName
' 5) A number which specifies the count of non-pivot/row heading columns (NonPivotFieldCount)
' 6) An optional array that contains any parameters needed for the query
'
'
'   USE:
'
'   SortPivotColumns "qryCrosstab_Initial", _
'                 "qryCrosstab_Sorted", _
'                 "tblKeyDescriptions", _
'                 "Descriptions", _
'                 "NumericIndexForSorting", _
'                  1
'
'
'
'
Dim rs As DAO.Recordset
Dim db As Database
Dim fld As DAO.Field
Dim sql As String
Dim ColumnHeading As Variant
Dim qdf As QueryDef
Dim qdfSRC As QueryDef
Dim UpdateIndexSQL As Variant

DoCmd.SetWarnings False 'Turn off warnings

Set db = CurrentDb

Set qdfSRC = db.QueryDefs(querynameSource)
Set qdf = db.QueryDefs(queryname)
qdf.sql = qdfSRC.sql

If Not (IsEmpty(ParamArr)) Then
    Dim i As Integer
    For i = 0 To UBound(ParamArr)
        qdf.Parameters(i) = ParamArr(i)
    Next
End If


' First, get the list of fields from the query

Set rs = qdf.OpenRecordset

' Then, create a temporary indexing table
If Not IsNull(DLookup("Name", "MSysObjects", "Name='ttblSortCrosstabColumns' And Type In (1,4,6)")) Then
    db.Execute "DROP TABLE ttblSortCrosstabColumns"
End If

db.Execute "CREATE TABLE ttblSortCrosstabColumns (FieldIndex INTEGER , ColumnName TEXT(250))"

' And populate it with the current index and column names from queryname
  For Each fld In rs.Fields
    If fld.OrdinalPosition > (NonPivotFieldCount - 1) Then
        DoCmd.RunSQL "Insert into ttblSortCrosstabColumns VALUES(" & fld.OrdinalPosition & ", """ & fld.Name & """)"
    End If
  Next fld
  Set fld = Nothing
  rs.Close
  Set rs = Nothing


' Now, the temporary table is joined with the sort table/query and the indexes are updated
UpdateIndexSQL = ("  UPDATE ttblSortCrosstabColumns " & _
                  "  INNER JOIN " & SortName & " ON ttblSortCrosstabColumns.ColumnName=" & SortName & "." & SortColumnNameField & _
                  "  Set ttblSortCrosstabColumns.FieldIndex = [" & SortIndexName & "]")
DoCmd.RunSQL (UpdateIndexSQL)


' Then, the column headings are added to a string to prepare the In list
sql = "SELECT ttblSortCrosstabColumns.ColumnName FROM ttblSortCrosstabColumns ORDER BY ttblSortCrosstabColumns.FieldIndex"
Set rs = db.OpenRecordset(sql)
    rs.MoveFirst
    ColumnHeading = "'" & rs.Fields(0).Value & "'"
    rs.MoveNext

    Do While Not rs.EOF
    ColumnHeading = ColumnHeading & ", '" & rs.Fields(0).Value & "'"
    rs.MoveNext
    Loop

rs.Close
Set rs = Nothing
' db.Execute "DROP TABLE ttblSortCrosstabColumns"

Dim cs As Variant

' Set qdf = db.QueryDefs(queryname)   ' may not need this

' The query is updated with the In list
cs = Left$(qdf.sql, Len(qdf.sql) - 3) & " In(" & ColumnHeading & ");"

qdf.sql = cs

' Take a look at the resulting query sql by uncommenting the below section
' Debug.Print cs


DoCmd.SetWarnings True  'Turn warnings back on

End Sub

在下面的屏幕截图中,请注意 tblKeyDescriptions 和 tblPFValues。这些来自问题。qryCrosstab_Initial 类似于上述问题中提供的查询。表单用于运行过程并打开前后查询。

屏幕截图 交叉表排序

一个整数字段 (NumericIndexForSorting) 被添加到 tblKeyDescriptions,因为 sub 需要一个数字索引来对列名进行排序。

带有数字索引的键描述表

现在,检查在初始查询和排序查询的 SQL 视图中突出显示的 In 列表。

PIVOT 子句中显示的 SQL 差异

这就是对交叉表查询中的列进行排序所需的全部内容。动态生成 In 列表是 sub 的目的。

注意:每次运行查询时都需要运行子程序,因此使用诸如命令按钮 On Click 事件之类的事件将序列绑定在一起会很有帮助。

于 2012-12-24T19:48:33.773 回答
1

这是使用一些 Access 和 Excel的不太完美的解决方案:

  1. 制作交叉表时,对列使用 Table1.Key。
  2. 在 Excel 文件中的新选项卡(称为“查找”?)上,制作 Table#1
  3. 在 Excel 文件的主选项卡的第一行(即粘贴数据集的位置),创建一堆 Vlookup() 公式来查看第 2 行并从查找表中提取正确的描述。
  4. 将数据集粘贴到第 2 行。结果将如下表所示,其中第一行实际上是一堆 Vlookup,它们提取了正确的列描述。
  5. 要求用户忽略或删除第 2 行。

我不知道你的脚本有多复杂,但如果这些数据是通过自动化粘贴到 Excel 文件中的,那么你可以隐藏第 2 行并跳过第 6 步。

P_Key 这又是一个会计代码! 另一个会计代码 嘿,这是会计代码X!
粘贴到这里 abR3 咕噜! Kfsg2E
1001 1.1 1.2 1.0
1001 2.1 2.2 2.0
1001 3.1 3.2 3.0
于 2012-12-13T17:22:36.880 回答
1

如果您知道查询的预期结果并且可以预测列数,那么对交叉表查询的结果进行排序的最简单方法是在属性表的列标题字段中指定正确的顺序。

访问列标题属性表

于 2018-12-28T15:53:10.870 回答