我一直在对这个主题进行一些研究,我似乎无法找到一个可行的解决方案,或者一个解释得足以让我实施的解决方案。
如果您曾在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 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
答案 0 :(得分:11)
在不同时间遇到相同的场景后,我准备了一种可重复的方法,将In列表添加到PIVOT子句的末尾。这样做将按照 pivotfield In列表中元素的顺序对交叉表查询中的列进行排序。 Documentation for this construct is available from 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列表。
这是在交叉表查询中对列进行排序所需的全部内容。动态生成In列表是sub的目的。
注意:每次运行查询时都需要运行sub,因此使用诸如命令按钮On Click事件之类的事件将序列绑定在一起是有帮助的。
答案 1 :(得分:1)
这是 不完美的 解决方案,它使用了一些Access& amp; Excel中:
我不知道您的脚本有多复杂,但如果这些数据通过自动化粘贴到Excel文件中,那么您只需隐藏第2行并跳过第6步。
+---------+--------------------------------------+-----------------------------+---------------------------------+
| P_Key | This is yet another accounting code! | Yet another accounting code | Hey, this is accounting code X! |
+---------+--------------------------------------+-----------------------------+---------------------------------+
|PasteHere| abR3 | Gruu! | Kfsg2E |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001 | 1.1 | 1.2 | 1.0 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001 | 2.1 | 2.2 | 2.0 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
| 1001 | 3.1 | 3.2 | 3.0 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
答案 2 :(得分:0)
我只是在解决这个问题。虽然提供的解决方案有效(根据描述),另一种可能的解决方案是动态创建查询 - def(如在所描述的解决方案中),但不是改变查询的SQL,只需填写查询的列标题属性动态生成的列标题字符串。 OP已经提到了列标题的工作原理,但没有提及 这似乎更容易实现,只涉及一些vba来枚举字符串中的可能值并设置属性
所以我要尝试一下,看看它是否有效
嗯....结果是列标题不是querydef的实际属性,但它会自动放入SQL中。
我以为我有一个光明的时刻;)
答案 3 :(得分:0)
如果您知道查询的预期结果并且可以预测列数,则对交叉表查询的结果进行排序的最简单方法是在属性表的“列标题”字段中指定正确的顺序。