При разработке внешних печатных форм (ВПФ) в среде 1С:Предприятие 8 часто возникает задача сохранения сформированного документа (например, файла Word или Excel) в конкретную папку на диске пользователя. Основная сложность заключается в том, что формирование данных обычно происходит на стороне сервера, а объект ДиалогВыбораФайла и доступ к локальной файловой системе доступны исключительно на стороне клиента. Рассмотрим подробнее, как обойти это ограничение и реализовать удобный интерфейс для пользователя.
Прежде чем переходить к коду, разберем ситуацию. Когда мы запускаем печать, серверная часть кода подготавливает макет и заполняет его данными. Однако сервер «не видит» рабочий стол пользователя и его папки. Поэтому мы не можем вызвать диалог выбора каталога непосредственно из серверной процедуры. Проанализируем основные стратегии решения этой задачи.
Самый правильный способ в рамках Библиотеки стандартных подсистем (БСП) — перенести логику инициализации печати на клиент. Для этого в модуле объекта внешней обработки, в функции СведенияОВнешнейОбработке, необходимо указать соответствующий тип команды.
Разберем по шагам настройку этого метода:
СведенияОВнешнейОбработке установите Использование в значение ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода().Печать.Важно соблюдать точную сигнатуру процедуры, иначе платформа ее не обнаружит:
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
// 1. Сначала вызываем диалог выбора каталога на клиенте
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
Диалог.Заголовок = "Выберите папку для сохранения печатных форм";
Если Диалог.Выбрать() Тогда
ВыбранныйПуть = Диалог.Каталог;
// 2. Теперь вызываем серверный метод для формирования файла
АдресХранилища = СформироватьФайлНаСервере(ОбъектыНазначения);
// 3. Получаем файл из хранилища и сохраняем по выбранному пути
ПолучитьФайл(АдресХранилища, ВыбранныйПуть + "\ПечатнаяФорма.docx", Истина);
КонецЕсли;
КонецПроцедуры
Если ваша архитектура требует сначала подготовить файл на сервере, а потом спросить пользователя, куда его положить, используйте механизм временного хранилища. Это стандартный паттерн 1С для обмена бинарными данными между слоями системы.
Проанализируем алгоритм работы:
ПолучитьИмяВременногоФайла.ДвоичныеДанные и помещаем их во временное хранилище, получая адрес (УИД).ПолучитьФайлССервера.Пример серверной функции:
&НаСервере
Функция СформироватьФайлНаСервере(СсылкиНаОбъекты)
ИмяФайла = ПолучитьИмяВременногоФайла("docx");
// Здесь логика заполнения шаблона Word...
// Документ.SaveAs(ИмяФайла);
ДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
Возврат ПоместитьВоВременноеХранилище(ДанныеФайла, Новый УникальныйИдентификатор);
КонецФункции
Начиная с версии платформы 8.3.15, использование синхронных методов (таких как Выбрать()) в модальных окнах запрещено, особенно если программа работает в веб-клиенте. Выясним причину: браузеры блокируют выполнение кода до закрытия окна, что негативно сказывается на стабильности. Посмотрим на пример асинхронного вызова:
&НаКлиенте
Процедура НачатьСохранение(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВыбораКаталога", ЭтотОбъект);
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораКаталога(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
ПутьККаталогу = ВыбранныеФайлы[0];
// Продолжаем логику сохранения...
КонецЕсли;
КонецПроцедуры
Библиотека стандартных подсистем содержит готовые обертки, которые берут на себя рутину по работе с файлами. Рекомендуем обратить внимание на общий модуль РаботаСФайламиКлиент. Метод СохранитьФайл() автоматически предложит пользователю диалог и выполнит копирование данных из временного хранилища. Это сокращает объем вашего кода и делает его более устойчивым к обновлениям платформы. Для быстрого подбора нужных процедур и функций пригодится справочник по методам БСП с практическими примерами использования.
Проанализируем ситуацию, когда файл нужно сохранить не на компьютер пользователя, а в сетевую папку на сервере. В этом случае диалог выбора файлов на клиенте бесполезен. Проверка существования каталога должна выполняться на сервере через объект Файл.
Важный нюанс: Права на запись в сетевой каталог должны быть не у пользователя 1С, а у учетной записи, под которой запущен процесс сервера 1С:Предприятия (обычно это USR1CV8). Если у этой службы нет прав в операционной системе на указанную папку, запись завершится ошибкой «Доступ запрещен».
Часто пользователю не нужно выбирать папку заранее. Рассмотрите вариант, при котором вы формируете файл во временном каталоге клиента и сразу открываете его через ЗапуститьПриложение. Пользователь увидит заполненный Word-документ и сможет нажать «Файл — Сохранить как» в самом текстовом редакторе. Это избавляет программиста от необходимости писать сложный код выбора пути и обработки ошибок доступа к дискам. Для этой задачи можно использовать шаблон внешней печатной формы для вывода данных в Word через БСП.
Для реализации этого сценария на клиенте достаточно вызвать:
ИмяВременногоФайла = КаталогВременныхФайлов() + "Печать.docx";
ДанныеИзХранилища = ПолучитьИзХранилища(Адрес);
ДанныеИзХранилища.Записать(ИмяВременногоФайла);
ЗапуститьПриложение(ИмяВременногоФайла);
Таким образом, мы разобрали несколько подходов к решению проблемы. Выбор конкретного метода зависит от требований к интерфейсу и версии платформы, на которой работает ваша конфигурация.