Как избавиться от диалога сохранения и победить зависание ПолучитьCOMОбъект при работе с Excel в 1С 8.3 на сервере?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации загрузки данных из файлов Excel (особенно с расширением .xlsx) разработчики часто используют COM-соединение. Однако при работе на стороне сервера этот подход преподносит неприятные сюрпризы. Программа может неожиданно выдать диалоговое окно с предложением сохранить изменения, либо выполнение серверного кода полностью зависает на вызове функции ПолучитьCOMОбъект.

В этой статье мы подробно разберем природу обеих проблем, найдем способы их устранения при работе через COM, а также рассмотрим наиболее современный, быстрый и безопасный альтернативный вариант чтения файлов Excel без использования сторонних приложений на сервере.

Часть 1. Как исключить появление диалоговых окон и вопросов о сохранении

Даже если мы открываем файл Excel исключительно для чтения данных и программно ничего в него не записываем, Microsoft Excel при закрытии книги может выдать интерактивный запрос: "Сохранить изменения в файле?". Это происходит из-за того, что при открытии документа Excel автоматически пересчитывает «летучие» формулы (например, функции СЕГОДНЯ(), ТДАТА()), обновляет внешние связи или переводит структуру файла в режим совместимости. На сервере этот невидимый диалог приводит к вечному ожиданию ответа пользователя, из-за чего сеанс зависает.

Давайте проанализируем четыре надежных способа предотвращения этого поведения в коде 1С:

  1. Принудительная установка флага "Сохранено" (свойство Saved)

    Мы можем программно «обмануть» Excel, сообщив ему, что все изменения в книге уже сохранены. Для этого перед закрытием файла необходимо установить свойство Saved в значение Истина. Рассмотрим пример кода:

    
    // Предположим, что Док — это полученный COM-объект книги Excel
    Док.Saved = Истина;
    Док.Application.Quit();
    
  2. Отключение системных предупреждений приложения (DisplayAlerts)

    Если мы работаем с объектом всего приложения Excel (Excel.Application), мы можем глобально запретить вывод любых предупреждений и диалоговых окон. В этом случае Excel автоматически принимает решение по умолчанию (закрывает документ без сохранения изменений):

    
    ЭксельПриложение = ПолучитьCOMОбъект("", "Excel.Application");
    ЭксельПриложение.DisplayAlerts = Ложь; // Отключаем все интерактивные вопросы
    // Выполняем чтение данных...
    ЭксельПриложение.Quit();
    
  3. Параметры метода закрытия книги Close()

    Метод Close объекта книги (Workbook) принимает несколько необязательных параметров. Первый параметр указывает, нужно ли сохранять изменения перед закрытием. Передав в него значение Ложь (или 0), мы гарантируем закрытие без лишних вопросов:

    
    // Закрываем конкретную книгу без сохранения изменений
    Док.Close(Ложь);
    
  4. Открытие файла в режиме "Только для чтения" (ReadOnly)

    Если файл изначально открывается через метод Open коллекции книг Workbooks, хорошей практикой является явное указание третьего параметра в значение Истина (режим ReadOnly):

    
    ПутьКФайлу = "C:\Temp\MyFile.xlsx";
    ЭксельПриложение = Новый COMОбъект("Excel.Application");
    Книга = ЭксельПриложение.Workbooks.Open(ПутьКФайлу, , Истина);
    // Работаем с файлом...
    Книга.Close(Ложь);
    ЭксельПриложение.Quit();
    

Часть 2. Почему зависает ПолучитьCOMОбъект на сервере и как это исправить

Зависание процесса выполнения на строке ПолучитьCOMОбъект(ВременныйФайлПоступлений) — классическая серверная проблема. При локальной работе под правами администратора на рабочем компьютере все работает отлично, но на серверной ОС Windows служба сервера 1С запускается в изолированном окружении. Выясним основные технические причины этого сбоя:

Причина 1: Отсутствие системных каталогов профиля Windows (Desktop)

