В процессе разработки обработок загрузки данных в клиент-серверном режиме 1С:Предприятия часто возникает ситуация, когда при вызове метода Excel.WorkBooks.Open(ИмяФайла) на стороне сервера система генерирует исключительную ситуацию. В тексте ошибки сообщается, что нет доступа к файлу по сетевому пути формата UNC, файл используется другой программой или не существует, хотя при проверке с рабочего места пользователя путь открывается без каких-либо затруднений.
Разберем детально, почему сервер 1С и компонент COM теряют доступ к сетевой папке, и рассмотрим надежные способы обхода и устранения этой неполадки.
Проанализируем ключевые причины возникновения данной проблемы:
ragent) по умолчанию часто работает под локальной системной учетной записью LocalSystem (или локальным пользователем usr1cv8). Такие учетные записи не имеют прав доступа к общим ресурсам в доменной сети и не могут пройти авторизацию на удаленном файловом сервере.Новый COMОбъект("Excel.Application") в серверном контексте процесс EXCEL.EXE запускается с правами, определенными в службе компонентов. Если в DCOM настроен запуск от имени запускающего пользователя, сетевой маркер безопасности часто оказывается урезанным, что блокирует сетевые подключения (эффект «двойного прыжка»).Open по умолчанию запрашивает открытие книги на чтение и запись. Если на сетевой ресурс выданы права только на чтение, либо книга уже открыта кем-то в сети, Excel блокирует операцию.Наиболее архитектурно правильный и изолированный вариант — прочитать файл на клиенте (где у текущего пользователя гарантированно есть доступ к сетевому ресурсу) и передать его на сервер в виде двоичных данных через временное хранилище. Посмотрим на реализацию этого подхода:
&НаКлиенте
Процедура ЗагрузитьФайлИзСети()
ФайлИсточник = "\\shara\Volume_1\azat\oit-zapis\doc-otdela\зп.xlsx";
// Считываем файл в контексте прав клиента
ДвоичныеДанные = Новый ДвоичныеДанные(ФайлИсточник);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
// Передаем адрес во временном хранилище на сервер
ПрочитатьФайлНаСервере(АдресХранилища);
КонецПроцедуры
&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресХранилища)
ДвоичныйФайл = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяФайлаСервер = ПолучитьИмяВременногоФайла("xlsx");
// Сохраняем файл локально на сервере
ДвоичныйФайл.Записать(ИмяФайлаСервер);
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Excel.ScreenUpdating = Ложь;
Попытка
// Открываем локальный файл только для чтения (ReadOnly = Истина)
Книга = Excel.Workbooks.Open(ИмяФайлаСервер, 0, Истина);
// Здесь выполняем чтение необходимых данных
Книга.Close(Ложь);
Исключение
ВызватьИсключение "Ошибка при чтении книги: " + ОписаниеОшибки();
КонецПопытки;
Excel.Quit();
Excel = Неопределено;
// Обязательно удаляем временный файл
УдалитьФайлы(ИмяФайлаСервер);
КонецПроцедуры
Рассмотрим преимущества этого способа: мы полностью отвязываем сервер 1С от сетевых папок. Сервер работает с локальным путем в каталоге временных файлов, к которому у службы 1С всегда есть полные права.
Если обработка выполняется полностью на клиенте или необходимо быстро проверить доступность без переписывания архитектуры, разберем вариант с предварительным копированием сетевого файла во временную локальную папку:
&НаКлиенте
Процедура СкопироватьИПрочитать()
ФайлИсточник = "\\shara\Volume_1\azat\oit-zapis\doc-otdela\зп.xlsx";
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
Попытка
КопироватьФайл(ФайлИсточник, ИмяВременногоФайла);
Исключение
Сообщить("Не удалось скопировать сетевой файл: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Попытка
Книга = Excel.Workbooks.Open(ИмяВременногоФайла, 0, Истина);
// Обработка данных
Книга.Close(Ложь);
Исключение
Сообщить("Ошибка открытия файла: " + ОписаниеОшибки());
КонецПопытки;
Excel.Quit();
Excel = Неопределено;
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Если сетевой путь всё же должен открываться напрямую, проанализируем параметры метода Open. По умолчанию метод требует эксклюзивного доступа на запись. Чтобы файл открылся, даже если он кем-то просматривается или папка доступна только для чтения, необходимо явно передать третий параметр ReadOnly:
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
// 3-й параметр - ReadOnly (Истина)
Книга = Excel.Workbooks.Open(СетевойПутьКФайлу, 0, Истина);
Важно: Всегда отключайте предупреждения через свойство DisplayAlerts = Ложь. Это предотвратит зависание процесса из-за скрытых модальных окон.
Если требуется, чтобы сервер 1С обращался к сетевым путям напрямую через COM-объект, выполним системную настройку:
LocalSystem).mmc comexp.msc /32.C:\Windows\System32\config\systemprofile\Desktop и C:\Windows\SysWOW64\config\systemprofile\Desktop с полными правами для учетной записи службы 1С.Использование COM Automation на сервере официально не рекомендуется компанией Microsoft, так как это приводит к зависанию процессов EXCEL.EXE и утечкам памяти. Самый надежный, быстрый и платформенный способ прочитать файл на сервере — использовать объект ТабличныйДокумент, который умеет загружать файлы формата XLSX без установленного пакета Office:
&НаСервере
Процедура ПрочитатьЧерезТабличныйДокумент(ИмяФайла)
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;
Для НомерСтроки = 1 По ВсегоСтрок Цикл
ЗначениеЯчейки = ТабДок.Область(НомерСтроки, 1).Текст;
// Обработка прочитанных данных
КонецЦикла;
КонецПроцедуры
Чтение через ТабличныйДокумент выполняется полностью встроенными средствами платформы 1С, работает стабильно в любых фоновых заданиях и не зависит от настроек DCOM или наличия Microsoft Office на сервере.