Почему серверная процедура с COM-объектом Excel зависает или выполняется циклически?

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

При разработке сложных систем интеграции часто возникает необходимость использовать мощные расчетные механизмы MS Excel из среды 1С. Однако при переносе работающего кода из файловой базы в клиент-серверный вариант программисты сталкиваются с аномалиями: процедуры начинают выполняться «бесконечно», серверные процессы зависают, а пользователь получает загадочные ошибки POST или обрывы соединения. Рассмотрим подробнее, почему это происходит и как правильно организовать работу с COM-объектами на стороне сервера.

Разбор ситуации: Почему возникает иллюзия «цикла»?

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

  1. Тайм-ауты веб-сервера (IIS или Apache). Если ваша база опубликована, и серверная процедура выполняется слишком долго (например, из-за медленных расчетов в Excel), веб-сервер разрывает соединение по тайм-ауту. Клиентское приложение или прокси-сервер может автоматически повторить запрос, что выглядит в отладчике как повторный вход в ту же процедуру.
  2. Перезапуск рабочих процессов 1С. В консоли администрирования часто настроены лимиты по памяти. Работа с Excel.Application потребляет значительные ресурсы, особенно при работе с большими числами (миллиардами). Если лимит превышен, сервер принудительно завершает процесс rphost и запускает новый, что прерывает выполнение кода в непредсказуемой точке.
  3. Ошибки в блоках исключений. Обратите внимание на код автора: пустые блоки Исключение без логирования позволяют коду «проглатывать» критические ошибки, из-за чего выполнение может идти по неверному пути, создавая видимость зацикливания.

Проблема «Миллиардов» и метод GoalSeek

Выясним причину, по которой проблема проявляется именно на больших суммах. В представленном коде используется метод GoalSeek (подбор параметра). Это численный итерационный алгоритм Excel. При передаче миллиардных значений и малых шагов расчета алгоритм может не сойтись к решению за стандартное количество итераций. Excel уходит в глубокие вычисления, загружая процессор на 100%, и перестает отвечать на вызовы COM-интерфейса от 1С. Сервер 1С при этом «ждет» ответа, что приводит к зависанию сеанса.

Также важно учитывать региональные настройки сервера. Если на сервере разделитель дробной части отличается от того, который ожидает Excel, число может быть интерпретировано неверно, что сломает логику формул.

Настройка окружения для Excel на сервере

Работа с Excel через COM на стороне сервера официально не поддерживается Microsoft, так как офисные приложения спроектированы для интерактивного использования. Чтобы сервер 1С мог корректно запустить Excel под системной учетной записью, выполним следующие шаги:

Шаг 1. Создание папок Desktop

Это самая частая причина «необъяснимых» зависаний. Для работы Excel под профилем System необходимо вручную создать следующие директории:

Без этих папок многие методы COM-объекта (например, Open или Save) будут блокировать процесс ожиданием несуществующего интерфейса.

Шаг 2. Настройка DCOM

Рассмотрим настройку прав доступа. Через утилиту dcomcnfg (Службы компонентов) найдите Microsoft Excel Application. В свойствах на вкладке «Безопасность» необходимо предоставить права на «Запуск и активацию» и «Доступ» пользователю, от имени которого запущен Агент сервера 1С:Предприятие (обычно это USR1CV8).

Оптимизация кода: отказ от построчной записи

Проанализируем фрагмент кода автора, который вызывает наибольшие задержки:


Для Каждого СтрДанные Из Объект.ТабличнаяЧасть Цикл
    Таб.Cells(Стр,1).Value = СтрДанные.ДатаРасчета;
    // ... еще много обращений к Cells
    Стр = Стр + 1;
КонецЦикла;

На сервере каждое обращение к Cells(Стр, Кол).Value — это отдельный дорогостоящий RPC-вызов между процессом 1С и процессом Excel. При сотнях строк это создает колоссальные задержки. Рекомендуется использовать выгрузку данных одним массивом через объект SafeArray.

Посмотрим на пример правильной передачи данных:


// Создаем массив данных в 1С
МассивДанных = Новый Массив(Объект.ТабличнаяЧасть.Количество(), 7);
Для Индекс = 0 По Объект.ТабличнаяЧасть.Количество() - 1 Цикл
    СтрТЧ = Объект.ТабличнаяЧасть[Индекс];
    МассивДанных[Индекс][0] = СтрТЧ.ДатаРасчета;
    // Заполняем остальные колонки...
КонецЦикла;

// Передаем весь массив в Excel одним вызовом
Область = Таб.Range(Таб.Cells(16, 1), Таб.Cells(16 + Объект.ТабличнаяЧасть.Количество() - 1, 7));
Область.Value = МассивДанных;

Такой подход ускоряет работу в десятки раз и снижает вероятность обрыва соединения по тайм-ауту.

Правильное завершение работы с COM

Одной из причин деградации сервера является накопление процессов EXCEL.EXE в памяти. Если в коде произошла ошибка, и мы не закрыли объект, процесс останется «висеть». Обязательно используйте конструкцию Попытка...Исключение с гарантированным закрытием приложения:


ExcelПриложение = Новый COMОбъект("Excel.Application");
Попытка
    // Основной код работы с файлом
    // ...
Исключение
    Сообщить("Произошла ошибка: " + ОписаниеОшибки());
КонецПопытки;

// Блок гарантированного закрытия
Если ExcelПриложение <> Неопределено Тогда
    ExcelПриложение.Quit();
    ExcelПриложение = Неопределено;
КонецЕсли;

Альтернатива: Использование встроенных средств 1С

Если задача сводится к чтению данных или записи простых формул, лучше полностью отказаться от COM в пользу встроенного объекта ТабличныйДокумент. Начиная с версии 8.3, 1С умеет читать и записывать файлы .xlsx напрямую, без установленного Excel.

Рассмотрим преимущества этого метода:

Пример чтения файла без Excel:


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
// Теперь мы можем обойти ячейки ТабДок как обычную таблицу

Подведем итог. Проблема автора вызвана сочетанием тяжелых вычислений GoalSeek на больших числах и нестабильностью COM-соединения на сервере. Для решения необходимо либо настроить окружение (папки Desktop, DCOM), либо оптимизировать передачу данных через массивы, либо (что предпочтительнее) перевести расчеты на сторону 1С или использовать ТабличныйДокумент для обмена данными.

← На главную