Служба сервера 1С:Предприятия обычно работает под специальной системной учетной записью (например, USR1CV8 или NetworkService). При инициализации COM-объекта Microsoft Excel пытается обратиться к папкам рабочего стола (Desktop) внутри профиля пользователя. Если этих папок физически не существует в системном профиле, процесс excel.exe зависает в бесконечном цикле ожидания.

Чтобы решить эту проблему, выполним следующие шаги:

Причина 2: «Зависшие» фоновые процессы excel.exe

Если во время предыдущих запусков импорта данных произошла ошибка, или код 1С аварийно завершился до вызова метода Quit(), то в операционной системе сервера остаются висеть скрытые процессы excel.exe. Они монополизируют доступ к ресурсам и блокируют новые обращения через COM.

Решение: откройте Диспетчер задач Windows на сервере, перейдите на вкладку "Подробности" (Details), найдите все процессы excel.exe, запущенные от имени системных учетных записей или пользователя 1С, и принудительно завершите их.

Причина 3: Настройки безопасности DCOM

Иногда операционная система блокирует запуск COM-сервера Excel из-под учетной записи службы 1С. Для исправления ситуации запустите утилиту настройки системных компонентов (нажмите Win+R, введите dcomcnfg и нажмите Enter). Перейдите по пути: Службы компонентов -> Компьютеры -> Мой компьютер -> Настройка DCOM. Найдите в списке Microsoft Excel Application, откройте свойства и на вкладке "Безопасность" настройте права на запуск и активацию для пользователя службы сервера 1С.

Часть 3. Радикальное и самое надежное решение: отказ от COM в пользу ТабличногоДокумента

Использование COM-объектов на сервере несет огромные риски стабильности: падение производительности, утечки памяти, зависимость от установленного пакета MS Office и жесткая привязка к операционной системе Windows. К счастью, платформа 1С:Предприятие 8.3 имеет встроенный функционал, позволяющий полностью отказаться от COM при чтении файлов .xlsx.

Объект ТабличныйДокумент в современных версиях платформы умеет напрямую импортировать файлы Excel без привлечения стороннего ПО. Давайте рассмотрим готовый и лаконичный пример, как прочитать данные из временного хранилища на сервере без создания COM-объектов:


&НаСервере
Процедура РаботаСФайламиНаСервере(АдресСтрокиДвоичныхДанных)
    
    // Получаем двоичные данные файла из временного хранилища
    СерверныеПоступленияДанные = ПолучитьИзВременногоХранилища(АдресСтрокиДвоичныхДанных);
    
    // Создаем имя временного файла на сервере
    ВременныйФайлПоступлений = ПолучитьИмяВременногоФайла("xlsx");
    
    // Записываем полученные данные во временный файл
    СерверныеПоступленияДанные.Записать(ВременныйФайлПоступлений);    
    
    // Инициализируем ТабличныйДокумент 1С
    ТабДок = Новый ТабличныйДокумент;
    
    Попытка
        // Напрямую читаем файл Excel средствами платформы
        ТабДок.Прочитать(ВременныйФайлПоступлений, СпособЧтенияЗначенийТабличногоДокумента.Значение);
    Исключение
        ЗаписьЖурналаРегистрации("ИмпортФайла", УровеньЖурналаРегистрации.Ошибка, , , 
            "Не удалось прочитать файл Excel: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Удаляем временный файл с диска сразу после прочтения, чтобы не засорять систему
    Попытка
        УдалитьФайлы(ВременныйФайлПоступлений);
    Исключение
        // Ошибка удаления не критична для процесса
    КонецПопытки;
    
    // Теперь мы можем обойти строки и колонки файла как обычную таблицу 1С!
    КоличествоСтрок = ТабДок.ВысотаТаблицы;
    КоличествоКолонок = ТабДок.ШиринаТаблицы;
    
    Для НомерСтроки = 1 По КоличествоСтрок Цикл
        // Проанализируем, например, значение первой колонки
        ЗначениеЯчейки = ТабДок.Область(НомерСтроки, 1).Текст;
        
        Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда
            // Обрабатываем данные строки...
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Этот подход обладает колоссальными преимуществами:

Используйте встроенные механизмы платформы 1С для работы с файлами — это значительно упростит поддержку и сделает вашу информационную базу стабильной и быстродействующей!

← На главную