Перейти к содержимому
Наше приложение «Дешевые авиабилеты» в AppGallery >>

VBA Excel. Переворот списка по вертикали

    Переворот списка по вертикали с помощью VBA Excel. Копирование несортированного списка на другой столбец в обратном порядке с помощью цикла и без него.

    Постановка задачи

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

    Код предназначен для неотсортированного списка, так как отсортированный список легко перевернуть обратной сортировкой. Но при тестировании очень удобно использовать, для наглядности, вертикальный отсортированный числовой ряд.

    Переворот списка с помощью цикла

    Данные для копирования на другой столбец в обратном порядке выделяем на листе вручную и используем в коде VBA Excel выбранный диапазон как объект Selection.

    Базовый пример

    Переворот списка с помощью цикла и прямого чтения данных из ячеек.

    Результат работы кода:

    Список, записанный в обратном порядке

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

    Пример с защитой от ошибок

    Этот код VBA Excel также обрабатывает диапазон, выделенный в любом столбце, циклом For... Next с прямым чтением ячеек.

    Результат работы кода:

    Переворот списка из первой выделенной области

    Переворот списка без цикла

    Создание массива значений в обратном порядке с помощью метода Evaluate и конструкции N(IF(1,...)).

    Код обращения списка без цикла

    Коротко о том, как это работает:

    • N(IF(1, массив_индексов)) — это известный приём в VBA Excel, который заставляет функцию INDEX возвращать массив значений, а не одно значение.
    • revArray становится двумерным массивом размером (rowCount, 1) с перевёрнутыми значениями.
    • Затем массив с перевёрнутыми значениями присваивается диапазону справа от исходного списка одной операцией.

    Объяснение переворота списка

    Подробное объяснение, как получить массив значений из диапазона ячеек в обратном порядке с помощью метода Evaluate, функций INDEX, N и IF без использования циклов.

    Давайте разберем переворота списка без цикла по шагам, от сборки строки на уровне VBA до вычисления ее в движке Excel.

    Шаг 1. Сборка строки на уровне VBA

    Предположим, у нас есть следующие переменные:

    VBA собирает строку формулы, подставляя значения переменных:

    В итоге в метод Evaluate передается следующая текстовая строка:

    Шаг 2. Вычисление формулы внутри Excel

    Метод Evaluate передает эту строку вычислительному движку Excel. Движок обрабатывает её как обычную формулу массива. Разберем формулу изнутри наружу:

    А) ROW(1:5)
    Функция ROW генерирует массив номеров строк от 1 до 5.
    Результат: {1; 2; 3; 4; 5} (вертикальный массив).

    Б) 6 - ROW(1:5)
    Производится арифметическая операция над массивом:

    Результат: {5; 4; 3; 2; 1}.
    Смысл операции над массивом: мы получили индексы строк в обратном порядке.

    В) IF(1, {5; 4; 3; 2; 1})
    В обычных формулах (в старых версиях Excel) функция INDEX не принимает массив чисел как аргумент номера строки, если это не формула массива (Ctrl+Shift+Enter). Она могла бы вернуть только первое значение.
    Конструкция IF(1, ...) заставляет движок Excel обработать содержимое как массив констант, а не как ссылку. Она как бы говорит: «Возьми этот массив чисел и передай его дальше целиком».
    Результат: {5; 4; 3; 2; 1} (массив сохраняется).

    Г) N(...)
    Функция N преобразует результат в числа.
    В данном контексте это «страховка». IF может вернуть логический тип или вариант, а INDEX ожидает только числа. N гарантирует, что в INDEX попадет чистый массив чисел {5; 4; 3; 2; 1}.

    Д) INDEX($A$1:$A$5, {5; 4; 3; 2; 1})
    Функция INDEX берет диапазон $A$1:$A$5 и извлекает значения по номерам строк из массива индексов.

    Итоговый результат вычисления: вертикальный массив значений {ЗначениеA5; ЗначениеA4; ...; ЗначениеA1}.

    Шаг 3. Возврат результата в VBA

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

    Конструкция N(IF(1,...)) обеспечивает работу этого приёма в разных версиях Excel от 2010 года, где динамические массивы еще не работали так, как в Office 365. В VBA Excel 365 можно было бы написать проще (без IF и N), но опубликованный выше вариант более универсален.


    Содержание рубрики VBA Excel по тематическим разделам со ссылками на все статьи.