Как я могу сортировать столбцы в запросе перекрестной таблицы, когда данные столбца являются динамическими?
я провел небольшое исследование по этой теме, и я не могу найти ни работоспособного решения, ни того, которое объяснено достаточно хорошо для меня, чтобы реализовать.
если вы когда-либо создавали перекрестный запрос в Access, вы знаете, что по умолчанию Access сортирует ваши столбцы в алфавитном порядке. Вы можете изменить этот порядок, перейдя в свойства диалог и ввод Заголовки Столбцов в порядке, который вы предпочитаете. Это настоящая боль. но, как один ответчик упомянул на другом сайте: "это всего лишь боль после!"
хорошо... это неверно, если ваши столбцы являются динамическими. В моем случае у меня есть второй столбец в таблице, содержащий заголовки столбцов, которые я хотел бы использовать для сортировки. Думаю, я мог бы добавить детали моего столбца сортировки в начало столбца описания (который был предложен еще где), но я не чувствую, что это самый элегантный способ решения проблемы. Это особенно проблема, поскольку информация о сортировке является системными данными и бесполезна для конечного пользователя перекрестной таблицы.
кто-нибудь знает решение этой проблемы? Если да, то не могли бы вы указать шаги для сортировки динамических столбцов запроса перекрестной таблицы?
Я думаю, что проблема сохраняется во всех версиях Access, которые широко используются (Access 2003+), но на всякий случай это имеет значение, я использую Access 2010.
обновление
вот некоторые очень упрощенные, примеры данных, которые помогают выразить проблему. Есть несколько других сложностей, окружающих мой живой сценарий, но этот набор данных, безусловно,получает точку зрения.
Таблица № 1
Вот откуда берутся заголовки. The 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 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
3 ответов
столкнувшись с одним и тем же сценарием несколько раз, я подготовил повторяемый способ добавления списка In в конец предложения PIVOT. При этом столбцы в запросе перекрестной таблицы будут отсортированы по порядку элементов в сводных полей в список. документация для этой конструкции доступна из MSDN. Решение-это процедура, которая должна запускаться кнопкой команды в форме или другом событии. Пожалуйста, смотрите снимки экрана ниже Подводная лодка.
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 аналогичен запросу, представленному в приведенном выше вопросе. Форма используется для выполнения процедуры и открытия запросов до и после.
в tblKeyDescriptions было добавлено целое поле (NumericIndexForSorting), поскольку для сортировки столбца sub требуется числовой индекс имена.
теперь проверьте список In, выделенный в представлении SQL начальных и отсортированных запросов.
Это все, что необходимо для заказа столбцов перекрестного запроса. Динамическое создание списка In является целью sub.
Примечание: sub должен запускаться каждый раз, когда выполняется запрос, поэтому использование события, такого как кнопка команды на событии Click, чтобы связать последовательность вместе, полезно.
здесь менее совершенным решение, которое использует некоторый доступ и Excel:
- при создании перекрестной таблицы используйте Table1.Ключ для столбцов.
- на новой вкладке (назовите это "поиск"?) в файле Excel сделайте таблицу#1
- в первой строке главной вкладки (т. е. там, где вставлен набор данных) в вашем файле Excel создайте кучу формул Vlookup (), чтобы посмотреть на строку#2 и вытащить правильное описание из вашего поиска таблица.
- вставьте набор данных в строку#2. Результатом будет таблица ниже, где первая строка на самом деле является кучей Vlookups, которые тянут правильное описание столбца.
- попросите пользователя просто игнорировать или удалять строку#2.
Я не знаю, насколько сложен ваш скрипт, но если эти данные вставлены в файл 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 |
+---------+--------------------------------------+-----------------------------+---------------------------------+
Я просто решаю эту проблему. Хотя предлагаемое решение работает (согласно описанию), другим возможным решением является создание query-def на лету (как в описанном решении), но вместо изменения SQL запроса просто заполните свойство заголовков столбцов запроса динамически генерируемой строкой заголовков столбцов. OP уже упоминает работу заголовков столбцов, но не Это кажется легче выполнить и не включает ничего, кроме некоторого vba для перечислите возможные значения в строке и задайте свойство
- создать перекрестную таблицу querydef
- перечислить заголовки столбцов в строки
- свойство
поэтому я собираюсь попробовать это и посмотреть, работает ли это/возможно
хорошо....оказывается, заголовки столбцов не являются фактическим свойством querydef, но он автоматически помещается в SQL.
Я думал, что у меня был яркий момент ;)