При разработке механизмов загрузки данных из Excel в 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, прекрасно работающий на локальном компьютере, выдает ошибку «Каталог не обнаружен» или «Файл не найден» при попытке выполнить его на сервере. В этой статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько надежных способов ее решения, начиная от передачи файла через временное хранилище и заканчивая настройкой прав доступа на уровне операционной системы. Если вам не требуется писать собственную логику парсинга, для интеграции можно использовать универсальную обработку для импорта справочников из Excel.
Разберем типичную ситуацию: пользователь на своем компьютере выбирает файл через диалог выбора. В переменную Объект.ФайлЗагрузки попадает локальный путь, например, C:\Users\Ivanov\Documents\price.xlsx. Когда управление передается на сервер (процедура с директивой &НаСервере), метод ТабличныйДокумент.Прочитать() пытается найти этот путь на жестком диске самого сервера.
Естественно, на сервере нет папки пользователя Ivanov, или же у службы 1С (которая обычно запускается от имени специального пользователя USR1CV8) нет прав на доступ к этой папке. Проанализируем основные причины этой ошибки:
Этот метод является самым универсальным и правильным с точки зрения архитектуры 1С. Вместо того чтобы заставлять сервер искать файл по пути, мы передаем сам контент файла с клиента на сервер. Рассмотрим этот процесс по шагам. Для быстрой реализации такой схемы можно использовать готовый шаблон кода для чтения и загрузки данных из Excel.
Шаг 1. Выбор файла на клиенте. Сначала мы получаем путь к файлу на компьютере пользователя.
&НаКлиенте
Процедура ВыбратьИЗагрузитьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Excel (*.xlsx)|*.xlsx|Excel 97-2003 (*.xls)|*.xls";
Если Диалог.Выбрать() Тогда
ИмяФайла = Диалог.ПолноеИмяФайла;
ВыполнитьЗагрузку(ИмяФайла);
КонецЕсли;
КонецПроцедуры
Шаг 2. Помещение файла во временное хранилище. Мы считываем файл в объект ДвоичныеДанные и отправляем его в специальную область памяти сервера.
&НаКлиенте
Процедура ВыполнитьЗагрузку(ИмяФайла)
// Читаем файл в двоичные данные
ДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
// Помещаем во временное хранилище и получаем уникальный адрес
АдресХранилища = ПоместитьВоВременноеХранилище(ДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
// Передаем адрес на сервер для обработки
ЗагрузитьНаСервере(АдресХранилища);
КонецПроцедуры
Шаг 3. Обработка файла на сервере. Теперь сервер извлекает данные из хранилища, сохраняет их во временный файл (к которому у него точно есть доступ) и читает его.
&НаСервере
Процедура ЗагрузитьНаСервере(АдресХранилища)
// Получаем двоичные данные из хранилища
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
// Создаем имя временного файла на сервере
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
// Записываем данные в этот файл
Данные.Записать(ИмяВременногоФайла);
// Читаем файл в ТабличныйДокумент
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяВременногоФайла);
// Далее идет логика разбора таблицы
Для Строка = 1 По ТабДок.ВысотаТаблицы Цикл
// Обработка данных...
КонецЦикла;
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
КонецПопытки;
// Обязательно удаляем временный файл после работы
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Если по каким-то причинам вы не хотите передавать файлы через хранилище (например, файлы имеют огромный объем в несколько гигабайт), можно настроить общую сетевую папку. Рассмотрим, как сделать это правильно, чтобы избежать ошибки «Каталог не обнаружен».
Во-первых, путь должен быть указан в формате UNC (Universal Naming Convention), например: \\ServerName\ShareFolder\file.xlsx. Использование путей типа Z:\folder\file.xlsx недопустимо, так как сетевые диски подключаются для конкретного пользователя, а служба 1С их «не видит».
Во-вторых, проанализируем права доступа. Пользователь, от имени которого запущен сервер 1С (например, USR1CV8), должен иметь полные права на чтение и изменение данных в этой сетевой папке. Выясним, под каким пользователем работает сервер, через оснастку «Службы» в Windows, и добавим этого пользователя в список доступа сетевой папки на вкладках «Общий доступ» и «Безопасность».
Иногда программисты решают использовать Excel.Application через COM-соединение. Если выполнять этот код на сервере, возникает множество проблем: от отсутствия установленного MS Office до зависания процессов в памяти. Рассмотрим вариант выполнения загрузки полностью на клиенте, если это позволяют бизнес-требования.
&НаКлиенте
Процедура ЗагрузитьЧерезCOM(ИмяФайла)
Попытка
Excel = Новый COMОбъект("Excel.Application");
Книга = Excel.Workbooks.Open(ИмяФайла);
Лист = Книга.Sheets(1);
// Читаем данные и сразу помещаем их, например, в таблицу значений на форме
Для Сч = 1 По 100 Цикл // Пример для 100 строк
НоваяСтрока = Объект.ТзДанных.Добавить();
НоваяСтрока.Наименование = Лист.Cells(Сч, 1).Value;
КонецЦикла;
Книга.Close(Ложь);
Excel.Quit();
Исключение
Сообщить("Ошибка Excel: " + ОписаниеОшибки());
Если Excel <> Неопределено Тогда
Excel.Quit();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Важное замечание: Метод с COM-объектом работает медленнее, чем ТабличныйДокумент.Прочитать(), и требует наличия установленного Excel на компьютере пользователя. Для серверной работы этот метод крайне не рекомендуется.
Если ваш сервер 1С работает под управлением Linux, использование путей Windows станет невозможным. Проанализируем, как поступить в этом случае:
mount -t cifs)./home/user/File.xlsx и /home/user/file.xlsx — это разные пути.Как упоминалось в обсуждении, при передаче очень тяжелых файлов стандартные методы могут давать сбой или приводить к порче данных. В современных версиях платформы (8.3.15+) рекомендуется использовать асинхронный метод НачатьПомещениеФайлаНаСервер(). Это позволяет передавать данные в фоновом режиме, обеспечивая более стабильную работу интерфейса и минимизируя риски обрыва соединения при передаче больших объемов двоичных данных.
Подводя итог, можно сказать: наиболее надежным и «чистым» способом загрузки Excel на сервере является передача двоичных данных файла через временное хранилище с последующим чтением через ТабличныйДокумент. Это избавляет от проблем с правами доступа к каталогам и делает ваш код кроссплатформенным.