Как организовать выбор каталога для сохранения файла во внешней печатной форме?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке внешних печатных форм (ВПФ) в среде 1С:Предприятие 8 часто возникает задача сохранения сформированного документа (например, файла Word или Excel) в конкретную папку на диске пользователя. Основная сложность заключается в том, что формирование данных обычно происходит на стороне сервера, а объект ДиалогВыбораФайла и доступ к локальной файловой системе доступны исключительно на стороне клиента. Рассмотрим подробнее, как обойти это ограничение и реализовать удобный интерфейс для пользователя.

Понимание клиент-серверного взаимодействия

Прежде чем переходить к коду, разберем ситуацию. Когда мы запускаем печать, серверная часть кода подготавливает макет и заполняет его данными. Однако сервер «не видит» рабочий стол пользователя и его папки. Поэтому мы не можем вызвать диалог выбора каталога непосредственно из серверной процедуры. Проанализируем основные стратегии решения этой задачи.

Решение 1: Использование типа команды «ВызовКлиентскогоМетода»

Самый правильный способ в рамках Библиотеки стандартных подсистем (БСП) — перенести логику инициализации печати на клиент. Для этого в модуле объекта внешней обработки, в функции СведенияОВнешнейОбработке, необходимо указать соответствующий тип команды.

Разберем по шагам настройку этого метода:

  1. В функции СведенияОВнешнейОбработке установите Использование в значение ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода().
  2. В модуле формы внешней обработки создайте экспортную процедуру Печать.

Важно соблюдать точную сигнатуру процедуры, иначе платформа ее не обнаружит:


Процедура Печать(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    
    // 1. Сначала вызываем диалог выбора каталога на клиенте
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
    Диалог.Заголовок = "Выберите папку для сохранения печатных форм";
    
    Если Диалог.Выбрать() Тогда
        ВыбранныйПуть = Диалог.Каталог;
        // 2. Теперь вызываем серверный метод для формирования файла
        АдресХранилища = СформироватьФайлНаСервере(ОбъектыНазначения);
        // 3. Получаем файл из хранилища и сохраняем по выбранному пути
        ПолучитьФайл(АдресХранилища, ВыбранныйПуть + "\ПечатнаяФорма.docx", Истина);
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Передача файла через временное хранилище

Если ваша архитектура требует сначала подготовить файл на сервере, а потом спросить пользователя, куда его положить, используйте механизм временного хранилища. Это стандартный паттерн 1С для обмена бинарными данными между слоями системы.

Проанализируем алгоритм работы:

  1. На сервере: Формируем файл Word во временном каталоге сервера с помощью ПолучитьИмяВременногоФайла.
  2. На сервере: Читаем файл в объект ДвоичныеДанные и помещаем их во временное хранилище, получая адрес (УИД).
  3. На клиенте: Получаем этот адрес и вызываем диалог. После выбора пути используем ПолучитьФайлССервера.

Пример серверной функции:


&НаСервере
Функция СформироватьФайлНаСервере(СсылкиНаОбъекты)
    ИмяФайла = ПолучитьИмяВременногоФайла("docx");
    // Здесь логика заполнения шаблона Word...
    // Документ.SaveAs(ИмяФайла);
    
    ДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
    Возврат ПоместитьВоВременноеХранилище(ДанныеФайла, Новый УникальныйИдентификатор);
КонецФункции

Решение 3: Асинхронные методы (для современных платформ)

Начиная с версии платформы 8.3.15, использование синхронных методов (таких как Выбрать()) в модальных окнах запрещено, особенно если программа работает в веб-клиенте. Выясним причину: браузеры блокируют выполнение кода до закрытия окна, что негативно сказывается на стабильности. Посмотрим на пример асинхронного вызова:


&НаКлиенте
Процедура НачатьСохранение(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораКаталога", ЭтотОбъект);
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
    Диалог.Показать(Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораКаталога(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
    Если ВыбранныеФайлы <> Неопределено Тогда
        ПутьККаталогу = ВыбранныеФайлы[0];
        // Продолжаем логику сохранения...
    КонецЕсли;
КонецПроцедуры

Использование функций БСП для упрощения разработки

Библиотека стандартных подсистем содержит готовые обертки, которые берут на себя рутину по работе с файлами. Рекомендуем обратить внимание на общий модуль РаботаСФайламиКлиент. Метод СохранитьФайл() автоматически предложит пользователю диалог и выполнит копирование данных из временного хранилища. Это сокращает объем вашего кода и делает его более устойчивым к обновлениям платформы. Для быстрого подбора нужных процедур и функций пригодится справочник по методам БСП с практическими примерами использования.

Ограничения и права доступа

Проанализируем ситуацию, когда файл нужно сохранить не на компьютер пользователя, а в сетевую папку на сервере. В этом случае диалог выбора файлов на клиенте бесполезен. Проверка существования каталога должна выполняться на сервере через объект Файл.

Важный нюанс: Права на запись в сетевой каталог должны быть не у пользователя 1С, а у учетной записи, под которой запущен процесс сервера 1С:Предприятия (обычно это USR1CV8). Если у этой службы нет прав в операционной системе на указанную папку, запись завершится ошибкой «Доступ запрещен».

Альтернатива: интерактивное открытие без сохранения

Часто пользователю не нужно выбирать папку заранее. Рассмотрите вариант, при котором вы формируете файл во временном каталоге клиента и сразу открываете его через ЗапуститьПриложение. Пользователь увидит заполненный Word-документ и сможет нажать «Файл — Сохранить как» в самом текстовом редакторе. Это избавляет программиста от необходимости писать сложный код выбора пути и обработки ошибок доступа к дискам. Для этой задачи можно использовать шаблон внешней печатной формы для вывода данных в Word через БСП.

Для реализации этого сценария на клиенте достаточно вызвать:


ИмяВременногоФайла = КаталогВременныхФайлов() + "Печать.docx";
ДанныеИзХранилища = ПолучитьИзХранилища(Адрес);
ДанныеИзХранилища.Записать(ИмяВременногоФайла);
ЗапуститьПриложение(ИмяВременногоФайла);

Таким образом, мы разобрали несколько подходов к решению проблемы. Выбор конкретного метода зависит от требований к интерфейсу и версии платформы, на которой работает ваша конфигурация.

← На главную