Чтение данных из внешних файлов Excel — одна из самых частых задач в практике разработчика 1С. Однако новички часто сталкиваются с ситуацией, когда код, написанный по всем правилам синтаксиса, выдает ошибку: «Ошибка при выполнении файловой операции». В этой статье мы подробно разберем, почему это происходит, проанализируем разницу в контекстах выполнения кода и рассмотрим несколько надежных способов загрузки данных из .xls и .xlsx.
Проанализируем типичную ситуацию. Программист пишет код на сервере, указывая путь к файлу, расположенному на рабочем столе его компьютера (например, C:\Users\home\Desktop\СписокКонтрагентов.xls). При запуске метода ТабДок.Прочитать() система выдает ошибку. Выясним причину этого сбоя.
Секрет кроется в физическом расположении ресурсов. Когда мы запускаем код в процедуре &НаСервере, он исполняется на компьютере, где установлена серверная часть 1С (кластер серверов). Для этого компьютера путь C:\Users\home\Desktop\... либо вообще не существует, либо ведет в папку «Рабочий стол» пользователя, под которым запущен сам сервер 1С (обычно это системная учетная запись USR1CV8), а не в папку пользователя на его локальном ПК.
Важно понимать: сервер 1С «не видит» локальные диски вашего рабочего компьютера напрямую. Он живет в своем собственном пространстве имен и путей.
Если на рабочем месте пользователя установлен пакет Microsoft Office, мы можем использовать механизм COMОбъект. Этот метод позволяет запустить Excel в фоновом режиме на стороне клиента, открыть файл и прочитать его содержимое построчно. Рассмотрим пример кода:
&НаКлиенте
Процедура ПрочитатьФайлExcel(Команда)
НомерЛистаExcel = 1;
Попытка
Excel = Новый COMОбъект("Excel.Application");
// Открываем книгу. Путь берется из реквизита объекта на клиенте
Excel.WorkBooks.Open(Объект.ПутьКФайлу);
ExcelЛист = Excel.Sheets(НомерЛистаExcel);
Исключение
Сообщить("Ошибка при открытии Excel. Возможно, файл занят или Excel не установлен.");
Возврат;
КонецПопытки;
// Определяем границы заполненной области
ActiveCell = Excel.ActiveCell.SpecialCells(11);
КоличествоСтрок = ActiveCell.Row;
Для НомерСтроки = 2 По КоличествоСтрок Цикл
НоваяСтрока = Объект.ДанныеФайла.Добавить();
// Читаем значения из ячеек (строка, колонка)
НоваяСтрока.Наименование = СокрЛП(ExcelЛист.Cells(НомерСтроки, 1).Text);
НоваяСтрока.УНП = СокрЛП(ExcelЛист.Cells(НомерСтроки, 2).Value);
КонецЦикла;
// Обязательно закрываем приложение, чтобы процесс не висел в памяти
Excel.Quit();
Excel = 0;
КонецПроцедуры
Преимущества: Высокая гибкость, возможность работы с любыми форматами, которые поддерживает установленный Excel.
Недостатки: Низкая скорость работы на больших объемах данных, зависимость от установленного стороннего ПО (Excel должен быть на каждом компьютере пользователя).
Наиболее современным и правильным подходом в управляемом приложении является предварительная передача файла с компьютера пользователя на сервер 1С. Рассмотрим, как реализовать этот алгоритм по шагам.
ТабличныйДокумент.Прочитать().
&НаСервере
Процедура ЗагрузитьНаСервере(АдресХранилища)
// Создаем временное имя файла на стороне сервера
ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла("xls");
// Извлекаем данные из хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ДвоичныеДанные.Записать(ИмяФайлаНаСервере);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайлаНаСервере, СпособЧтенияЗначенийТабличногоДокумента.Текст);
Исключение
Сообщить("Ошибка чтения: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Цикл обхода строк Табличного Документа
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
// Обработка данных...
КонецЦикла;
// Удаляем временный файл после чтения
УдалитьФайлы(ИмяФайлаНаСервере);
КонецПроцедуры
Использование параметра СпособЧтенияЗначенийТабличногоДокумента.Текст позволяет избежать проблем с неявным преобразованием типов, когда 1С пытается угадать формат данных в ячейке Excel.
Иногда даже при правильном контексте (код выполняется там, где лежит файл) 1С все равно выдает ошибку. Проанализируем возможные ситуации:
1. Файл открыт в Excel.
Многие версии 1С не могут прочитать файл, если он заблокирован другой программой для редактирования. Убедитесь, что файл закрыт перед началом загрузки. Для проверки можно попробовать переименовать файл в Windows: если система не дает этого сделать, значит, файл занят процессом.
2. Права службы USR1CV8.
Если вы все же решили читать файл напрямую с диска сервера (например, из сетевой папки), помните: служба 1С работает под определенной учетной записью. Чаще всего это USR1CV8. У этой записи должны быть права «Чтение» и «Просмотр содержимого» на папку, в которой лежит файл. Даже если вы как Администратор видите файл, сервер 1С может его «не видеть» из-за ограничений безопасности Windows.
3. Формат файла.
Бывают случаи, когда файл имеет расширение .xls, но внутри представляет собой HTML-разметку или CSV. В таких ситуациях метод ТабличныйДокумент.Прочитать() может выдать ошибку. Выходом будет предварительное пересохранение файла в «честный» формат Excel (Книга Excel) или использование специализированных библиотек.
Если ваш сервер 1С имеет разрядность 64 бит, а вы пытаетесь использовать COMОбъект("Excel.Application"), может возникнуть ошибка «Класс не зарегистрирован». Это происходит потому, что 32-битные COM-компоненты Excel не могут быть напрямую вызваны 64-битным процессом сервера 1С. В этом случае единственным стабильным решением будет использование встроенного метода ТабличныйДокумент.Прочитать(), который не зависит от наличия установленного Excel на сервере, либо выполнение кода строго &НаКлиенте (где установлена 32-битная версия Office).
Подведем итог: для стабильной работы всегда старайтесь передавать файл через временное хранилище на сервер и использовать нативный объект ТабличныйДокумент. Это обеспечит максимальную производительность и независимость от настроек окружения на рабочих станциях пользователей.