При автоматизации взаимодействия 1С с Microsoft Excel часто возникает задача не просто заполнить таблицу данными, но и запустить внутри книги определенную обработку на VBA (макрос). Если список доступных макросов заранее неизвестен или зависит от загружаемого файла, необходимо динамически выгрузить имена процедур и предоставить пользователю выбор для запуска через метод Excel.Run().
Рассмотрим подробно, как реализовать чтение компонентов VBA из книги Excel на стороне 1С, с какими настройками безопасности можно столкнуться и как правильно запустить выбранный макрос.
Прежде чем обращаться к объектной модели проектов VBA из 1С, разберем важное ограничение платформы Microsoft Office. По умолчанию прямой программный доступ к коду VBA заблокирован в целях безопасности. Если попытаться прочитать свойство VBProject без предварительной настройки, Excel вернет ошибку доступа (например, Error 1004: Programmatic access to Visual Basic Project is not trusted).
Для корректной работы кода выполним следующие настройки на рабочем месте, где исполняется алгоритм:
Важно: Важно помнить, что механизм взаимодействия через COMОбъект("Excel.Application") функционирует исключительно под управлением ОС Windows. Если сервер 1С работает на Linux, чтение макросов через COM необходимо выполнять на стороне клиента.
Проанализируем структуру программного кода 1С, который открывает книгу Excel, перебирает компоненты проекта (модули), считывает их содержимое построчно и вычленяет имена процедур Sub и Public Sub.
Разберем готовый пример решения:
// Создаем COM-объект и открываем файл
Excel = Новый COMОбъект("Excel.Application");
Excel.Visible = Ложь;
Книга = Excel.Workbooks.Open(ПутьКФайлу);
МодулиVBA = Новый Массив;
Попытка
// Перебираем компоненты проекта VBA в книге
Для i = 1 По Книга.VBProject.VBComponents.Count Цикл
ИмяМодуля = Книга.VBProject.VBComponents(i).Name;
МодулиVBA.Добавить(ИмяМодуля);
КонецЦикла;
// Обходим каждый модуль и читаем его код
Для Каждого ИмяМодуляVBA Из МодулиVBA Цикл
КодМодуляVBA = Книга.VBProject.VBComponents(ИмяМодуляVBA).CodeModule;
// Считываем строки после блока объявлений
Для i = КодМодуляVBA.CountOfDeclarationLines + 1 По КодМодуляVBA.CountOfLines Цикл
СтрокаVBA = КодМодуляVBA.Lines(i, 1);
// Проверяем наличие ключевых слов объявлений процедур
Если СтрНайти(СтрокаVBA, "Public Sub ") <> 0 ИЛИ СтрНайти(СтрокаVBA, "Sub ") <> 0 Тогда
Если СтрНайти(СтрокаVBA, "Public Sub ") <> 0 Тогда
СмещениеСимволов = 11;
Иначе
СмещениеСимволов = 4;
КонецЕсли;
НачСимвол = (СтрНайти(СтрокаVBA, "Sub") + СмещениеСимволов);
КонСимвол = (СтрНайти(СтрокаVBA, "("));
Если КонСимвол = 0 Тогда
ИмяМакроса = СокрЛП(Сред(СтрокаVBA, НачСимвол));
Иначе
ИмяМакроса = СокрЛП(Сред(СтрокаVBA, НачСимвол, КонСимвол - НачСимвол));
КонецЕсли;
// Добавляем найденный макрос в элемент формы (например, список выбора)
Элементы.МакросДляЗапуска.СписокВыбора.Добавить(ИмяМакроса);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Исключение
Сообщить("Не удалось получить список макросов из файла. Ошибка: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
После того как имя нужной процедуры получено, выполним её запуск из 1С с помощью метода Run приложения Excel.
Рассмотрим особенности синтаксиса при вызове макросов из разных типов модулей:
Excel.Run(ИмяМакроса);
// Запуск макроса, расположенного в коде Листа1
Excel.Run("Лист1." + ИмяМакроса);
По завершении работы не забудьте закрыть книгу без сохранения изменений (или с сохранением, если макрос модифицировал файл) и завершить процесс Excel:
Книга.Close(Ложь);
Excel.Quit();
Excel = Неопределено;