Часто при разработке собственных конфигураций на управляемых формах «с нуля» без использования Библиотеки стандартных подсистем (БСП) возникает задача: необходимо вывести печатную форму документа (сформированный табличный документ) и сделать так, чтобы при ее сохранении пользователю автоматически предлагалось определенное имя файла.
Давайте разберем по шагам эту задачу, проанализируем типичные ошибки (такие как вызов интерфейсных методов на сервере или получение ошибки доступа 5(0x00000005)) и рассмотрим несколько корректных способов реализации.
Первое, с чем мы сталкиваемся при работе с управляемыми формами — это строгое разделение контекста на серверный и клиентский. Печатная форма всегда формируется на сервере, так как именно там есть доступ к базе данных, макетам и объектам. Однако выводить документ на экран и управлять диалогами сохранения нужно исключительно на клиенте.
Посмотрим на пример правильного разделения кода. В модуле формы создадим серверную функцию для генерации документа и клиентскую процедуру для его отображения:
&НаСервере
Функция СформироватьТабДокНаСервере()
ТабДок = Новый ТабличныйДокумент;
// Вызываем процедуру печати из модуля менеджера документа
Документы.ЛУВР.Печать(ТабДок, Объект.Ссылка);
Возврат ТабДок;
КонецФункции
&НаКлиенте
Процедура ПечатьДокумента(Команда)
ТабДок = СформироватьТабДокНаСервере();
ТабДок.Показать();
КонецПроцедуры
Важно: Никогда не используйте метод Показать() внутри модуля менеджера или в серверном контексте. Это приведет к ошибке исполнения, так как сервер не умеет работать с интерфейсом пользователя.
Проанализируем ситуацию: мы хотим, чтобы при нажатии пользователем кнопки «Сохранить» (иконка дискеты или меню «Файл» — «Сохранить как...») в стандартном диалоге ОС уже было вписано нужное нам имя. Для этого у объекта ТабличныйДокумент есть специальное свойство ИспользуемоеИмяФайла.
Главный нюанс: Это свойство должно устанавливаться на клиенте. Если вы установите его на сервере, при передаче табличного документа между контекстами оно может очиститься.
Дополнительно стоит задать свойство Заголовок — оно поменяет текст в шапке окна выведенной печатной формы и также послужит подсказкой для платформы 1С при формировании имени файла.
&НаКлиенте
Процедура ПечатьДокумента(Команда)
ТабДок = СформироватьТабДокНаСервере();
// Устанавливаем свойства на клиенте!
ТабДок.Заголовок = "Накладная №" + Объект.Номер;
ТабДок.ИспользуемоеИмяФайла = "Накладная_" + Объект.Номер + ".pdf";
// Показываем документ без дополнительных параметров
ТабДок.Показать(ТабДок.Заголовок);
КонецПроцедуры
Теперь, когда печатная форма откроется, пользователь сможет нажать стандартную кнопку сохранения, и платформа автоматически подставит предложенное имя файла.
В платформе 1С метод Показать() имеет следующий синтаксис: Показать(Заголовок, ИмяФайла). Разберем подробнее, как работает второй параметр и почему он может вызывать проблемы.
Если мы напишем код: ТабДок.Показать("ПечатнаяФорма", "МойДокумент.mxl");, то мы не получим ожидаемого диалога сохранения при нажатии кнопки. Второй параметр предназначен для автоматического сохранения состояния документа при закрытии окна (и только в том случае, если документ был изменен пользователем вручную).
Если указать имя файла без полного пути, платформа попытается сохранить его во временные системные каталоги или в папку установки программы (bin). У обычного пользователя нет прав на запись в эти папки, поэтому система выдает ошибку:
Ошибка доступа к файлу 'МойДокумент.mxl'. 5(0x00000005): Отказано в доступе.
Если же указать полный путь (например, "D:\МойДокумент.mxl"), то документ при закрытии будет просто сохранен на диск (если в него вносились правки), а окно выбора пути не появится вовсе. Выясним причину: этот параметр создавался для автосохранения рабочих таблиц, а не для экспорта печатных форм пользователем.
Если ваша цель — сделать так, чтобы по нажатию отдельной кнопки «Сохранить в файл» на форме сразу открывалось окно выбора пути (с предзаполненным именем файла), стандартного метода Показать() будет недостаточно. Нам необходимо использовать объект ДиалогВыбораФайла.
Рассмотрим, как реализовать полноценный диалог в современном асинхронном стиле (рекомендуется для платформы 8.3.15 и выше):
&НаКлиенте
Процедура СохранитьВФайл(Команда)
ТабДок = СформироватьТабДокНаСервере();
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Заголовок = "Сохранение печатной формы";
Диалог.ПолноеИмяФайла = "Накладная_" + Объект.Номер;
Диалог.Фильтр = "Файлы PDF (*.pdf)|*.pdf|Табличный документ 1С (*.mxl)|*.mxl|Документ Excel (*.xlsx)|*.xlsx";
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайлаДляСохранения", ЭтаФорма, ТабДок);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайлаДляСохранения(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы = Неопределено Тогда
Возврат; // Пользователь отменил выбор
КонецЕсли;
ТабДок = ДополнительныеПараметры;
ПутьКФайлу = ВыбранныеФайлы[0];
// Определяем формат сохранения по расширению
ТипФайла = ТипФайлаТабличногоДокумента.PDF; // По умолчанию
Если Прав(ПутьКФайлу, 4) = ".mxl" Тогда
ТипФайла = ТипФайлаТабличногоДокумента.MXL;
ИначеЕсли Прав(ПутьКФайлу, 5) = ".xlsx" Тогда
ТипФайла = ТипФайлаТабличногоДокумента.XLSX;
КонецЕсли;
// Выполняем сохранение
ТабДок.Записать(ПутьКФайлу, ТипФайла);
Сообщить("Файл успешно сохранен: " + ПутьКФайлу);
КонецПроцедуры
Преимущества этого метода:
ОповещениеЗавершения гарантирует стабильную работу конфигурации в веб-клиенте.Мы проанализировали различные варианты задания имени файла для печатных форм. Если вам нужен просто вывод формы на экран с подготовленным именем для будущего ручного сохранения — используйте свойства Заголовок и ИспользуемоеИмяФайла строго на клиентской стороне. Если нужен принудительный экспорт документа в конкретный файл по нажатию кнопки — применяйте асинхронный ДиалогВыбораФайла. Избегайте использования второго параметра метода Показать() для экспорта, так как он предназначен исключительно для теневого автосохранения.