Заполнение строки данными из несмежных диапазонов

Прошу подсказать, почему возникает ошибка при заполнении массива?

Несколько раз проверял синтаксис, вроде всё нормально, но не работает. Жму F8 (пошаговое выполнение макроса), но попытка заполнить массив в строке NumStrok = Array(...) вызывает ошибку.

Что не так?

Sub Макрос1()
    Dim NumStrok(1 To 21) As String
    NumStrok = Array("B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "H11", "I11", "J11", "K11", "H13", "I13", "J13", "K13", "B14", "D14", "B15", "D15", "H16")
    Dim NumKol(1 To 21) As String
    NumKol = Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U")
    Dim OrgData(21) As Variant
    Dim KakaStroka As String

    Sheets("Ввод").Select

    For i = 1 To 21
      OrgData(i) = Range(NumStrok)
    Next

    KakaStroka = CStr(CInt(OrgData(1)) + 4)

    Sheets("База").Select

    For i = 1 To 21
      Range(NumKol + KakaStroka) = OrgData(i)
    Next

End Sub

Ответы (1 шт):

Автор решения: vikttur

Ошибка не одна, их много. А без понимания конечной задачи код смотрится сборной солянкой.

  1. Не нужно задавать размерность массива, если он будет заполняться диапазоном с листа или массивом констант. При объявлении массива размерность можно задать, если он впоследствии будет заполняться поэлементно.

OrgData(i) = .Range(NumStrok) Хотите передать в массив значение ячейки? Не тут-то было...

  1. Во-первых, сразу же ошибка - не указан элемент массива-передатчика, надо NumStrok(i).

  2. При декларации массива OrgData указано, что его элементы типа Variant (т.е. могут быть любого типа). В цикле массив заполняется Range(NumStrok(i))... Но чем? В OrgData может быть передано значение, которое находится по ссылке, но может быть записан и адрес ссылки!

Вывод. Всегда явно указывать, что хотим получить - Range(NumStrok(i)).Value

  1. Знак + (плюс). Это может быть и объединение текстовых строк, и суммирование числовых данных. И его действие зависит от первого элемента перед знаком.

CInt(OrgData(1)) + 4 - здесь в элементе массива может быть текст "B2" (см. выше ошибку 3). Попытка задать тексту тип "целое" - ошибка. Если без CInt, получим конкатенацию (объединение строк) - "B2" + 4 = "B24"

Range(NumKol + KakaStroka) - здесь NumKol - число, предполагается суммирование, но KakaStroka - текcт. Результат попытки суммирования с текстом - ошибка. Если в KakaStroka число в текстовом формате (ведь переменная типа String), получим суммирование двух чисел - номера столбца и номера строки. Догадайтесь, что будет :)

Вывод. Для суммирования применять + , для объединения текстов &. Если в переменной предполагается хранение числового значения, то почему эта переменная декларируется строковой?

  1. Примечание. Почему в примере выше B2, а не B1? Если в модуле не декларирован оператор принудительного указания первого элемента массивов, то при заполнении массивом констант по умолчанию первый элемент массива - 0 (ноль). Отсюда еще дна неточность - цикл нужно начинать с нуля, а не с единицы.

  2. Sheets("Ввод").Select. Для обращения к диапазонам не обязательно активировать лист.

  3. Массив NumKol лишний. Ссылку можно формировать и так: Cells(KakaStroka, i) = OrgData(i)

  4. Массив OrgData и первый цикл тоже лишние, если значение .Range(NumStrok(i)) передавать во втором цикле напрямую в ячейки.

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

Если задумка понята правильно, код может быть таким:

Sub Макрос1()
    Dim NumStrok(), OrgData(20)
    Dim KakaStroka As Long ' перевод: совсем плохая строка :) '
    Dim j As Long

    NumStrok = Array("B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "H11", "I11", "J11", "K11", "H13", "I13", "J13", "K13", "B14", "D14", "B15", "D15", "H16")

    With Sheets("Ввод")
        For j = 0 To 20
            OrgData(j) = .Range(NumStrok(j)).Value
        Next j

        KakaStroka = OrgData(0) + 4
        Sheets("Ввод").Cells(KakaStroka, 1).Resize(1, 21).Value = OrgData
    End With
End Sub

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

→ Ссылка