Работа с файлами в клиент-серверной архитектуре «1С:Предприятия» часто преподносит сюрпризы начинающим разработчикам. Ситуация, когда код идеально работает в файловой базе или на локальном компьютере программиста, но «падает» с ошибкой «Каталог не обнаружен» на боевом сервере — одна из самых распространенных. Рассмотрим подробно, почему так происходит, как устроена работа серверных процессов и какими способами можно гарантированно прочитать файл Excel на стороне сервера.
Первое, что нам необходимо понять: в клиент-серверном варианте код, исполняемый под директивой &НаСервере, выполняется не на вашем компьютере и даже не всегда на том сервере, где расположена сама база данных (SQL-сервер). Его исполняет рабочий процесс 1С (rphost.exe). Проблема «Каталог не обнаружен» при выполнении метода ТабличныйДокумент.Прочитать() обычно вызвана одной из трех причин:
USR1CV8). У этой учетной записи нет доступа к вашим личным папкам (Рабочий стол, Документы) и, что критично, она не видит подключенные сетевые диски (диск Z:, X: и т.д.), которые вы создали в своем сеансе Windows."C:\Users\Admin\Desktop\file.xlsx" для сервера означает поиск файла на его собственном локальном диске, а не на диске пользователя, который нажал кнопку в интерфейсе.Проанализируем ситуацию с помощью встроенных инструментов отладки. Чтобы понять, на каком именно физическом компьютере выполняется ваш серверный код, попробуйте вычислить имя компьютера прямо в момент ошибки. Для этого в табло отладчика или в коде перед вызовом чтения файла выполните команду:
ИмяСервера = ИмяКомпьютера();
Сообщить("Код выполняется на сервере: " + ИмяСервера);
Если вы увидите имя, отличное от того, где физически лежит файл, причина локализации проблемы станет очевидной. В распределенных системах менеджер кластера может перекидывать процессы между узлами, и полагаться на локальные пути C:\... категорически нельзя.
Если специфика задачи требует, чтобы файл считывался напрямую из какой-то папки без предварительной загрузки в базу, нам необходимо использовать общесетевые пути. Рассмотрим, как это настроить правильно:
Exchange).USR1CV8, ей нужно дать права на уровне NTFS. Если серверы в домене, лучше использовать доменную учетную запись для службы 1С.
ПутьКФайлу = "\\ServerName\Exchange\PriceList.xlsx";
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу);
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось прочитать файл: " + ОписаниеОшибки());
КонецПопытки;
Внимание: Никогда не используйте буквы дисков (Z:\...), так как они существуют только в рамках вашей пользовательской сессии и не видны операционной системе в контексте служб.
Это самый надежный и современный способ, который работает независимо от настроек сети и количества серверов в кластере. Суть метода заключается в том, что мы выбираем файл на клиенте, «загружаем» его в оперативную память (временное хранилище) и передаем на сервер ссылку на этот объект. Платформа сама позаботится о доставке данных на нужный узел кластера.
Рассмотрим пошагово реализацию этого механизма:
Шаг 1. На клиенте: Используем функцию ПоместитьФайлНаСервер() или ПоместитьФайл().
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
ОписаниеФайла = Новый ОписаниеПередаваемогоФайла;
ПередаваемыеФайлы = Новый Массив;
ПередаваемыеФайлы.Добавить(ОписаниеФайла);
// Вызываем диалог выбора файла
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Excel (*.xlsx)|*.xlsx";
Если Диалог.Выбрать() Тогда
ПомещенныеФайлы = Новый Массив;
Если ПоместитьФайлы(,, Диалог.ВыбранныеФайлы, Ложь) Тогда
// Первый элемент массива содержит адрес во временном хранилище
ПрочитатьФайлНаСервере(ПомещенныеФайлы[0].Хранилище);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Шаг 2. На сервере: Извлекаем данные и читаем их в табличный документ.
&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресХранилища)
// Получаем данные из хранилища
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
// Создаем временное имя файла на сервере, чтобы метод Прочитать смог к нему обратиться
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДанныеФайла.Записать(ИмяВременногоФайла);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяВременногоФайла);
// Далее выполняем обработку данных ТабДок
Исключение
ЗаписьЖурналаРегистрации("ЗагрузкаExcel", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
// Удаляем временный файл после использования
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Проанализируем преимущества этого подхода: нам не важны права доступа к папкам, нам не важны сетевые настройки, и код будет работать даже если завтра ваша база переедет в «облако» или на Linux-сервер.
Чтобы программа не просто выдавала системную ошибку, а вела себя дружелюбно, мы можем предварительно проверить доступность ресурса. Для этого используем объект Файл. Рассмотрим пример функции-проверки, которую стоит запускать перед чтением:
&НаСервере
Функция ПроверитьДоступностьФайла(ПолныйПуть)
ПроверкаФайла = Новый Файл(ПолныйПуть);
Если Не ПроверкаФайла.Существует() Тогда
Сообщить("Сервер 1С не видит файл по пути: " + ПолныйПуть);
Сообщить("Текущий рабочий сервер: " + ИмяКомпьютера());
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
Использование такой проверки позволит вам быстро диагностировать проблемы с правами или путями, не прибегая к сложному анализу логов сервера.
Стоит помнить, что ТабличныйДокумент.Прочитать() при работе с Excel (форматы .xls и .xlsx) на сервере не требует установленного Microsoft Excel. Это огромное преимущество, так как использование COM-объектов (Excel.Application) на сервере считается «плохим тоном» и часто блокируется системой безопасности Windows из-за отсутствия интерактивного рабочего стола у системной службы.
Однако, если ваш файл защищен паролем или имеет сложную структуру со сводными таблицами, стандартный метод Прочитать() может выдать ошибку или прочитать данные некорректно. В таких случаях рекомендуется использовать специализированные библиотеки для чтения XLSX или предварительно сохранять файл в упрощенном формате.
Подведем итог: при возникновении ошибки «Каталог не обнаружен» первым делом проверяйте, где физически находится файл и имеет ли конкретный узел кластера 1С доступ к этому месту по сетевому имени. Но лучшим решением всегда будет передача файла через временное хранилище, что делает ваш код универсальным и надежным.