При разработке механизмов загрузки данных из Excel в клиент-серверном варианте работы 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда код, прекрасно работающий в файловой базе или на клиенте, перестает выполняться на сервере. Одной из самых распространенных ошибок является сообщение: "Произошла исключительная ситуация (Microsoft Office Excel): Нет доступа к файлу... Имени файла или пути не существует".
Давайте разберем причины этой проблемы, проанализируем архитектурные особенности передачи файлов и рассмотрим два основных пути решения: использование встроенных средств платформы и настройку COM-объектов.
Прежде чем переходить к правкам кода или настройкам системы, необходимо четко понимать архитектуру взаимодействия.
Если пользователь выбирает файл на своем рабочем столе (например, C:\Users\User\Desktop\Data.xlsx), этот путь является локальным для компьютера клиента. Когда мы передаем эту строку (путь) на сервер, сервер пытается найти этот файл у себя по тому же пути. Естественно, на сервере в папке C:\Users\User\Desktop\ этого файла нет. Это первая причина ошибки.
Вторая причина, более специфичная для сообщения "Нет доступа", возникает, когда файл физически доступен серверу (например, лежит в сетевой папке), но служба сервера 1С (rphost), работающая от имени системной учетной записи (например, USR1CV8 или Local System), не имеет прав на взаимодействие с Excel или доступа к папке профиля для временных файлов.
Если ваша задача состоит только в чтении данных из файла (без сложного форматирования и сохранения), наиболее эффективным способом является отказ от использования COM-объекта Excel.Application. Платформа 1С умеет читать файлы Excel (xlsx, xls) напрямую.
Преимущества этого метода:
Рассмотрим код, который позволяет прочитать файл без использования COM:
Процедура ПрочитатьФайлБезExcel(ПутьКФайлуНаСервере)
// Создаем новый табличный документ
ТабДок = Новый ТабличныйДокумент;
Попытка
// Метод Прочитать сам определяет формат (xls или xlsx)
ТабДок.Прочитать(ПутьКФайлуНаСервере);
Исключение
Сообщить("Не удалось прочитать файл: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Подготовка таблицы для данных
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ТочкаВремени");
ТЗ.Колонки.Добавить("Сотрудник");
// Перебор строк табличного документа
// Начинаем со 2-й строки, если в первой заголовки
Для Сч = 2 По ТабДок.ВысотаТаблицы Цикл
НоваяСтрока = ТЗ.Добавить();
// Получаем область ячейки и берем её текст
НоваяСтрока.ТочкаВремени = ТабДок.ПолучитьОбласть(Сч, 1, Сч, 1).ТекущаяОбласть.Текст;
НоваяСтрока.Сотрудник = ТабДок.ПолучитьОбласть(Сч, 2, Сч, 2).ТекущаяОбласть.Текст;
КонецЦикла;
// Далее обрабатываем ТЗ...
КонецПроцедуры
Обратите внимание: метод ТабДок.Прочитать требует путь к файлу, который доступен серверу. О том, как доставить файл на сервер, мы поговорим ниже.
Если вам необходимо использовать именно COM-объект (например, для сохранения сложного форматирования или выполнения макросов), и вы получаете ошибку доступа, проблема часто кроется в отсутствии профиля рабочего стола для системного пользователя.
При запуске Excel в неинтерактивном режиме (под службой) он пытается обратиться к системным папкам. Если их нет, возникает исключение.
Что нужно сделать:
Для 64-разрядной (x64) системы создайте папку:
C:\Windows\System32\config\systemprofile\Desktop
Для 32-разрядной (x86) системы (или если установлен 32-битный Office на x64 системе) создайте папку:
C:\Windows\SysWOW64\config\systemprofile\Desktop
Важно: Даже если вы используете 64-битную ОС, но Excel 32-битный, необходимо создать папку именно в SysWOW64. Рекомендуется создать обе папки, чтобы гарантировать работоспособность.
После создания папок необходимо проверить права доступа к ним. У пользователя, от имени которого запущена служба сервера 1С, должны быть полные права на эти папки.
Независимо от выбранного метода чтения (через ТабличныйДокумент или COMОбъект), файл сначала нужно передать с компьютера пользователя на сервер 1С. Просто передать строковый путь вида "C:\" нельзя.
Давайте разберем правильный алгоритм действий:
Пример реализации:
1. Код на Клиенте (выбор и передача):
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
Если Диалог.Выбрать() Тогда
// Помещаем файл во временное хранилище
// УникальныйИдентификатор формы позволяет привязать файл к жизни формы
АдресВХранилище = "";
ПоместитьФайл(АдресВХранилище, Диалог.ПолноеИмяФайла, , Ложь, УникальныйИдентификатор);
// Вызываем серверную процедуру
ОбработатьФайлНаСервере(АдресВХранилище, Диалог.ПолноеИмяФайла);
КонецЕсли;
КонецПроцедуры
2. Код на Сервере (получение и чтение):
&НаСервере
Процедура ОбработатьФайлНаСервере(АдресВХранилище, ИсходноеИмяФайла)
// Получаем расширение файла, чтобы сохранить его правильно
Расширение = Прав(ИсходноеИмяФайла, 4);
Если Найти(Расширение, ".") = 0 Тогда
Расширение = ".xlsx"; // Значение по умолчанию
КонецЕсли;
// Получаем имя временного файла на сервере
ПутьНаСервере = ПолучитьИмяВременногоФайла(Расширение);
// Получаем двоичные данные из хранилища
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресВХранилище);
// Записываем файл на диск сервера
ДанныеФайла.Записать(ПутьНаСервере);
// Теперь по пути ПутьНаСервере файл физически существует на сервере
// Можно использовать ТабДок.Прочитать(ПутьНаСервере)
// Или Excel.Workbooks.Open(ПутьНаСервере)
Попытка
ОбработатьДанные(ПутьНаСервере); // Ваша процедура разбора
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
// Обязательно удаляем временный файл после использования
УдалитьФайлы(ПутьНаСервере);
КонецПроцедуры
Если вы все же используете COMОбъект("Excel.Application"), помните о необходимости освобождать ресурсы. Процессы Excel могут оставаться в памяти сервера, если их не закрыть принудительно, что со временем приведет к нехватке оперативной памяти.
Всегда оборачивайте работу с COM в конструкцию Попытка ... Исключение и в блоке исключения (или после успешного выполнения) вызывайте методы закрытия:
Попытка
Excel = Новый COMОбъект("Excel.Application");
Книга = Excel.Workbooks.Open(ПутьКФайлу);
// ... чтение данных ...
Книга.Close(0); // Закрываем книгу без сохранения
Исключение
// Логирование ошибки
КонецПопытки;
// Завершаем процесс Excel
Если Excel <> Неопределено Тогда
Excel.Quit();
Excel = Неопределено;
КонецЕсли;
Следуя этим рекомендациям, вы сможете избежать проблем с доступом к файлам и обеспечить стабильную работу загрузки данных на сервере 1С.