До сих пор весь код в этой главе работал внутри одной книги. Но в реальной работе данные часто приходят снаружи: коллега прислал отдельный файл Excel, бухгалтерия выгрузила таблицу в CSV, часть цифр лежит в базе Access. Эта тема — про то, как код дотягивается за пределы своей книги: открывает и закрывает другие файлы Excel, читает и пишет обычные текстовые файлы, и в общих чертах — как достучаться до внешней базы данных.
К концу темы ты сможешь:
— открыть, переключиться на другую и закрыть книгу Excel из кода;
— объяснить разницу между ThisWorkbook и ActiveWorkbook;
— прочитать данные из текстового файла или CSV построчно и разложить их по ячейкам;
— записать данные из Excel в текстовый файл;
— знать, какой объект в VBA отвечает за подключение к внешней базе данных вроде Access.
Открытие, переключение и закрытие книг
Чтобы код мог работать с другим файлом Excel, книгу сперва нужно открыть — методом Workbooks.Open, указав путь к файлу. Если книга понадобится дальше по коду, её сразу сохраняют в переменную через Set.
Dim otchet As Workbook
Set otchet = Workbooks.Open("C:\Отчёты\Продажи.xlsx")
Как только книга открыта этим кодом, она сразу становится ActiveWorkbook — той, что сейчас на переднем плане. А ThisWorkbook — это всегда та книга, в которой лежит сам выполняющийся код, и она не меняется, даже если на экране открылась и стала активной другая книга. Разница ощущается сразу, если код открывает вторую книгу: ThisWorkbook по-прежнему указывает на первую, а ActiveWorkbook — уже на вторую, только что открытую.
ThisWorkbook - книга, где лежит САМ КОД. Не меняется никогда.
ActiveWorkbook - книга, которая СЕЙЧАС на переднем плане.
Меняется, стоит открыть или переключиться на другую.
Открыли Workbooks.Open("Продажи.xlsx") из кода в книге "Макросы.xlsm":
ThisWorkbook -> всё ещё "Макросы.xlsm" (там лежит код)
ActiveWorkbook -> уже "Продажи.xlsx" (её только что открыли)
Закрывают книгу методом Close, и по нему сразу видно, что делать с несохранёнными изменениями: otchet.Close SaveChanges:=True — сохранит их перед закрытием, otchet.Close SaveChanges:=False — закроет и отбросит, не сохраняя. Если нужно закрыть сразу ВСЕ открытые книги, их перебирают циклом For Each — так же, как в прошлой теме перебирали коллекцию листов.
Dim wb As Workbook
For Each wb In Workbooks
wb.Close SaveChanges:=True
Next wb
Осторожно. Если среди закрываемых книг окажется та, где лежит сам этот код, поведение непредсказуемо — код закрывает книгу, из которой сам же выполняется. На практике такой код кладут в отдельную книгу-инструмент, а не в рабочую книгу с данными.
Импорт и экспорт: чтение и запись текстовых файлов и CSV
CSV-файл — это обычный текст, где значения одной строки разделены запятой. Чтобы прочитать его в VBA, файл сначала открывают на чтение: Open путь For Input As #1. Дальше построчно читают командой Line Input, а каждую прочитанную строку разбирают на отдельные значения функцией Split — она рвёт строку по указанному разделителю и возвращает массив кусочков.
Dim stroka As String
Dim znacheniya() As String
Dim i As Integer
Open "C:\Данные\zakazy.csv" For Input As #1
i = 1
Do While Not EOF(1)
Line Input #1, stroka
znacheniya = Split(stroka, ",")
Cells(i, 1).Value = znacheniya(0) ' первый столбец строки CSV
Cells(i, 2).Value = znacheniya(1) ' второй столбец строки CSV
i = i + 1
Loop
Close #1
Условие Not EOF(1) проверяет, не дошли ли до конца файла (EOF — End Of File); пока строки не кончились, цикл продолжает читать дальше. После того как файл дочитан до конца, его обязательно закрывают командой Close #1 — так же, как закрывают книгу Excel.
Строка CSV: "Иванов,25,Москва" Split(строка, ",") -> массив из ТРЁХ элементов (индексы с 0, как у любого массива) znacheniya(0) = "Иванов" znacheniya(1) = "25" znacheniya(2) = "Москва"
Записывают данные в текстовый файл похожим образом, только открывают его на запись — Open путь For Output As #1, а не For Input. Дальше в файл пишут командой Write # — она удобна тем, что сама расставляет запятые между значениями и берёт текст в кавычки, то есть готовит строку сразу в формате CSV, который потом можно снова прочитать обратно.
Open "C:\Отчёты\export.csv" For Output As #1
Write #1, "Иванов", 120
Write #1, "Петров", 340
Close #1
Не перепутай с Print #. Есть похожая команда Print # — она тоже пишет в файл, но записывает текст «как есть», без автоматических запятых и кавычек. Если файл потом снова читают программой (в том числе своим же кодом VBA), удобнее Write # — он сразу готовит правильный CSV-формат.
Кратко: базы данных и веб-запросы из VBA
CSV — не единственный внешний источник. Иногда данные лежат в настоящей базе данных, например Access. Напрямую формулой Excel до неё не дотянуться, а из VBA — можно. Для соединения с файлом базы (.accdb) используют объект Connection из библиотеки ADO (ActiveX Data Objects) — через него выполняют обычный SQL-запрос. Результат запроса — набор найденных строк — приходит в виде отдельного объекта, Recordset; по нему можно пройтись циклом и разложить значения по ячейкам, точно так же, как из CSV.
Ещё один внешний источник — не файл на диске, а интернет: с помощью объекта XMLHTTP код VBA умеет отправлять HTTP-запрос и получать ответ от веб-сервиса (например, актуальный курс валюты). Тема нишевая и для большинства офисных задач не нужна — если интересно, загляни в необязательную практику ниже.
Проверь себя
Контрольный вопрос. Что нужно сделать, чтобы дальше в коде можно было обращаться к только что открытой книге через переменную?
Подсказка: Workbooks.Open возвращает объект книги — его нужно куда-то поместить, чтобы не потерять.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Книга открыта кодом через Workbooks.Open. Какой книгой она сразу становится?
Подсказка: Только что открытый файл оказывается на переднем плане.
Онлайн-проверка ответа появится позже
Задание. В книге otchet есть несохранённые изменения. Сохранятся ли они при выполнении этой команды? Ответь одним словом: да или нет.
Исходный код для этого задания:
otchet.Close SaveChanges:=FalseПодсказка: Параметр SaveChanges равен False — подумай, что это означает буквально.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Код в книге «Макросы.xlsm» открывает через Workbooks.Open книгу «Продажи.xlsx». Чему в этот момент равен ThisWorkbook?
Подсказка: ThisWorkbook и ActiveWorkbook — это про разные вещи: где лежит код и что сейчас на переднем плане.
Онлайн-проверка ответа появится позже
Задание. Открыто пять книг Excel. Сколько из них останется открытыми после выполнения этого кода? Впиши число.
Исходный код для этого задания:
Dim wb As Workbook For Each wb In Workbooks wb.Close SaveChanges:=True Next wbПодсказка: Цикл проходит по коллекции Workbooks и закрывает КАЖДУЮ книгу без исключения.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Какая команда открывает текстовый файл для последующего построчного чтения?
Подсказка: Нужен режим ЧТЕНИЯ уже существующего файла, а не записи в новый.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Какая функция разбивает строку CSV на отдельные значения по разделителю (например, по запятой)?
Подсказка: Она возвращает массив кусочков строки.
Онлайн-проверка ответа появится позже
Задание. Сколько элементов окажется в массиве znacheniya? Впиши число.
Исходный код для этого задания:
stroka = "Смирнова,31,Казань" znacheniya = Split(stroka, ",")Подсказка: Посчитай, на сколько частей запятая режет эту строку.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Задание. Тебе нужно получить из этого массива город («Казань»). Под каким индексом он лежит? Впиши число.
Исходный код для этого задания:
stroka = "Смирнова,31,Казань" znacheniya = Split(stroka, ",")Подсказка: Индексы у массива, который вернул Split, начинаются с 0 — посчитай, какой по счёту элемент город.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Что проверяет условие Not EOF(1) в цикле построчного чтения файла?
Подсказка: EOF расшифровывается как End Of File.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Чем команда Write # отличается от Print # при записи в текстовый файл?
Подсказка: Одна из команд просто печатает текст как есть, другая сама готовит его к повторному чтению.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Чтобы обратиться из VBA к внешней базе данных вроде Access, обычно используют объект…
Подсказка: Это тот же объект, что открывает соединение с файлом базы .accdb.
Онлайн-проверка ответа появится позже
Контрольный вопрос. В каком виде обычно приходит результат SQL-запроса к базе данных через ADO?
Подсказка: Это набор строк, которые вернул запрос, — по нему потом проходят циклом.
Онлайн-проверка ответа появится позже
Итог
Итог. Workbooks.Open открывает другую книгу и сразу делает её ActiveWorkbook; ThisWorkbook всегда указывает на книгу с самим кодом и не меняется. Close SaveChanges:=True/False решает судьбу несохранённых изменений; For Each по коллекции Workbooks закрывает разом все открытые книги. Текстовый файл читают через Open…For Input As, построчно — Line Input, а строку CSV разбирают функцией Split на массив значений (индексы с 0); конец файла проверяет EOF(). Пишут в файл через Open…For Output As и Write # — она сама готовит строку в формате CSV, в отличие от Print #, который пишет текст как есть. К внешней базе данных (Access) обращаются через объект Connection (ADO), а результат SQL-запроса приходит как Recordset.
Практика (необязательная)
Задание для практики. Создай текстовый файл zakazy.csv с тремя строками вида «Товар,Количество,Цена» (например, «Ноутбук,2,45000»). Напиши макрос, который откроет файл (Open…For Input), построчно прочитает данные (Line Input + Split) и перенесёт их в таблицу на листе. Затем посчитай в Excel сумму по каждой строке (количество × цена) и запиши результат обратно в новый файл itogi.csv через Open…For Output и Write #.
Если хочешь пойти дальше (нишевая, необязательная тема): посмотри, как VBA обращается к внешним источникам за пределами обычных файлов —
CreateObject("ADODB.Connection")для запроса к базе Access через SQL, илиCreateObject("MSXML2.XMLHTTP")для запроса к веб-сервису (например, получить текущий курс валюты). Для большинства офисных задач это не понадобится — но знать, что такая возможность есть, полезно.
