Работа с COM в 1С 8.3: Excel, Word, внешнее соединение и типичные сбои
Содержание
COM-объект в 1С — это экземпляр внешней Windows-программы или библиотеки, которым код на встроенном языке управляет напрямую: Новый COMObject("Excel.Application") запускает Excel, и дальше 1С вызывает его методы и свойства так же, как методы своих объектов. Работает это только под Windows, в тонком и толстом клиенте, на сервере 1С и во внешнем соединении. В веб-клиенте и на Linux такого типа нет.
Типичная ситуация: бухгалтер просит выгрузить реестр платежей в Excel «с нашим оформлением и формулами», а штатного сохранения в xlsx не хватает. Или нужно из одной базы 1С прочитать остатки другой без обмена. Обе задачи решают через COM, и обе ломаются на одних и тех же местах: регистрация, разрядность, права, зависшие процессы.
Что такое COM-объект и как он работает в 1С
COM (Component Object Model) — технология Microsoft, через которую одна программа публикует свои объекты, а другая ими пользуется. Excel, Word, Outlook, драйверы торгового оборудования, ADO для баз данных, сама 1С — все они умеют быть COM-серверами.
Что происходит при вызове Новый COMObject("Word.Application"):
- 🔎 Платформа ищет в реестре Windows строку
Word.Application(её называют ProgID) и по ней находит класс. - 🚀 Windows запускает сервер: отдельный процесс (
WINWORD.EXE) или загружает DLL прямо в процесс 1С. - 🔗 1С получает ссылку на объект и оборачивает её в тип
COMОбъект. - 📞 Каждое обращение
Word.Documents.Open(...)уходит в COM-сервер через позднее связывание: имена методов ищутся по ходу выполнения, поэтому опечатка проявится только при запуске.
Отсюда два практических следствия. Первое: COM-объект создаётся на том компьютере, где выполняется код. Процедура с директивой &НаКлиенте запустит Excel у пользователя, &НаСервере — на сервере 1С. Второе: каждое обращение к свойству — это вызов между процессами, а значит, тысяча обращений в цикле заметно медленнее, чем одно обращение за всем диапазоном сразу.
| Где выполняется код | COM доступен | Что учесть |
|---|---|---|
| Тонкий клиент на Windows | Да | Нужна программа на компьютере пользователя |
| Толстый клиент на Windows | Да | То же |
| Сервер 1С на Windows | Да | Работает под учётной записью службы, без рабочего стола |
| Веб-клиент | Нет | Вынесите логику на сервер или используйте другой способ |
| Клиент или сервер на Linux, macOS | Нет | Только альтернативы: файлы, HTTP, OData |
В файловом варианте базы серверный контекст выполняется в процессе самого клиента. Поэтому &НаСервере в файловой базе тоже запускает Excel на компьютере пользователя. После перехода на клиент-серверный вариант тот же код начнёт создавать Excel уже на сервере.
Как создать COM-объект в 1С: порядок действий
Схема одинакова для любого приложения.
- Убедитесь, что программа установлена там, где выполнится код. Для Excel на клиенте — Excel на рабочем месте пользователя.
- Узнайте ProgID. Для популярных программ они известны:
Excel.Application,Word.Application,Outlook.Application,WScript.Shell,Scripting.FileSystemObject,ADODB.Connection. Для оборудования ProgID указан в документации драйвера. - Создайте объект в
Попытка, чтобы отсутствие программы не обрушило всю процедуру. - Работайте через методы и свойства из документации самого приложения (для Office — объектная модель VBA). Имена пишутся латиницей, как в VBA.
- Закройте приложение и освободите ссылку. Для Office — вызов
Quit(), затем присваивание переменнойНеопределено.
Минимальный каркас:
&НаКлиенте
Процедура ВыгрузитьВExcel(Команда)
Попытка
Excel = Новый COMObject("Excel.Application");
Исключение
Сообщить("Excel не установлен или не зарегистрирован: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Попытка
Excel.DisplayAlerts = Ложь;
Книга = Excel.Workbooks.Add();
Лист = Книга.Worksheets(1);
Лист.Cells(1, 1).Value = "Контрагент";
Лист.Cells(1, 2).Value = "Сумма";
Книга.SaveAs("C:\Temp\Реестр.xlsx");
Книга.Close(Ложь);
Исключение
Сообщить("Ошибка Excel: " + ОписаниеОшибки());
КонецПопытки;
Excel.Quit();
Excel = Неопределено;
КонецПроцедуры
Вызов Excel.Quit() стоит после блока Попытка, а не внутри него. Так Excel закроется даже тогда, когда запись ячейки упала с ошибкой.
Подключиться к уже запущенному приложению
Если Excel уже открыт и нужно взять его активную книгу, используйте ПолучитьCOMОбъект:
Excel = ПолучитьCOMОбъект(, "Excel.Application"); // запущенный экземпляр
Книга = ПолучитьCOMОбъект("C:\Temp\Реестр.xlsx"); // объект по имени файла
Если запущенного экземпляра нет, первый вариант вызовет исключение. Оберните его в Попытка и при ошибке создайте новый объект.
Готовые примеры кода для частых задач
Быстро прочитать лист Excel
Чтение по одной ячейке в цикле — главная причина «загрузка 5 000 строк идёт 10 минут». Читайте диапазон за один вызов: свойство Value у диапазона возвращает объект типа COMSafeArray.
Книга = Excel.Workbooks.Open(ПутьКФайлу);
Лист = Книга.Worksheets(1);
ЧислоСтрок = Лист.UsedRange.Rows.Count;
ЧислоКолонок = Лист.UsedRange.Columns.Count;
Данные = Лист.UsedRange.Value.Выгрузить(); // массив массивов
Книга.Close(Ложь);
Метод Выгрузить() превращает COMSafeArray в обычный массив 1С, с которым дальше работают без обращений к Excel. Индексы в массиве начинаются с нуля. Перед боевой загрузкой проверьте на файле из двух строк и трёх колонок, какой уровень массива отвечает за колонки, а какой за строки, и зафиксируйте это в коде.
Заполнить шаблон Word
Шаблон договора с метками [ФИО], [Сумма] удобно заполнять заменой через Find.Execute. Одиннадцатый параметр 2 означает «заменить все вхождения», десятый — текст замены:
Word = Новый COMObject("Word.Application");
Попытка
Док = Word.Documents.Open(ПутьКШаблону);
Док.Content.Find.Execute("[ФИО]", , , , , , , , , "Иванов И. И.", 2);
Док.Content.Find.Execute("[Сумма]", , , , , , , , , "15 000,00", 2);
Док.ExportAsFixedFormat(ПутьКPDF, 17); // 17 — формат PDF
Док.Close(0); // 0 — не сохранять шаблон
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Word.Quit(0);
Word = Неопределено;
Пропущенные параметры между запятыми 1С передаёт как «не указано», и Word подставляет значения по умолчанию.
Запустить внешнюю программу и дождаться её
Оболочка = Новый COMObject("WScript.Shell");
КодВозврата = Оболочка.Run("cmd /c ""C:\Scripts\backup.bat""", 0, Истина);
Второй параметр 0 скрывает окно, третий Истина заставляет ждать завершения. Для такой задачи есть и штатный ЗапуститьПриложение, но WScript.Shell.Run возвращает код завершения программы.
Подключиться к другой базе 1С через COMConnector
Внешнее соединение — это COM-сервер самой 1С. Он позволяет из одной базы (или из скрипта) открыть другую и выполнить в ней запрос:
Коннектор = Новый COMObject("V83.COMConnector");
Соединение = Коннектор.Connect("Srvr=""srv1c"";Ref=""buh"";Usr=""Обмен"";Pwd=""*****"";");
Запрос = Соединение.NewObject("Запрос");
Запрос.Текст = "ВЫБРАТЬ Наименование, Код ИЗ Справочник.Контрагенты";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование);
КонецЦикла;
Соединение = Неопределено;
Для файловой базы вместо Srvr и Ref указывают File=""D:\Bases\Buh"";. Пользователю, под которым идёт подключение, в целевой базе нужна роль с правом «Внешнее соединение».
Объекты, полученные через соединение, живут в другой базе. Строку, число и дату можно спокойно переносить, а ссылку на справочник «чужой» базы записать в реквизит своей нельзя. Сопоставляйте данные по коду, ИНН или уникальному идентификатору.
Коллекции и события COM-объектов
Обход коллекций
Коллекции COM-серверов (Workbooks, Worksheets, Documents) обходят двумя способами.
- 🔁 Конструкцией
Для Каждого Лист Из Книга.Worksheets Цикл— платформа поддерживает перебор COM-коллекций. - 🔢 По индексу:
Для Н = 1 По Книга.Worksheets.Count Цикл Лист = Книга.Worksheets(Н); .... У Office нумерация с единицы, в отличие от коллекций 1С.
Если в цикле элементы удаляются (например, лишние листы книги), идите с конца, иначе индексы сдвинутся и каждый второй лист останется:
Всего = Книга.Worksheets.Count;
Для Сч = 0 По Всего - 2 Цикл
Книга.Worksheets(Всего - Сч).Delete(); // оставляем первый лист
КонецЦикла;
При пяти листах цикл удалит листы с номерами 5, 4, 3 и 2.
События
Некоторые COM-серверы сообщают о событиях: закрытие документа, поступление данных от оборудования. Обработчик подключают командой ДобавитьОбработчик Объект.ИмяСобытия, ИмяПроцедуры;, а отключают УдалитьОбработчик. Процедура-обработчик должна принимать параметры в том порядке, в каком их передаёт COM-сервер, — он описан в документации приложения.
На практике событиями пользуются редко. Для торгового оборудования современные драйверы подключаются через подсистему подключаемого оборудования, а не через «голый» COM. Для Office обычно хватает последовательного кода без подписок.
Типичные ошибки при работе с COM в 1С
Если Excel уже «завис» в процессах на сервере 1С, снимать задачи EXCEL.EXE безопасно для самой базы, но оборвётся выгрузка, которую сейчас делает другой пользователь. Делайте это, когда никто не запускал выгрузок, или предупредите коллег.
COM или другие способы интеграции: что выбрать
COM удобен, но привязывает решение к Windows и к установленным программам. Во многих задачах есть штатная замена без этих ограничений.
| Задача | Через COM | Альтернатива | Когда альтернатива лучше |
|---|---|---|---|
| Выгрузить таблицу в Excel | Excel.Application | ТабличныйДокумент.Записать в формате xlsx | Нужна просто таблица без макросов и сложных формул |
| Загрузить данные из Excel | Чтение через Range.Value | ТабличныйДокумент.Прочитать | Сервер на Linux, у пользователей нет Office |
| Получить данные другой базы 1С | V83.COMConnector | HTTP-сервис, стандартный интерфейс OData, обмен через план обмена | Базы в разных сетях, нужна постоянная синхронизация |
| Запрос к внешней SQL-базе | ADODB.Connection | Внешние источники данных | Нужен доступ из запросов 1С и отчётов |
| Работа с файлами и папками | Scripting.FileSystemObject | Файл, НайтиФайлы, КопироватьФайл | Почти всегда: встроенные средства кроссплатформенны |
| Подключить оборудование | Драйвер-COM | Внешняя компонента Native API | Нужна работа в веб-клиенте и на Linux |
Правило выбора простое. Если результат должен работать у всех пользователей и на любом сервере, выбирайте встроенные средства. COM оставляйте там, где без конкретного приложения не обойтись: печать сложного шаблона Word, макросы Excel, старый драйвер, у которого нет другой версии.
Безопасность и скорость кода с COM-объектами
Безопасность
- 🔒 Безопасный режим. Внешние обработки и расширения, подключённые в безопасном режиме, создавать COM-объекты не могут. Разрешение дают через профили безопасности кластера или снятием безопасного режима — решение принимает администратор.
- 👤 Отдельный пользователь для COMConnector. Не подключайтесь под администратором базы. Заведите пользователя с ролью только на нужные объекты и правом внешнего соединения.
- 🗝 Пароль не в коде. Строку подключения с паролем не храните в тексте модуля: её видит каждый, кто откроет конфигуратор. Держите параметры в защищённом хранилище или константе с ограниченным доступом.
- 🖥 Office на сервере. Microsoft не поддерживает автоматизацию Office из серверных служб без интерактивного пользователя: возможны зависания на диалогах и ошибки прав. Не стройте регламентные задания на
Excel.Applicationна рабочем сервере 1С — используйте табличный документ.
Скорость
- ⚡ Читайте и пишите диапазонами, а не ячейками: заполненный двумерный
COMSafeArray, присвоенныйRange.Value, записывается в лист одним вызовом. - 👁 Держите
Excel.Visible = ЛожьиExcel.ScreenUpdating = Ложьна время заполнения, иначе Excel перерисовывает окно на каждое изменение. - 🔁 Не вызывайте длинные цепочки
Книга.Worksheets(1).Cells(Стр, 1)в цикле. Сохраните лист в переменную один раз. - 🔌 Для COMConnector одно соединение на весь сеанс обработки. Каждый новый
Connectоткрывает сеанс в целевой базе, а это секунды.