Как открыть и прочитать файл Excel на сервере 1С: решаем проблему COM-объектов и прав доступа

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

Работа с файлами Microsoft Excel в клиент-серверном варианте работы 1С часто преподносит сюрпризы. Программисты сталкиваются с тем, что код, идеально работающий на локальном компьютере («на файле»), внезапно выдает ошибки при переносе в серверный контекст. Ошибка «Sorry, we couldn't find...» или «Не удалось создать COM-объект» становится настоящей головной болью.

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

Причина проблемы: почему COM-объект не видит файл

Разберем ситуацию, когда при вызове метода Open возникает исключительная ситуация. Основная причина кроется в том, что серверный процесс 1С (обычно запущенный под пользователем USR1CV8) работает в изолированном сеансе. Для него пути типа D:\Выгрузка\doc.xls могут быть либо недоступны из-за прав доступа, либо этот путь ведет на локальный диск сервера, в то время как файл находится на компьютере пользователя.

Кроме того, Microsoft Excel — это интерактивное приложение. Оно не предназначено для работы в фоновом режиме на сервере. Рассмотрим основные пути решения этой задачи.

Способ 1. Использование встроенного объекта ТабличныйДокумент (Рекомендуется)

Это самый современный и эффективный метод. Начиная с версии 8.3, 1С умеет читать файлы .xlsx и .xls напрямую, не используя установленный Microsoft Office. Это избавляет от необходимости настраивать DCOM и покупать лицензии на Office для сервера.

Проанализируем пример кода, который позволяет прочитать файл на сервере:


&НаСервере
Процедура ПрочитатьЭксельНаСервере(ПутьКФайлу)
    // Создаем объект табличного документа
    ТД = Новый ТабличныйДокумент;
    
    Попытка
        // Читаем файл. Второй параметр указывает на способ чтения значений
        ТД.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
    Исключение
        Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // Далее работаем с ТД как с обычной таблицей
    Для НомерСтроки = 1 По ТД.ВысотаТаблицы Цикл
        Значение = ТД.Область(НомерСтроки, 1).Текст;
        // Обработка данных...
    КонецЦикла;
КонецПроцедуры

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

  1. Скорость: Работает значительно быстрее, чем запуск тяжелого приложения Excel через COM.
  2. Стабильность: Нет риска зависания процесса excel.exe в памяти сервера.
  3. Автономность: Не требует наличия установленного Excel на стороне сервера.

Способ 2. Передача файла через временное хранилище

Если вы все же решили использовать серверные процедуры для обработки файла, помните: сервер не имеет прямого доступа к файлам на вашем локальном диске C:. Файл необходимо сначала «передать» на сервер.

Рассмотрим по шагам, как это реализовать:

  1. На клиенте выбираем файл и помещаем его во временное хранилище.
  2. Передаем адрес хранилища на сервер.
  3. На сервере извлекаем файл из хранилища во временный файл и обрабатываем его.

&НаКлиенте
Процедура ВыгрузитьФайл(Команда)
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Если Диалог.Выбрать() Тогда
        ДанныеФайла = Новый ДвоичныеДанные(Диалог.ПолноеИмяФайла);
        АдресХранилища = ПоместитьВоВременноеХранилище(ДанныеФайла, УникальныйИдентификатор);
        ОбработатьФайлНаСервере(АдресХранилища);
    КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ОбработатьФайлНаСервере(АдресХранилища)
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xls");
    Данные.Записать(ИмяВременногоФайла);
    
    // Теперь файл физически есть на диске сервера, и его можно открыть
    // Например, через ТабличныйДокумент или COM (если он настроен)
    ТД = Новый ТабличныйДокумент;
    ТД.Прочитать(ИмяВременногоФайла);
    
    УдалитьФайлы(ИмяВременногоФайла); // Не забываем чистить за собой
КонецПроцедуры

Способ 3. Настройка окружения для COM-объекта (если Excel необходим)

Бывают случаи, когда нужно использовать специфические функции Excel (макросы, сложное форматирование), которые не поддерживает ТабличныйДокумент. В этом случае придется настраивать сервер.

Выясним причину, по которой Excel часто выдает ошибку на сервере даже при наличии прав. Для корректной инициализации COM-объекта Excel под системной учетной записью необходимо наличие папок Desktop. Выясним, где их нужно создать:

Важно: У пользователя, под которым запускается сервер 1С, должны быть полные права на эти папки. Без этого Excel.Application может просто не стартовать в фоновом сеансе.

Способ 4. Передача данных между контекстами (ТЗ на Клиент)

Часто возникает вопрос: как обработать данные на сервере (так как там запросы и база), а потом передать их в Excel на клиенте (так как Excel установлен только у пользователя)? Напрямую объект ТаблицаЗначений передать на клиент нельзя.

Рассмотрим наиболее надежный метод — преобразование ТЗ в массив структур:


&НаСервере
Функция ПолучитьДанныеДляExcel()
    Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Код, Наименование ИЗ Справочник.Номенклатура ГДЕ ... ");
    ТЗ = Запрос.Выполнить().Выгрузить();
    
    МассивРезультат = Новый Массив;
    Для Каждого СтрокаТЗ Из ТЗ Цикл
        СтруктураСтроки = Новый Структура;
        Для Каждого Колонка Из ТЗ.Колонки Цикл
            СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
        КонецЦикла;
        МассивРезультат.Добавить(СтруктураСтроки);
    КонецЦикла;
    
    Возврат МассивРезультат;
КонецФункции

&НаКлиенте
Процедура СформироватьExcel(Команда)
    Данные = ПолучитьДанныеДляExcel();
    
    Excel = Новый COMОбъект("Excel.Application");
    Книга = Excel.Workbooks.Add();
    Лист = Книга.Sheets(1);
    
    НомерСтроки = 1;
    Для Каждого СтрокаДанных Из Данные Цикл
        Лист.Cells(НомерСтроки, 1).Value = СтрокаДанных.Наименование;
        Лист.Cells(НомерСтроки, 2).Value = СтрокаДанных.Код;
        НомерСтроки = НомерСтроки + 1;
    КонецЦикла;
    
    Excel.Visible = Истина;
КонецПроцедуры

Использование массива структур позволяет легко обходить ограничения контекстов 1С. Также можно использовать Временное хранилище для передачи больших таблиц значений, как было предложено в обсуждении темы. В этом случае на сервере мы помещаем ТЗ в хранилище, а на клиенте в цикле запрашиваем данные порциями (строками), чтобы не перегружать память.

Советы по оптимизации

Проанализируем еще несколько важных моментов при работе с Excel на сервере:

Подведем итог: если ваша задача — просто прочитать данные из файла, используйте ТабличныйДокумент. Это избавит вас от 90% технических проблем с правами доступа и настройкой DCOM. Если же требуется сложная генерация отчета по шаблону на стороне клиента, используйте передачу данных через Массив структур или Временное хранилище.

← На главную