При программной работе с документами Microsoft Excel из 1С с помощью механизмов COM (Excel.Application) программисты часто сталкиваются с ситуацией, когда после выполнения кода процесс EXCEL.EXE продолжает висеть в диспетчере задач Windows. Это может приводить к блокировке файлов, нехватке оперативной памяти и сбоям при повторном запуске обменов.
В этой статье мы подробно проанализируем причины возникновения этой проблемы и разберем практические способы корректного завершения работы с Excel в 1С.
Рассмотрим, почему операционная система не завершает процесс Excel даже после вызова метода Quit():
Workbooks, Worksheets, Cells, Range), система удерживает эти COM-объекты в памяти. Пока счетчик ссылок на каждый объект не обнулится, процесс EXCEL.EXE не закроется.DisplayAlerts = 0), процесс зависает в ожидании ответа.Проанализируем базовый способ решения проблемы. Недостаточно просто вызвать метод Quit() для главного объекта приложения. Необходимо последовательно очистить ссылки на все созданные промежуточные объекты — листы, книги и сам COM-объект, присвоив им значение Неопределено.
Разберем по шагам правильную последовательность действий в коде:
Эксель = Новый COMОбъект("Excel.Application");
Книга = Эксель.WorkBooks.Add();
Лист = Книга.WorkSheets(1);
// Выполнение операций с файлом
Лист.Cells(1, 1).Value = "Заголовок";
Попытка
Книга.SaveAs(Путь_SRC_OUT_PAYMENT);
Исключение
Сообщить(ОписаниеОшибки() + " Файл не сохранен!");
КонецПопытки;
// Отключаем интерактивные предупреждения
Эксель.DisplayAlerts = 0;
// Закрываем рабочую книгу без сохранения повторных запросов
Книга.Close(Ложь);
// Завершаем работу приложения Excel
Эксель.Quit();
// Обязательно обнуляем все переменные COM-объектов
Лист = Неопределено;
Книга = Неопределено;
Эксель = Неопределено;
Важный момент: Присвоение 0 вместо Неопределено (как в выражении Эксель = 0) не всегда приводит к немедленному уничтожению COM-ссылки в платформе 1С. Используйте именно Неопределено.
Рассмотрим еще один надежный подход. Посмотрим, как работает область видимости переменных в 1С: при выходе из процедуры все ее локальные переменные автоматически уничтожаются, а удерживаемые ими COM-ссылки освобождаются платформой.
Спроектируем архитектуру взаимодействия через отдельные функции подключения и отключения связей:
Функция EXCELУстановитьСвязь(ИмяФайла) Экспорт
Результат = Новый Соответствие;
Попытка
BaseOLE = Новый COMОбъект("Excel.Application");
ExcelФайл = BaseOLE.WorkBooks.Open(ИмяФайла);
Результат.Вставить("EXCEL", BaseOLE);
Результат.Вставить("ExcelФайл", ExcelФайл);
Исключение
Сообщить("Ошибка создания объекта Microsoft Excel: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
Возврат Результат;
КонецФункции
Процедура EXCELРазорватьСвязь(СоответствиеCOM) Экспорт
Попытка
СоответствиеCOM["EXCEL"].DisplayAlerts = 0;
СоответствиеCOM["ExcelФайл"].Close(Ложь);
СоответствиеCOM["EXCEL"].Quit();
СоответствиеCOM.Вставить("ExcelФайл", Неопределено);
СоответствиеCOM.Вставить("EXCEL", Неопределено);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если код с Excel.Application выполняется в серверном модуле под системной учетной записью (например, SYSTEM или usr1cv8), вы можете столкнуться с тем, что Excel не может корректно инициализировать пользовательский профиль.
Для устранения подвисаний на 64-разрядных серверах Windows необходимо убедиться в наличии следующих системных каталогов:
C:\Windows\System32\config\systemprofile\DesktopC:\Windows\SysWOW64\config\systemprofile\DesktopУчетная запись, от имени которой запущен сервис 1С (rphost), должна иметь полные права на чтение и запись в эти папки.
Чтобы гарантированно избежать проблем с висящими процессами EXCEL.EXE, рекомендуем по возможности отказаться от технологии COM в пользу штатных возможностей платформы 1С. Объект ТабличныйДокумент позволяет формировать и сохранять файлы формата XLSX на любых операционных системах (включая Linux) без установки Microsoft Office.
Пример сохранения через табличный документ:
ТабДок = Новый ТабличныйДокумент;
// Заполнение табличного документа данными...
// Сохранение в файл Excel без использования COM
ТабДок.Записать(Путь_SRC_OUT_PAYMENT, ТипФайлаТабличногоДокумента.XLSX);
Этот способ работает намного быстрее, не требует управления сторонними процессами в ОС и полностью исключает утечки ресурсов.