Перенос внешних обработок из файлового варианта базы данных в клиент-серверный часто преподносит неприятные сюрпризы. Классический сценарий: обработка загрузки данных из Excel, которая годами отлично работала на локальном компьютере пользователя, при попытке выполнить её на сервере 1С просто «зависает» или завершается без видимых ошибок. При этом визуально ничего не происходит, а стандартная отладка «не заходит» в серверный код.
В этой статье мы подробно разберем, почему возникает эта проблема, как правильно настроить окружение сервера для работы с COM-объектами MS Office, и как полностью избавиться от этой зависимости, переписав код на современные нативные механизмы платформы 1С:Предприятие.
Давайте проанализируем исходный код серверной функции, предоставленный автором темы:
&НаСервере
Функция ВыполнитьЗагрузкуНаСервере(АдресХранения);
Путь = КаталогВременныхФайлов + "temp1.xls";
Файл = ПолучитьИзВременногоХранилища(АдресХранения);
Файл.Записать(Путь);
Попытка
ОбъектExcel = Новый COMОбъект("Excel.Application");
Исключение
Возврат "Ошибка открытия MS Excel";
КонецПопытки;
...
КонецФункции
В ходе обсуждения на форуме было установлено, что обработка прекращает свою работу именно на строке инициализации COM-объекта: Новый COMОбъект("Excel.Application").
Когда вы запускаете обработку на локальном компьютере (на клиенте), 1С работает под управлением вашей учетной записи Windows. У вас есть права администратора (или пользователя), запущен интерактивный сеанс, настроен профиль, и Excel без проблем открывается в фоновом режиме. Но как только выполнение переходит на сервер приложений 1С:Предприятия, ситуация кардинально меняется:
USR1CV8) работает в изолированном системном сеансе (Session 0). MS Excel изначально не проектировался для работы в качестве серверного компонента без пользовательского интерфейса. При запуске в неинтерактивной среде он часто блокируется операционной системой.rphost.exe с 32-битным COM-сервером Excel.USR1CV8 этой папки по умолчанию нет.Рассмотрим по шагам, как решить каждую из этих проблем.
Для того чтобы точно локализовать ошибку и видеть, что происходит в процедурах с директивой &НаСервере, нам необходимо активировать отладку на сервере приложений. Давайте разберем, как это сделать:
services.msc).regedit и нажмите Enter.[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\1C:Enterprise 8.3 Server Agent\] ImagePath. Он содержит команду запуска службы.-debug. "C:\Program Files\1cv8\8.3.22.1709\bin\ragent.exe" -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d "C:\Program Files\1cv8\srvinfo""C:\Program Files\1cv8\8.3.22.1709\bin\ragent.exe" -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d "C:\Program Files\1cv8\srvinfo" -debugТеперь точки останова, установленные в серверном коде обработки, будут успешно срабатывать.
Если на сервере установлен 64-битный сервер 1С и 32-битный Microsoft Office (или наоборот), вам необходимо настроить связь между ними на уровне системных служб компонентов DCOM.
Для настройки взаимодействия откройте консоль управления службами компонентов. Если у вас разная разрядность ПО, обычный запуск через dcomcnfg может не показать Microsoft Excel в списке. Поэтому запустите консоль принудительно в 32-битном режиме с помощью команды:
mmc comexp.msc /32
После открытия консоли выполните следующие действия:
USR1CV8.USR1CV8) и предоставьте ему полные права (Локальный запуск, Локальная активация).Это самый неочевидный нюанс, из-за которого спотыкаются многие разработчики. Программа MS Excel при запуске инициализирует временные файлы в профиле пользователя Windows. Если папка Рабочего стола отсутствует в системном профиле, инициализация COM-объекта аварийно завершается без вывода диагностических сообщений.
Нам необходимо вручную создать эти папки на сервере приложений 1С. Создайте следующие каталоги в зависимости от архитектуры вашей операционной системы:
Для 64-разрядной операционной системы Windows:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopДля 32-разрядной операционной системы Windows:
C:\Windows\System32\config\systemprofile\DesktopВажно: После создания этих папок обязательно кликните по ним правой кнопкой мыши, перейдите в свойства безопасности и предоставьте учетной записи, под которой запускается сервер приложений 1С (например, USR1CV8 или Служба сетевого сервиса), права на чтение, запись и изменение данных в этих папках.
Использование COM-объекта Excel.Application на стороне сервера 1С считается устаревшим и крайне нестабильным подходом. Процессы excel.exe часто зависают в оперативной памяти сервера, блокируют файлы, вызывают утечки памяти и требуют покупки дорогостоящих серверных лицензий Microsoft Office.
Начиная с версии платформы 8.3.6, в 1С встроен мощный и быстрый механизм прямого чтения файлов форматов XLS, XLSX, ODS напрямую без использования установленного Microsoft Office. Это работает в десятки раз быстрее и абсолютно стабильно на любом сервере (включая Linux-серверы!).
Давайте перепишем серверный метод автора темы, исключив использование COM-объектов. Мы будем использовать объект платформы ТабличныйДокумент.
Ниже представлен готовый пример безопасного и быстрого чтения файла Excel на сервере:
&НаСервере
Функция ВыполнитьЗагрузкуНаСервереНативно(АдресХранения)
// Получаем файл из временного хранилища во временный каталог сервера
ПутьКФайлу = КаталогВременныхФайлов() + ПолучитьУникальныйИдентификатор() + ".xlsx";
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранения);
ДвоичныеДанныеФайла.Записать(ПутьКФайлу);
// Создаем объект ТабличныйДокумент для чтения файла без Excel
ТабДок = Новый ТабличныйДокумент;
Попытка
// Читаем файл. Платформа сама определит формат (XLS или XLSX)
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияДвумерныхДанных.ИмяФормата);
Исключение
УдалитьФайлы(ПутьКФайлу);
Возврат "Не удалось прочитать файл. Ошибка: " + ОписаниеОшибки();
КонецПопытки;
// Получаем размеры таблицы
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;
Если ВсегоСтрок < 2 Тогда
УдалитьФайлы(ПутьКФайлу);
Возврат "Файл пуст или содержит недостаточно данных для загрузки.";
КонецЕсли;
// Формируем структуру колонок по первой строке (заголовкам)
СоответствиеКолонок = Новый Соответствие;
Для НомерКолонки = 1 По ВсегоКолонок Цикл
ИмяКолонки = СокрЛП(ТабДок.Область(1, НомерКолонки).Текст);
Если ЗначениеЗаполнено(ИмяКолонки) Тогда
СоответствиеКолонок.Вставить(ВРег(ИмяКолонки), НомерКолонки);
КонецЕсли;
КонецЦикла;
// Обходим строки данных, начиная со 2-й строки
Для НомерСтроки = 2 По ВсегоСтрок Цикл
// Пример получения данных из конкретных колонок по их имени
ИндексОС = СоответствиеКолонок.Получить(ВРег("Основное средство"));
Если ИндексОС <> Неопределено Тогда
ЗначениеОС = ТабДок.Область(НомерСтроки, ИндексОС).Текст;
КонецЕсли;
ИндексДата = СоответствиеКолонок.Получить(ВРег("Дата принятия к учету"));
Если ИндексДата <> Неопределено Тогда
ЗначениеДатыТекст = ТабДок.Область(НомерСтроки, ИндексДата).Текст;
// Преобразуем текст в дату безопасным способом
КонецЕсли;
// Здесь выполняется логика создания документов и справочников, аналогичная исходному коду...
// Например:
// ДокОстаток = Документы.ВводНачальныхОстатковОС.СоздатьДокумент();
// ... заполнение и запись объекта ...
КонецЦикла;
// Обязательно удаляем временный файл после завершения работы
Попытка
УдалитьФайлы(ПутьКФайлу);
Исключение
// Игнорируем ошибку удаления, если файл занят
КонецПопытки;
Возврат "Загрузка успешно завершена!";
КонецФункции
Мы подробно проанализировали системные проблемы, препятствующие нормальной работе COM-соединения с Excel на сервере 1С. Если архитектура вашего решения жестко требует использования именно Excel.Application, то обязательным условием является создание папок Desktop в профиле systemprofile и тонкая настройка прав пользователей в утилите dcomcnfg.
Тем не менее, в рамках стандартов разработки 1С мы настоятельно рекомендуем отказаться от использования внешних COM-библиотек в пользу встроенного метода ТабличныйДокумент.Прочитать(). Это сделает вашу обработку кроссплатформенной, повысит скорость выполнения операций загрузки в несколько раз и гарантированно убережет сервер приложений от зависших фоновых процессов Excel.