Рекомендации по размещению хранилища Excel VBA Worksheet Range - PullRequest
0 голосов
/ 13 декабря 2018

Одной из проблем, для которой я никогда не находил отличного решения, является определение местоположения объектов на листе в проекте VBA.Если кому-то из вас приходилось создавать рабочий лист с функциями VBA и рабочего листа, вы знаете, почему это важно.Это невероятно расстраивает запуск скрипта и осознание того, что ячейка, которая содержала результат вашего f-теста, переместилась с F20 на H20, потому что вам пришлось добавить два столбца данных, и вы не нашли все ссылки на диапазон в VBA, которыенеобходимо обновить.

Мне нужны новые идеи и лучшие практики для систематического хранения ссылок на диапазоны VBA, которые легко обновлять и которые соответствуют развивающейся электронной таблице.

Я перечисляю то, что я думаю, это общие варианты.Первые четыре я уже делал раньше, но они просто не справляются с задачей.

Option1: определение и программирование переменных местоположения в верхней части каждой подпрограммы

Это обычно то, что происходит.В верхней части каждой основной подпрограммы вы определяете переменные интерфейса диапазона и затем устанавливаете их с полностью определенными ссылками.Обычно этого достаточно для быстрых проектов с одной или двумя основными функциями.

Это становится проблемой, когда вы начинаете иметь много вложенных функций.Вы переопределяете headerRow и firstDataRow внутри функции moveDataRow()?Или вы передаете всю эту информацию каждый раз?Какая боль.Управляется в небольших масштабах.Полностью становится монстром спагетти и иголкой в ​​стоге сена по мере того, как вещи растут (и мы все знаем, что они обычно это делают).

Вариант 2: Определить мой собственный объект рабочего листа

I 'мы пошли на то, чтобы определить свой собственный объект листа, который имеет дополнительные свойства, такие как "headerRow" или "firstDataRow", чтобы я мог сохранить эти свойства в коде листа.Затем, когда я определяю объект листа, я использую dim srcSheet as myWorksheet вместо dim srcSheet as Worksheet.Это позволяет мне находить свойства через объектную модель.Например: srcSheet.headerRow

Это решение является УДИВИТЕЛЬНЫМ, когда вы имеете дело с большим количеством повторов одного и того же листа.Это пустая трата времени, если у вас есть шесть листов, которые делают что-то другое с разными необходимыми свойствами.Например: один лист может быть элементом управления Монте-Карло, в то время как другой выполняет f-тесты.Я не хочу создавать новый объект рабочего листа для каждого из них.

Вариант 3: динамически находить все

Это, вероятно, самый надежный, но невероятно трудоемкий процесс.,Найдите способ определить местоположение каждой ячейки на основе ее содержимого, форматирования и относительного местоположения.Обычно в ячейке, на которую вы пытаетесь сослаться, есть что-то конкретное, что не изменится.Написание сценария для поиска этой вещи значительно облегчает дальнейшие действия.тем не менее, это тонна работы и не реально выполнимо для каждого проекта.Это так много работы, это пустая трата времени для большинства проектов.

Опция 4: переменные местоположения на уровне модуля

Используйте новый модуль для основных функций, которые взаимодействуют с поднабором листов.Затем определите все элементы размещения один раз в верхней части этого модуля как частные константы.

Это хорошо работает для проектов среднего размера.Однако, когда вы имеете дело с несколькими модулями и перемещаете данные по нескольким рабочим листам по мере их обработки, вы начинаете определять одни и те же константы несколько раз.

Вариант 5: Создание модуля «Местоположения»

Это может хорошо работать, поскольку все местоположения будут в одном месте.Я еще не пробовал, но по этой причине я задаю этот вопрос здесь.Каждый раз, когда вы создаете ссылку на местоположение, она попадает в модуль местоположения.Каждый лист будет иметь определенный префикс, который идентифицирует этот конкретный лист.Таким образом, в подпрограмме или функции вместо установки местоположений диапазона листа в подпрограмме вы должны вызвать srcHeaderRow = dataHeaderRow, чтобы определить, что заголовки данных находятся в строке 5, вместо того, чтобы переопределять строку каждый раз, когда вам нужно использовать srcHeaderRow.

Что еще?Что-нибудь, что вы пробовали, было просто замечательно?

Какие еще методы вы использовали для поддержания местоположения ячеек / диапазонов для взаимодействия между VBA и рабочими листами?

1 Ответ

0 голосов
/ 13 декабря 2018

Я не знаю, подходят ли они как лучшие практики, но вот как я это делаю.

Изменение кодового имени рабочих листов

Почему dim srcSheet as myWorksheet, когда вы можете просто изменитьКодовые имена рабочего листа?

Changing Worksheets Code Names

Перечисление столбцов и строк заголовка

Я создаю Enum для каждого рабочего листа, чтобы перечислить каждый столбец,[Первый столбец], [Последний столбец] и [Строка заголовка].Заключение членов Enum в скобки и использование специальных символов для их имен создаст скрытых членов.Смотрите пример кода ниже.Если позже я решу изменить порядок столбцов, добавить столбцы или переместить данные, все, что мне нужно сделать, это обновить перечисление, и код не будет поврежден.

При щелчке правой кнопкой мыши по Обозревателю объектов вы можете отобразитьскрытые члены Object и Enums.show-hidden-members

Перечисления доступны для Intellisense

Intellisense

Образцы данных

Iиспользовали первые 10 строк из Пример данных Excel для данных.

Sample Data

Демонстрационный код

Public Enum EnumWSDataColumns
    dcOrderDate = 3
    dcRegion
    dcRep
    dcItem
    dcUnits
    dcUnitCost
    dcTotal
    [_dcFirstColumn] = dcOrderDate
    [_dcLastColumn] = dcTotal
    dcHeaderRow = 4
End Enum

Sub DemoEnum()
    Dim r As Long, c As Long
    Dim value As String * 10
    With wsData
        For r = dcHeaderRow To .Cells(.Rows.count, [_dcFirstColumn]).End(xlUp).Row
            For c = [_dcFirstColumn] To [_dcLastColumn]
                value = .Cells(r, c)
                Debug.Print value; "|";
            Next
            Dim n As Long
            n = ([_dcLastColumn] - [_dcFirstColumn] + 1) * (Len(value) + 1)
            Debug.Print
            Debug.Print String(n, "-")
        Next
    End With
End Sub

Вывод

Output

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...