2016-06-16 4 views
2

У меня было впечатление, что у VBA были свойства по умолчанию для всех его объектов. Так что если я скажу Cells(counter, x), то по умолчанию будет добавлено значение .value. Кроме того, я всегда использовал Cells(counter, x) и Cells(counter, x).value взаимозаменяемо. Однако при добавлении элементов в коллекцию через цикл for я заметил, что вместо того, чтобы хранить значение, я не включил .value, он сохранил значение, представленное местоположением на листе. Таким образом, если местоположение было удалено, ссылка в коллекции будет потеряна. Это приводит меня к двум открытиям: 1) Коллекции могут хранить нестатические ссылки, а 2) Cells() и другие объекты не имеют свойств по умолчанию, таких как .value.Свойство default для cells()

Если кто-либо может уточнить, подтвердить и просветить, это было бы отлично.

+2

Значение по умолчанию часто зависит от контекста. Если вы добавите 'Cells (c, x)' в коллекцию, вы добавите * ссылку * к объекту Range. Если вы присваиваете 'Cells (c, x)' переменной * без *, используя 'Set', то это свойство по умолчанию будет занесено в переменную. –

ответ

6

Нет, не все типы имеют элемент по умолчанию.

Любой модуль класса может иметь член по умолчанию, указав специальный атрибут участника (вам нужно будет экспортировать и отредактировать файл кода вручную, чтобы сделать это, VBE не предоставляет никаких функций для этого):

Attribute {member name}.VB_UserMemId = 0 

Только один член может быть членом по умолчанию.

Вы обнаруживаете гадость членов по умолчанию и почему их следует избегать.

VBA делает много вещей, чтобы «сделать нашу жизнь проще» (например, неявные преобразования типов), а элементы по умолчанию - одна из этих вещей.

Коллекция может хранить нестатические ссылки

Я не знаю, что такой «статический справочник» есть, но при сохранении ссылкиобъекта в Collection, вы не хранить копия объекта, но ссылка.

Cells() и другие объекты не имеют свойств по умолчанию, таких как .value.

Global.Cells - это параметризированное свойство getter, которое возвращает ссылку на объект Range; Range.Cells также является получателем, который возвращает объект Range; в объектной модели Excel нет класса Cell. Элементом по умолчанию Range является его Value. Но тогда, когда вы сделаете это:

Dim c As Collection 
Set c = New Collection 
c.Add ActiveSheet.Cells(1, 1) 

Затем вы добавляете Range ссылку, которая .Cells(1, 1) возвращается, и тогда это:

Debug.Print c.Item(1) 

Выведет, что Range значение объекта. Тем не менее это:

Debug.Print TypeName(c.Item(1)) 

Вывод Range.

Confusing? Да. Вот почему вы должны всегда указывать Option Explicit, работать с переменными, объявленными с явным типом, насколько это возможно, избегать неявных преобразований типов, ... и избегать использования элементов по умолчанию.

Написав код, который читается точно так, как он должен себя вести, вы избегаете нескольких ловушек VBA, и когда вы в конце концов захотите изучить некоторые VB.NET или C#, вы не потеряете вообще о типе безопасности и ясности.


С the latest Rubberduck build (с открытым исходным кодом VBE добавить в проект, которым я управляю), вы можете указать класс членпо умолчанию со специальным комментарием ("аннотаций"):

'@DefaultMember 
Public Property Get Foo() 
End Property 

Аннотации запускают результат проверки кода, который предупреждает о недостающем соответствующем атрибуте; запустив «синхронизировать аннотации/атрибуты» результата проверки, Rubberduck экспортирует модуль, добавляет атрибут VB_Attribute Foo.VB_UserMemId = 0 и повторно импортирует модуль для вас.

С другой стороны, если элемент имеет атрибут VB_UserMemId = 0, но нет соответствующего @DefaultMember аннотации, Rubberduck производит осмотр результат предупреждения о пропавшей аннотации, и предлагает быстро исправить, чтобы автоматически добавить ВЗ для вас.

Больше аннотаций существует, но выходит за рамки этого ответа. Просмотрите RD News сообщения блога для всей информации.

+1

Если вы определяете ключевой аргумент в своей коллекции 'Add', вы можете в итоге использовать c.Add ActiveSheet.Cells (1, 1), ActiveSheet.Cells (1, 1)', который является 2 различными способами использования в такое же заявление! – ThunderFrame