Как остановить Excel VBA от переименования переменных и параметров в несвязанных модулях и методах? - PullRequest
0 голосов
/ 09 февраля 2020

Я заметил невероятное разрушительное поведение Excel VBA. Он тихо и автоматически переименовывает переменные и параметры функции в несвязанных модулях, когда я добавляю, скажем, новое свойство в класс. Замечено в Office Professional Plus 2016 и Windows 10.

Для конкретного примера у меня есть один модуль и один класс. Модуль выглядит так:

Private Function MyRequests() As Collection
    Dim requests As Collection
    Set requests = New Collection
    Dim row As Integer
    row = 3
    Dim oRequest As New MyRequest
    oRequest.Name = "SomeName"
    requests.Add oRequest
    MyRequests = requests
End Function

Класс MyRequest выглядит следующим образом:

Private sName As String

Property Let Name(sValue As String)
    sName = sValue
End Property

Теперь невероятная часть приходит. Я добавляю новое свойство в класс MyRequest:

Private iRow As Integer

Property Let Row(iValue As Integer)
    iRow = iValue
End Property

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

Private Function MyRequests() As Collection
    Dim requests As Collection
    Set requests = New Collection
    Dim Row As Integer
    Row = 3
    Dim oRequest As New MyRequest
    oRequest.Name = "SomeName"
    requests.Add oRequest
    MyRequests = requests
End Function

Обратите внимание, что row стало Row! Это автоматическое переименование в автоматическом режиме также происходит во всем коде VBA в листах ... В основном везде Excel переименовывается в row в Row!

Итак, мой вопрос: что я могу сделать, чтобы остановить это безумное поведение?

Ответы [ 2 ]

3 голосов
/ 09 февраля 2020

Называть переменную с тем же именем, что и ключевое слово, не рекомендуется.

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


«Итак, мой вопрос: что я могу сделать, чтобы остановить это безумное поведение?»

Решение состоит в том, чтобы не объявлять переменную с тем же именем, что и ключевое слово VBA.

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

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


Ключевые слова определяются моделью объекта.

Ссылка на список ключевых слов в объектной модели VBA (ссылка в комментариях идет. NET):
https://docs.microsoft.com/en-us/office/vba/language/reference/keywords-visual-basic-for-applications

Ссылка на объектную модель Excel (не знаю где найти сжатый список, но если это объект, свойство или метод, то это ключевое слово): https://docs.microsoft.com/en-us/office/vba/api/overview/excel/object-model


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

Когда вы обнаружите, что называете переменную с потенциалом конфликта (например, строка, столбец, рабочий лист) et * 1 081 *.

  • во всех случаях лучше использовать более описательное имя (indexRow, lastRow, rowCounter)

  • Если вы можете Чтобы придумать что-нибудь подходящее, нажмите F2, чтобы открыть средство просмотра объектной модели и выполнить поиск по этому имени. Надеемся, что поиск не даст никаких результатов, и вы можете смело использовать это имя. Но если нет, поищите, где происходит конфликт

    • У вас не возникнет проблем, если вы создаете проект Excel и конфликт обнаружен в объекте Outlook. Вы можете даже рассмотреть возможность удаления ссылки на объект Outlook из вашего проекта

    • , если это имя свойства (например, Color) или метод (например, Resize), тогда вы можете использовать с осторожностью (в некоторых случаях это на самом деле идеально, например, при присваивании свойств и методов вашим пользовательским классам)

    • если это объект (например, Workbook), то вы не должны его использовать , Слишком большой риск независимо от объема. Никогда бы не узнал, если бы не ответ Майкла]

2 голосов
/ 10 февраля 2020

Эта проблема не возникает, потому что вы используете имена переменных, которые соответствуют встроенному свойству. Это происходит просто потому, что вы используете два разных варианта написания одной и той же переменной. Если вы использовали iRow в одном модуле и irow в другом, вы все равно получите ту же проблему.

Вы не можете остановить это поведение. IDE VBA автоматически изменяет имена подпрограмм, функций, переменных и свойств в соответствии с регистром последнего оператора объявления, который был отредактирован. Затем он также запоминает регистр, используемый для всех будущих экземпляров, введенных / отредактированных где-либо в коде.

При выполнении этого переименования среда IDE не различает guish между локальными и глобальными переменными или свойствами разные классы. Если вы изменяете регистр в любом месте, он будет обновляться и использоваться везде.

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

Если они локальные и различаются без риска путаницы, то вы все равно можете использовать одинаковое написание регистра. Зачем иметь одно соглашение об именах в одном модуле и другое соглашение об именах в другом модуле?

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

Это поведение также помогает вам гарантировать, что код вводится правильно при вводе, особенно если вы объявляете все переменные, подпрограммы и т. д. c с at хотя бы одна заглавная буква. Затем вы сможете редактировать весь код, используя только нижний регистр, что сокращает усилия, и тогда все, что правильно написано, будет автоматически преобразовано в объявленный регистр. Если вы вводите переменную в нижнем регистре, и она не меняет автоматически регистр, то вы сразу же знаете, что неправильно набрали переменную, вместо того, чтобы обнаруживать ошибку только при попытке скомпилировать / запустить.

Обратите внимание, что Проблема, которую действительно возникает из-за использования встроенных свойств в качестве имен для переменных и подпрограмм, заключается в том, что автоматическое c изменение регистра также применимо и здесь. Поэтому, если вы определите переменную как VALue, она будет переименовывать свойство .Value везде, где она используется.

Если вы затем определите подпрограмму как value, она переименует обе существующие VALue переменная, а также свойство .Value.

Если вы следуете хорошим правилам именования и нигде не используете имена, у вас не возникнет этой проблемы.

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