В моих проектах я часто использую таблицы и базовые объекты ListObjects и ListColumns. Мне они нравятся, так как их легче ссылаться и обновлять, чем объекты диапазона Range. Тем не менее, я до сих пор не нашел разумного и удобного способа обработки нескольких ListObjects, состоящих из многих ListColumns, и ссылки на все рабочие листы в проекте.Как написать чистый и поддерживаемый код при работе со столами?
Предположим, у меня есть рабочий лист (с (Name) свойство, установленным в «WorksheetA»), который содержит таблицу (называемую таблицей A) с несколькими столбцами (называемыми столбцами Column1, Column2, ..., Column10).
Теперь я хочу ссылаться на один из столбцов кода другого рабочего листа. Я мог бы сделать это следующим образом:
WorksheetA.ListObjects("TableA").ListColumns("Column7")
Теперь, это плохая практика, чтобы использовать строку непосредственно, как это трудно поддерживать и склонны к ошибкам.
Так что же теперь?
Я мог бы создать выделенный модуль для хранения моей строки в качестве констант. Например, модуль называется "Константы":
Public Const TABLE_A As String = "TableA"
Public Const COLUMN7 As String = "Column7"
Тогда мое обращение может быть преобразовано в:
WorksheetA.ListObjects(Constants.TABLE_A).ListColumns(Constants.COLUMN7)
Однако это решение имеет некоторые недостатки:
- Константы модуль будет расти до смешного быстро с каждой добавленной таблицей и столбцом.
- Ссылка сама по себе растет и становится менее читаемой.
- Все константы, связанные со столами из всех книг, бросаются в одну гигантскую яму.
Я мог бы хранить константы внутри WorksheetA, и сделать их доступными через публичные функции, такие как:
Private Const TABLE_A As String = "TableA"
Private Const COLUMN7 As String = "Column7"
Public Function GetTableAName() As String
GetTableAName = TABLE_A
End Function
Public Function GetTableA() As ListObject
Set GetTableA = WorksheetA.ListObjects(TABLE_A)
End Function
Public Function GetTableAColumn7() As ListColumn
Set GetTableAColumn7 = GetTableA().ListColumns(COLUMN7)
End Function
Это решение фактически решает все три упомянутые выше проблемы, но это все-таки немного «грязной» и по времени поскольку добавление новой таблицы приводит к необходимости создания функции для каждого столбца.
У вас есть идея, как справиться с этой проблемой?
EDIT1 (для наглядности): Предположим, что пользователь не должен изменять имена (ни имена таблиц, ни имена столбцов). Если пользователь делает это, он виноват.
EDIT2 (для четкости): Я использовал колонку 7 в качестве имени столбца только в качестве примера. Предположим, что столбцы имеют более значимые имена.
Интересная проблема. Если бы было простое решение для этого, я бы предположил, что мы бы увидели его в библиотеках доступа к данным, таких как DAO, ADO, JDBC и т. Д. Единственное, что разработчики могут сделать для инкапсуляции этих «имен полей» и «имен таблиц», писать «постоянные» классы, т. е. один класс для каждой таблицы или объекта данных. Это «чистое» решение, но оно добавляет слой и требует много времени. Он рекомендуется для больших проектов БД, но я сомневаюсь, что проект Excel достигнет такого масштаба, что это решение станет действительно необходимым. –
Я думаю, вы обеспокоены тем, что в строчном подходе имена таблиц могут быть изменены пользователем и, следовательно, нарушают ссылку. Если на листе есть только одна таблица, вы можете использовать номер индекса (1) вместо строки. Это допустимо только для максимальной таблицы на листе. Не знаю, если это применимо на всех ваших листах. Это было бы в вашем примере. –
Если имена столбцов на самом деле такие же неописуемые, как 'Column7', то почему бы не ссылаться на них по числовому индексу? –