В процессе разработки на платформе 1С:Предприятие 8.1 программисты часто сталкиваются с ситуацией, когда код, идеально работающий в интерактивном режиме под учетной записью пользователя, внезапно «ломается» при переносе в регламентное задание. Одной из самых коварных проблем является сохранение табличного документа в формате XLS на стороне сервера. Мы часто видим ошибку «Файл не обнаружен» при попытке дальнейшей работы с этим файлом (например, при отправке по почте), хотя визуально код кажется верным. Давайте разберем эту ситуацию подробно, выясним причины и найдем эффективные способы решения.
Первым делом проанализируем поведение платформы. В версии 1С 8.1 метод Записать() объекта ТабличныйДокумент имеет существенные архитектурные отличия в зависимости от того, где выполняется код: на клиенте или на сервере. При работе в клиентском сеансе (под «обычным пользователем») платформа задействует графические ресурсы и библиотеки операционной системы, доступные в текущей сессии. Это позволяет успешно формировать файлы в формате XLS.
Однако, когда управление передается серверу (в РегламентныеЗадания), контекст выполнения меняется. Проанализируем техническую документацию (Синтакс-Помощник) для версии 8.1. Там прямо указано: «При работе на сервере или через COM-соединение использует только файлы форматов MXL и TXT». Это фундаментальное ограничение платформы того времени. Система не просто «не хочет» записывать файл, у нее физически отсутствуют механизмы для формирования двоичного формата Excel 97-2003 (XLS) в серверном окружении без графического интерфейса. Именно поэтому попытка записи завершается фактически ничем, файл не создается, а последующий код, пытающийся найти этот файл на диске, выдает ошибку «Файл не обнаружен».
Рассмотрим несколько эффективных способов обхода этого ограничения, которые позволят нам автоматизировать рассылку прайс-листов или отчетов в формате Excel.
Это самый простой и быстрый способ, не требующий установки стороннего программного обеспечения. Суть метода заключается в том, что Microsoft Excel прекрасно умеет открывать файлы в формате HTML, интерпретируя их как таблицы. Мы можем сохранить табличный документ как HTML, но принудительно задать ему расширение .xls.
Разберем по шагам, как это реализовать в коде:
// Вместо прямого сохранения в XLS, которое не работает на сервере:
// ТабДок.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLS);
// Используем сохранение в HTML
ПолноеИмяФайла = "C:\Temp\Price_20-06-2018.xls"; // Расширение оставляем XLS
ТабДок.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.HTML);
Важный нюанс: при открытии такого файла в MS Excel пользователь может увидеть предупреждение: «Действительный формат открываемого файла отличается от указанного расширения имени файла». Если пользователь нажмет «Да», файл откроется со всем форматированием, объединением ячеек и цветами. Для регламентных рассылок внутри компании это часто является приемлемым компромиссом.
Если нам требуется получить «честный» файл XLS, который не будет вызывать предупреждений у пользователя, обратимся к проверенному сообществом решению — библиотеке Йоксель. Это мощный инструмент, который умеет конвертировать файлы MXL в XLS программно и, что самое главное, работает на сервере без установленного Microsoft Office.
Рассмотрим алгоритм работы с этой компонентой:
MXL (это разрешено на сервере).XLS.Пример кода для реализации этой схемы:
// 1. Сохраняем в промежуточный MXL
ВременныйMXL = ПолучитьИмяВременногоФайла("mxl");
ТабДок.Записать(ВременныйMXL, ТипФайлаТабличногоДокумента.MXL);
// 2. Используем Йоксель для конвертации
// Предполагается, что компонента зарегистрирована на сервере
Попытка
Йоксель = Новый COMОбъект("Yoksel.Spreadsheet");
Йоксель.Открыть(ВременныйMXL);
// 3. Сохраняем в итоговый XLS
Конвертер = Новый COMОбъект("Yoksel.Converter.XLS");
Йоксель.Записать(ПолноеИмяФайла, Конвертер);
Исключение
ЗаписьЖурналаРегистрации("Ошибка конвертации в XLS", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
Этот метод является наиболее профессиональным для платформы 8.1, так как он полностью автоматизирует процесс и на выходе дает корректный файл.
Если наш прайс-лист или отчет представляет собой простую таблицу с данными без сложного оформления (без цветов, рамок и объединенных ячеек), проанализируем возможность использования формата CSV (Comma-Separated Values). Формат TXT (и его вариация CSV) официально поддерживается методом Записать() на сервере 1С 8.1.
Посмотрим на пример реализации:
// Сохранение в формате CSV, который открывается Экселем без лишних вопросов
ИмяФайлаCSV = "C:\Reports\Data.csv";
ТабДок.Записать(ИмяФайлаCSV, ТипФайлаТабличногоДокумента.ANSITXT);
Помните, что при использовании ANSITXT в качестве разделителя обычно выступает знак табуляции. Чтобы Excel сразу распознал разделители, файл лучше сохранять с кодировкой и структурой, соответствующей стандартам CSV для вашего региона.
Выясним еще одну важную причину, по которой файл может не обнаруживаться. Даже если мы решим проблему с форматом, регламентное задание выполняется от имени специального системного пользователя (обычно это USR1CV81). У этого пользователя свой профиль в операционной системе и свои временные папки.
Когда мы используем функцию КаталогВременныхФайлов(), находясь в серверном коде, путь будет вести в C:\Users\USR1CV81\AppData\Local\Temp\.... Убедимся в следующем:
USR1CV81 есть права на запись в эту папку.Послать() должен иметь доступ к тому же самому пути. Проверьте, не очищается ли временная папка между моментом записи и моментом отправки.В завершение стоит отметить, что данная проблема была полностью решена в более поздних версиях платформы. Начиная с 1С 8.2.13 и выше, метод Записать() поддерживает форматы XLS, XLSX и PDF непосредственно на сервере (нативно). Если бизнес-логика позволяет, переход на платформу 8.3 (в режиме совместимости с 8.1) снимет все вопросы по работе с файлами в регламентных заданиях и значительно упростит жизнь разработчику.
Подведем итог: если вы ограничены версией 8.1, используйте Yoksel для качественных файлов или сохранение в HTML с расширением .xls для быстрых решений. Всегда проверяйте права системного пользователя 1С на серверные каталоги.