Почему нет необходимости устанавливать переменную объекта перед использованием цикла For Each Next? - PullRequest
0 голосов
/ 05 ноября 2018

Я изучаю этот простой макрос, но я не понимаю, почему нет необходимости устанавливать переменную объекта с именем ws со ссылкой на объект перед использованием цикла For Each ... Next. Моя логика:

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

Итак, когда мы ссылаемся на ws в строке For each ws In ActiveWorkbook.Worksheets, разве переменная ws не является технически пустой? Разве не должно быть какой-то строки, где мы берем ws = ActiveSheet, чтобы переменная фактически содержала ссылку на объект на листе? Так растерялся.

Sub FormatFormulas()
    Dim ws As worksheet
    On Error Resume Next
    For Each ws In ActiveWorkbook.Worksheets
        With ws.Cells.SpecialCells(xlCellTypeFormulas)
            .NumberFormat = ”#,##0”
            .Interior.ColorIndex = 36
            .Font.Bold = True
        End With
    Next ws
End Sub

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

Хорошо, благодаря ответу Тима, я смог разобраться:

Мы МОЖЕМ инициировать переменную ws, используя Set ws = Worksheets (1), НО это не нужно для цикла For Each Next, потому что он устанавливает переменную с каждой итерацией (и всегда начинается с первого элемента в коллекции на основе порядковый номер изделия).

0 голосов
/ 05 ноября 2018

Поведение во время выполнения в циклах For Each описано в разделе 5.4.2.4 спецификации языка VBA.

Для массивов:

  • Если объявленный тип массива Object , тогда > Set назначается первому элементу в массиве. В противном случае Пусть присваивается первому элементу в массиве.
  • После установки выполняется <оператор-блок>. Если присутствует <вложенный оператор>, он выполняется.
  • После того как <оператор-блок> и, если он есть, <вложенный-для-оператора> завершил выполнение, <связанное-переменное-выражение> будет присвоено следующему элементу в массиве (или назначено для набора) если это массив объектов). Если и только если в массиве больше нет элементов, выполнение <для каждого оператора> немедленно завершается. В противном случае <оператор-блок> выполняется снова, после чего следует <вложенный_статист>, если он присутствует, и этот шаг повторяется.

Для других перечислимых типов (в вашем случае Workbook.Worksheets) это поведение во время выполнения:

  • Значение данных должно быть ссылкой на объект для внешнего объекта, который поддерживает перечисление, определяемое реализацией интерфейс. является либо назначенным, либо Набор назначается первому элементу в в в зависимости от реализации.
  • После установки выполняется <оператор-блок>. Если присутствует <вложенный оператор>, он выполняется.
  • Когда <оператор-блок> и, если он есть, <вложенный-для-оператора> завершил выполнение, <привязанное-переменное-выражение> назначается для следующего элемента в в реализации- определенным образом. Если в больше нет элементов, выполнение <для каждого оператора> немедленно завершается. В противном случае <оператор-блок> выполняется снова, после чего следует <вложенный-для-оператора>, если он присутствует, и этот шаг повторяется.

В вашем случае все сводится к тому, что неявный вызов генерируется компилятором, который выполняет следующее присваивание при входе в цикл в первый раз и для каждой итерации. Это будет что-то похожее на это после компиляции (на самом деле это немного сложнее, чем проверка Nothing):

Set ws = ActiveWorkbook.Worksheets.[_NewEnum]
Do While ws Is Not Nothing
    With ws.Cells.SpecialCells(xlCellTypeFormulas)
        .NumberFormat = "#,##0"
        .Interior.ColorIndex = 36
        .Font.Bold = True
    End With
    Set ws = ActiveWorkbook.Worksheets.[_NewEnum]
Loop

Обратите внимание, что именно поэтому вы не должны изменять содержимое коллекции во время итерации по ней - следующий элемент извлекается путем вызова [_NewEnum]. Это означает, что элементы, возвращаемые базовой коллекцией, «выдаются» по одному за раз, поэтому изменение содержимого коллекции внутри цикла будет либо влиять на то, какие элементы возвращаются, либо потенциально может вызвать ошибку (поведение [_NewEnum] зависит от реализации).

0 голосов
/ 05 ноября 2018

Здесь ссылка ws используется для получения рабочих листов ActiveWorkbook одна за другой.

For Each ws In ActiveWorkbook.Worksheets

Ссылка на выше ws в

Dim ws As worksheet

не инициирует объект, но объявляет, что переменная ws будет использоваться в качестве рабочего листа.

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