В процессе разработки в системе 1С:Предприятие 8 часто возникает задача предоставить пользователю возможность не просто вывести документ на печать, но и сохранить его в файл формата Excel (XLSX) для дальнейшей обработки или отправки контрагентам. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с трудностями, связанными с разделением контекстов выполнения кода (сервер и клиент) и доступом к файловой системе. В этой статье мы подробно разберем, как правильно организовать этот процесс, проанализируем типичные ошибки и рассмотрим современные стандарты разработки.
Рассмотрим ситуацию, с которой часто начинают разработчики. Проанализируем пример кода, который часто не срабатывает так, как ожидается. Основная проблема здесь заключается в попытке выполнить интерактивные действия (выбор файла) и запись файла в одном месте без учета того, где именно "живет" объект ТабличныйДокумент.
Типичная ошибка заключается в том, что разработчик пытается вызвать метод Записать() на сервере, указывая путь к локальному диску пользователя (например, C:\МоиДокументы). Выясним причину, почему это не работает: сервер 1С — это отдельный процесс, который может физически находиться на другом компьютере. Он "не видит" диск С: вашего локального компьютера и работает от имени специальной системной учетной записи (обычно USR1CV8).
Для решения задачи нам необходимо четко разделить ответственность. Проанализируем правильный алгоритм совместной работы клиента и сервера:
ТабличныйДокумент, заполняем его областями, выводим параметры и возвращаем готовый объект на клиент.Рассмотрим пример реализации этого подхода:
&НаСервере
Функция СформироватьПечатнуюФормуНаСервере()
ТабДок = Новый ТабличныйДокумент;
// Здесь логика заполнения документа
// Макет = Отчеты.МойОтчет.ПолучитьМакет("Макет");
// Область = Макет.ПолучитьОбласть("Заголовок");
// ТабДок.Вывести(Область);
ТабДок.АвтоМасштаб = Истина;
ТабДок.ПолеСверху = 10;
Возврат ТабДок;
КонецФункции
&НаКлиенте
Процедура СохранитьВExcel(Команда)
// 1. Получаем сформированный документ с сервера
ТабДок = СформироватьПечатнуюФормуНаСервере();
// 2. Настраиваем диалог выбора файла
Режим = РежимДиалогаВыбораФайла.Сохранение;
Диалог = Новый ДиалогВыбораФайла(Режим);
Диалог.Заголовок = "Укажите имя файла для сохранения печатной формы";
Диалог.ПолноеИмяФайла = "ПечатнаяФорма_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd");
Диалог.Фильтр = "Файл Excel (*.xlsx)|*.xlsx";
// 3. Интерактивный выбор пути пользователем
Если Диалог.Выбрать() Тогда
ПутьКФайлу = Диалог.ПолноеИмяФайла;
// 4. Запись документа на стороне клиента
Попытка
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Сообщить("Файл успешно сохранен: " + ПутьКФайлу);
Исключение
Предупреждение("Ошибка при сохранении файла! Возможно, файл открыт в другой программе.");
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Разберем важный нюанс: в современных конфигурациях (особенно работающих через веб-клиент или в интерфейсе "Такси") использование синхронных методов, таких как Диалог.Выбрать(), является нежелательным или вовсе заблокированным. Платформа требует асинхронности, чтобы интерфейс не "замирал" во время ожидания действий пользователя.
Посмотрим на пример того, как реализовать сохранение с использованием асинхронных вызовов. Вместо Выбрать() мы будем использовать метод Показать(), передавая в него описание оповещения.
&НаКлиенте
Процедура СохранитьАсинхронно(Команда)
ТабДок = СформироватьПечатнуюФормуНаСервере();
ПараметрыДиалога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
ПараметрыДиалога.Фильтр = "Excel (.xlsx)|*.xlsx";
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект, ТабДок);
ПараметрыДиалога.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
Путь = ВыбранныеФайлы[0];
ТабДок = ДополнительныеПараметры;
ТабДок.Записать(Путь, ТипФайлаТабличногоДокумента.XLSX);
КонецЕсли;
КонецПроцедуры
Если ваши пользователи работают через браузер, прямой доступ к файловой системе ограничен. В этом случае метод Записать() на клиенте может столкнуться с ограничениями безопасности. Проанализируем ситуацию: браузер не позволяет приложению просто так записывать файлы в произвольные папки на диске.
Стандартным решением для веб-клиента является формирование файла во временном хранилище на сервере и последующая "отдача" его пользователю для скачивания средствами браузера. Для этого используются методы ПоместитьВоВременноеХранилище и ПолучитьФайл (или его асинхронный аналог НачатьПолучениеФайлаССервера).
Выясним причину, по которой сохранение на сервере иногда все же необходимо. Это актуально для регламентных заданий (например, автоматическая рассылка отчетов по расписанию в папку на сервере). В этом случае важно помнить:
\\ServerName\ShareFolder\Report.xlsx). Сетевые диски, подключенные в сессии пользователя (например, Z:\), серверу обычно не видны.Записать() выдаст ошибку. Перед записью на сервере рекомендуется проверить наличие каталога или создать его программно.При выгрузке больших объемов данных следует учитывать ограничения самой программы Microsoft Excel:
ТабличныйДокумент больше, 1С не сможет выполнить запись.ТабДок.АвтоМасштаб = Истина корректно переносится в параметры печати Excel-файла, что позволяет документу сразу выглядеть презентабельно при печати из Excel.Подводя итог, можно сказать, что ключом к успешному сохранению печатных форм является четкое понимание того, где находится объект ТабличныйДокумент и где выполняется команда Записать. Для интерактивной работы пользователя всегда выбирайте клиентский контекст, а для автоматизированных систем — серверный с тщательной настройкой прав доступа к файловой системе.