При разработке печатных форм в среде «1С:Предприятие» программисты часто сталкиваются с задачей автоматизации рутинных действий пользователя. Одно из таких действий — сохранение сформированного отчета или печатной формы в файл (например, в формате Excel или PDF). По умолчанию платформа предлагает сохранить документ с пустым именем файла или использует стандартный заголовок формы. Это заставляет пользователя вручную копировать название документа (например, «Заказ клиента №15 от 10.10.2023»), что замедляет работу и приводит к ошибкам.
Попытка решить эту задачу «в лоб» через свойство ИспользуемоеИмяФайла у объекта ТабличныйДокумент часто заканчивается неудачей. В этой статье мы подробно разберем, почему штатные механизмы могут не срабатывать, как реализовать программное сохранение с нужным именем файла на обычных формах, как избежать проблемы с «кракозябрами» в Excel и как эта задача элегантно решается в современных конфигурациях на базе Библиотеки стандартных подсистем (БСП).
Рассмотрим ситуацию, с которой столкнулся автор темы. В коде прописывается вполне логичная строка:
ТабДокумент.ИспользуемоеИмяФайла = Строка(СсылкаНаОбъект);
Однако при выводе формы печати и нажатии на стандартную кнопку сохранения имя файла в диалоговом окне все равно остается пустым. Почему так происходит?
Дело в том, что в большинстве типовых конфигураций (особенно прошлых поколений, таких как УПП 1.2, УТ 10.3, БП 1.6) вывод документов на печать осуществляется не напрямую, а через вспомогательные общие формы. Функция УниверсальныеМеханизмы.НапечататьДокумент() создает форму-обертку, в которую помещается поле табличного документа. Когда пользователь нажимает кнопку сохранения на панели этой общей формы, управление берет на себя код самой формы, а не системная команда табличного документа. Общая форма «не знает» о том, что вы записали в свойство ИспользуемоеИмяФайла исходного табличного документа, и открывает стандартный пустой диалог.
Интересная особенность: если вывести документ на экран напрямую методом ТабДокумент.Показать(), то свойство ИспользуемоеИмяФайла отработает корректно, и платформа автоматически подставит нужное значение в имя файла. Но такой подход лишает пользователя сервисных функций общей формы печати (отправка по почте, выбор количества копий, двухсторонняя печать и т.д.).
Если мы работаем в конфигурациях на обычных формах (например, УПП) и хотим дать пользователю возможность сохранять документ в один клик с правильным именем, лучшим решением будет добавление на форму печати отдельной команды (кнопки) «Сохранить». В обработчике этой кнопки мы программно инициализируем диалог выбора файла.
Давайте разберем по шагам, как должен выглядеть правильный код этой процедуры:
Процедура КоманднаяПанельФормыСохранитьПоЗаголовку(Кнопка)
ТабДок = ПечатныйДокумент; // Получаем наш табличный документ
// Инициализируем диалог выбора файла в режиме сохранения
Режим = РежимДиалогаВыбораФайла.Сохранение;
Диалог = Новый ДиалогВыбораФайла(Режим);
Диалог.Заголовок = "Выбор файла для сохранения";
Диалог.Фильтр = "Файл Excel (*.xls)|*.xls|Документ PDF (*.pdf)|*.pdf";
Диалог.Расширение = "xls";
// Формируем имя файла на основе объекта печати
ИмяФайлаПоУмолчанию = Строка(ОбъектПечати);
Диалог.ПолноеИмяФайла = СокрЛП(ИмяФайлаПоУмолчанию);
Если Не Диалог.Выбрать() Тогда
Возврат; // Пользователь отказался от сохранения
КонецЕсли;
// Определяем формат сохранения на основе выбранного расширения
РасширениеФайла = ВРег(Прав(Диалог.ПолноеИмяФайла, 3));
Если РасширениеФайла = "XLS" Тогда
ТабДок.Записать(Диалог.ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLS);
ИначеЕсли РасширениеФайла = "PDF" Тогда
ТабДок.Записать(Диалог.ПолноеИмяФайла, ТипФайлаТабличногоДокумента.PDF);
Иначе
// По умолчанию сохраняем в родном формате MXL
ТабДок.Записать(Диалог.ПолноеИмяФайла, ТипФайлаТабличногоДокумента.MXL);
КонецЕсли;
Предупреждение("Документ успешно сохранен!");
КонецПроцедуры
Обратите внимание на ключевой момент в коде выше. Первоначальный вариант автора темы содержал ошибку:
ТабДок.Записать(Диалог.ПолноеИмяФайла);
При таком вызове файл записывался на диск с расширением .xls, но при открытии его в Microsoft Excel программа выдавала предупреждение о несовпадении формата, а внутри таблицы отображались нечитаемые символы («кракозябры»).
Причина проблемы: Метод Записать() объекта ТабличныйДокумент принимает два параметра. Первый параметр — имя файла, второй (необязательный) — формат сохранения (тип ТипФайлаТабличногоДокумента). Если второй параметр не указан, платформа 1С по умолчанию сохраняет файл в своем внутреннем бинарном формате MXL, независимо от того, какое расширение (например, .xls или .doc) вы прописали в первом параметре. В итоге на диске оказывается файл MXL, переименованный в XLS, который Excel, естественно, не может корректно прочесть.
Решение: Всегда явно указывайте тип файла вторым параметром при вызове метода Записать(). Для сохранения в старый формат Excel 97-2003 используйте ТипФайлаТабличногоДокумента.XLS. Для современных версий настоятельно рекомендуется использовать формат ТипФайлаТабличногоДокумента.XLSX.
Если вы работаете в современных конфигурациях 1С (таких как ERP 2, УТ 11, БП 3.0, ЗУП 3.1), разработанных с использованием Библиотеки стандартных подсистем (БСП), вам вообще не потребуется вручную переопределять диалоги выбора файлов или писать сложные обработчики.
В БСП вывод на печать стандартизирован. Имя файла, подставляемое при сохранении печатной формы на диск или при отправке по электронной почте, настраивается на этапе формирования коллекции печатных форм в модуле менеджера объекта.
Рассмотрим, как это реализовать в процедуре Печать модуля менеджера документа:
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем наличие нашей печатной формы в коллекции
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ИмяВашейПечатнойФормы");
Если ПечатнаяФорма <> Неопределено Тогда
ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати);
ПечатнаяФорма.ТабличныйДокумент = ТабличныйДокумент;
// Задаем индивидуальные имена файлов для сохранения каждого документа
ИменаФайлов = Новый Соответствие;
Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
// Формируем красивое представление, например: "Заказ клиента №15 от 10.10.2023"
ПредставлениеДокумента = Строка(СсылкаНаДокумент);
// Обязательно очищаем имя от символов, запрещенных операционной системой
ОчищенноеИмяФайла = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(ПредставлениеДокумента, "-");
ИменаФайлов.Вставить(СсылкаНаДокумент, ОчищенноеИмяФайла);
КонецЦикла;
// Передаем соответствие имен в специальное свойство БСП
ПечатнаяФорма.ИмяФайлаПечатнойФормы = ИменаФайлов;
КонецЕсли;
КонецПроцедуры
При использовании этого механизма БСП самостоятельно сделает следующее:
При динамическом формировании имен файлов на основе реквизитов документов (например, номеров с косой чертой вроде "Акт № 123/П-4") велика вероятность столкнуться с системной ошибкой записи. Операционные системы Windows и Linux накладывают жесткие ограничения на использование спецсимволов в путях файлов.
К числу запрещенных символов относятся: / \ : * ? " < > |. Если попытаться передать строку с этими знаками в диалог или метод Записать(), программа выдаст исключение или проигнорирует команду.
Если вы разрабатываете решение на БСП, всегда используйте готовую функцию очистки: ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(). Если же вы пишете решение для старой конфигурации с нуля, напишите простую вспомогательную функцию для удаления или замены недопустимых знаков:
Функция ОчиститьИмяФайла(Знач ИсходноеИмя) Экспорт
ЗапрещенныеСимволы = "/\:*?""<>|";
Результат = ИсходноеИмя;
Для Индекс = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
СимволЗамены = Сред(ЗапрещенныеСимволы, Индекс, 1);
Результат = СтрЗаменить(Результат, СимволЗамены, "-");
КонецЦикла;
Возврат СокрЛП(Результат);
КонецФункции
Мы проанализировали особенности работы с сохранением табличных документов в 1С. Для успешного решения задачи автоподстановки имени файла помните следующие правила:
ИспользуемоеИмяФайла работает без проблем только при прямом открытии табличного документа методом Показать().ДиалогВыбораФайла.ТипФайлаТабличногоДокумента во втором параметре метода Записать(), чтобы избежать нечитаемых символов в итоговом документе Excel.ИмяФайлаПечатнойФормы в БСП.