RLH*_*RLH 8 sorting ms-access crosstab ms-access-2010
我一直在对这个主题做一些研究,我似乎无法找到一个可行的解决方案,或者一个解释得足以让我实施的解决方案.
如果您曾在Access中创建交叉表查询,则您知道默认情况下,Access会按字母顺序对列进行排序.您可以通过转到" 属性"对话框并按照您喜欢的顺序输入列标题来更改此顺序.这是一个真正的痛苦,但是,因为在其他网站上提到的一个回答者,"这只是一个痛一次!"
嗯......如果您的列是动态的,那就不是这样.就我而言,我在表格上有第二列,其中包含我想要使用该字段进行排序的列标题.我想我可以追加我的排序列的细节,说明柱前端(已经提出的其他地方),但我不觉得这是解决问题的最优雅的方式.这尤其是一个问题,因为排序信息是系统数据,对交叉表的最终用户来说是无用的.
有谁知道这个问题的解决方案?如果是这样,您是否可以拼出对交叉表查询的动态列进行排序的步骤?
我认为这个问题在所有常用的Access版本(Access 2003+)中都是持久的,但为了防止它产生影响,我使用的是Access 2010.
UPDATE
这是一些非常简单的示例数据,可以帮助表达问题.我的实时场景周围还有一些其他的复杂性,但这个数据集肯定能够解决问题.
表#1
这是标题的来源.这Key是列顺序的排序,Descriptions是交叉表中的输出标题.
+---------+---------------------------------------+
| Key | Descriptions |
+---------+---------------------------------------+
| Kfsg2E | Hey, this is accounting code X! |
+---------+---------------------------------------+
| abR3 | This is yet another accounting code! |
+---------+---------------------------------------+
| Gruu! | Yet another accounting code |
+---------+---------------------------------------+
Run Code Online (Sandbox Code Playgroud)
表#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 |
+---------+---------+-------+
Run Code Online (Sandbox Code Playgroud)
交叉表结果 这些结果将导出到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 |
+---------+---------------------------------+--------------------------------------+-----------------------------+
Run Code Online (Sandbox Code Playgroud)
这就是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 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
Run Code Online (Sandbox Code Playgroud)
eea*_*rly 11
在不同时间遇到相同的场景后,我准备了一种可重复的方法来在PIVOT子句的末尾添加In列表.这样做将按照pivotfield 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
Run Code Online (Sandbox Code Playgroud)
在下面的屏幕截图中,请注意tblKeyDescriptions和tblPFValues.这些来自这个问题.qryCrosstab_Initial类似于上述问题中提供的查询.该表单用于运行该过程并打开前后查询.

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

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

这就是在交叉表查询中对列进行排序所需的全部内容.动态生成In列表是sub的目的.
注意:每次运行查询时都需要运行sub,因此使用诸如命令按钮On Click事件之类的事件将序列绑定在一起是有帮助的.