Работа с COM в 1С 8.3: Excel, Word, внешнее соединение и типичные сбои

· 10 мин

Содержание

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"):

  1. 🔎 Платформа ищет в реестре Windows строку Word.Application (её называют ProgID) и по ней находит класс.
  2. 🚀 Windows запускает сервер: отдельный процесс (WINWORD.EXE) или загружает DLL прямо в процесс 1С.
  3. 🔗 1С получает ссылку на объект и оборачивает её в тип COMОбъект.
  4. 📞 Каждое обращение Word.Documents.Open(...) уходит в COM-сервер через позднее связывание: имена методов ищутся по ходу выполнения, поэтому опечатка проявится только при запуске.

Отсюда два практических следствия. Первое: COM-объект создаётся на том компьютере, где выполняется код. Процедура с директивой &НаКлиенте запустит Excel у пользователя, &НаСервере — на сервере 1С. Второе: каждое обращение к свойству — это вызов между процессами, а значит, тысяча обращений в цикле заметно медленнее, чем одно обращение за всем диапазоном сразу.

Где выполняется кодCOM доступенЧто учесть
Тонкий клиент на WindowsДаНужна программа на компьютере пользователя
Толстый клиент на WindowsДаТо же
Сервер 1С на WindowsДаРаботает под учётной записью службы, без рабочего стола
Веб-клиентНетВынесите логику на сервер или используйте другой способ
Клиент или сервер на Linux, macOSНетТолько альтернативы: файлы, HTTP, OData

В файловом варианте базы серверный контекст выполняется в процессе самого клиента. Поэтому &НаСервере в файловой базе тоже запускает Excel на компьютере пользователя. После перехода на клиент-серверный вариант тот же код начнёт создавать Excel уже на сервере.

Как создать COM-объект в 1С: порядок действий

Схема одинакова для любого приложения.

  1. Убедитесь, что программа установлена там, где выполнится код. Для Excel на клиенте — Excel на рабочем месте пользователя.
  2. Узнайте ProgID. Для популярных программ они известны: Excel.Application, Word.Application, Outlook.Application, WScript.Shell, Scripting.FileSystemObject, ADODB.Connection. Для оборудования ProgID указан в документации драйвера.
  3. Создайте объект в Попытка, чтобы отсутствие программы не обрушило всю процедуру.
  4. Работайте через методы и свойства из документации самого приложения (для Office — объектная модель VBA). Имена пишутся латиницей, как в VBA.
  5. Закройте приложение и освободите ссылку. Для 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АльтернативаКогда альтернатива лучше
Выгрузить таблицу в ExcelExcel.ApplicationТабличныйДокумент.Записать в формате xlsxНужна просто таблица без макросов и сложных формул
Загрузить данные из ExcelЧтение через Range.ValueТабличныйДокумент.ПрочитатьСервер на Linux, у пользователей нет Office
Получить данные другой базы 1СV83.COMConnectorHTTP-сервис, стандартный интерфейс 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 открывает сеанс в целевой базе, а это секунды.
Перед запуском обработки с COM у пользователей
Выполнено: 0 / 6

Частые вопросы о COM-объектах

Можно ли использовать COM-объект в веб-клиенте 1С?
Нет. Тип COMObject в веб-клиенте недоступен. Выполняйте код на сервере 1С под Windows или замените COM встроенными средствами платформы.
Чем V83.COMConnector отличается от V83.Application?
COMConnector открывает внешнее соединение без интерфейса: только данные и программный код. V83.Application запускает полноценный клиент 1С как COM-сервер, он тяжелее и нужен, когда требуется выполнить клиентский код или формы.
Нужно ли перерегистрировать comcntr.dll после обновления платформы?
Да, если старая версия платформы удалена или вы хотите работать через новую. Регистрация привязана к пути DLL конкретной версии, поэтому после удаления старого каталога COMConnector перестанет создаваться.
Как узнать ProgID программы, если его нет в документации?
Посмотрите ветку HKEY_CLASSES_ROOT в редакторе реестра: ProgID — это подразделы вида Программа.Объект с вложенным ключом CLSID. Вносить изменения в реестр для этого не нужно, достаточно поиска.
Почему код с COM работал в файловой базе, а после переноса на сервер перестал?
В файловой базе серверный код выполнялся на компьютере пользователя, где установлен Office. На сервере 1С программы может не быть, а служба работает под другой учётной записью без нужных прав.