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

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

Каждый разработчик 1С рано или поздно сталкивается с задачей формирования печатных форм. Это могут быть расходные накладные, счета на оплату, акты выполненных работ или сложные аналитические отчеты. Когда пользователь нажимает кнопку «Печать», перед ним открывается красивое окно с табличным документом. Но как только дело доходит до сохранения этой формы на диск через стандартное системное меню «Файл — Сохранить как...», возникает неприятная проблема: платформа настойчиво предлагает сохранить файл под стандартным и безликим именем Таблица.mxl.

Естественно, пользователям это неудобно. Им приходится каждый раз вручную переименовывать файл в «Накладная №125 от 25.10.2023.pdf» или «Счет на оплату.xlsx». В этой статье мы подробно разберем, почему стандартные попытки решить эту задачу «в лоб» не работают, выясним истинные причины такого поведения платформы 1С и рассмотрим несколько надежных способов программной установки дефолтного имени файла для различных сценариев работы.

Почему не работает метод Показать() с параметром имени файла?

Первое, что делает большинство программистов, заглянув в Синтакс-помощник, — пытается использовать параметры метода Показать(). Синтаксис этого метода выглядит следующим образом:

Показать(<Заголовок>, <ИмяФайла>, <Активизация>)

Казалось бы, решение найдено! Достаточно написать простую строку кода, и система должна сама подставить имя файла в диалог сохранения:

ТабДок.Показать("Накладная", "Накладная.mxl");

Однако на практике этот код разочаровывает. При попытке сохранить открытый документ через меню «Файл — Сохранить как...» платформа всё равно предлагает имя Таблица.mxl. Почему так происходит? Разберем эту ситуацию подробнее.

Дело в скрытой логике работы самой платформы «1С:Предприятие»:

  1. Второй параметр метода Показать() (в нашем случае "Накладная.mxl") предназначен исключительно для сценария, когда пользователь закрывает окно измененного табличного документа.
  2. Если документ был программно или интерактивно изменен (то есть его свойство Модифицированность равно Истина), при закрытии окна платформа выдаст стандартный диалог: «Документ был изменен. Сохранить?».
  3. Если пользователь ответит «Да», вот только тогда система предложит имя файла, переданное в параметре метода Показать().
  4. Если же пользователь просто открыл документ для просмотра и решил сохранить его через главное меню программы, платформа полностью игнорирует этот параметр и подставляет дефолтное системное значение Таблица.

Поскольку такое поведение не устраивает конечных пользователей, нам необходимо использовать другие, более надежные инструменты платформы.

Решение №1: Использование свойства ИспользуемоеИмяФайла

Для прямого управления именем файла, которое подставляется в диалоговое окно сохранения при вызове команды «Сохранить как...», разработчики платформы предусмотрели специальное свойство объекта ТабличныйДокумент — ИспользуемоеИмяФайла (в англоязычной локализации — UsedFileName).

Это свойство содержит строковое значение, которое система автоматически подставляет в поле «Имя файла» при любом интерактивном сохранении документа.

Давайте посмотрим на практический пример реализации этого подхода в обработчике команды печати:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    ТабДок = Новый ТабличныйДокумент;
    
    // Заполняем табличный документ на сервере
    СформироватьПечатнуюФормуНаСервере(ПараметрКоманды, ТабДок);
    
    // Настраиваем свойства отображения
    ТабДок.ОтображатьСетку = Ложь;
    ТабДок.Защита = Ложь;
    ТабДок.ТолькоПросмотр = Истина;
    ТабДок.ОтображатьЗаголовки = Истина;
    
    // Задаем имя файла по умолчанию (без расширения!)
    ТабДок.ИспользуемоеИмяФайла = "Накладная_на_отпуск_товара";
    
    // Выводим документ на экран
    ТабДок.Показать("Накладная от покупателя");
    
КонецПроцедуры

Важное примечание: Обратите внимание, что в свойстве ИспользуемоеИмяФайла мы указали имя без расширения файла (просто "Накладная_на_отпуск_товара"). Это правильный подход, поскольку пользователь в диалоговом окне сохранения сам выберет желаемый тип файла (Excel, PDF или стандартный MXL), и платформа автоматически добавит нужное расширение к вашему имени.

Внимание: Опасность использования спецсимволов!

При динамическом формировании имени файла (например, при добавлении номера и даты документа) крайне важно помнить об ограничениях операционной системы Windows на символы в именах файлов. В имени файла категорически запрещено использовать следующие символы: \ / : * ? " < > |.

Представим ситуацию: вы решили сформировать красивое имя файла:

ТабДок.ИспользуемоеИмяФайла = "Накладная №" + Объект.Номер + " от " + Формат(Объект.Дата, "ДФ=dd.MM.yyyy");

Если номер вашего документа в базе данных содержит косую черту (например, "ОФ-12/3"), то результирующее имя файла будет выглядеть как "Накладная №ОФ-12/3 от 25.10.2023". При попытке интерактивного сохранения такого файла операционная система заблокирует операцию, а платформа 1С выдаст критическую ошибку: «К сожалению, возникла ошибка при работе с файлом...».

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


&НаКлиентеНаСервереБезКонтекста
Функция ОчиститьИмяФайлаОтЗапрещенныхСимволов(Знач ИсходноеИмя) Экспорт
    
    ЗапрещенныеСимволы = "\/:*?""<>|";
    Результат = ИсходноеИмя;
    
    Для Индекс = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
        ТекущийСимвол = Сред(ЗапрещенныеСимволы, Индекс, 1);
        Результат = СтрЗаменить(Результат, ТекущийСимвол, "_");
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

Теперь мы можем безопасно формировать имя файла для сохранения:


ОпасноеИмя = "Накладная № " + НомерДокумента + " от " + Формат(ДатаДокумента, "ДФ=dd.MM.yyyy");
ТабДок.ИспользуемоеИмяФайла = ОчиститьИмяФайлаОтЗапрещенныхСимволов(ОпасноеИмя);

Применение такой функции-санитайзера убережет ваших пользователей от внезапных падений программы в момент сохранения важных отчетов.

Решение №2: Специфика Управляемых форм

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

Если поле табличного документа размещено на управляемой форме, нам необходимо обращаться к свойствам элементов этой формы. Делать это нужно на стороне сервера при инициализации или заполнении отчета:


&НаСервере
Процедура СформироватьОтчетНаСервере()
    
    // Получаем табличный документ (реквизит формы с типом ТабличныйДокумент)
    ТабДок = РеквизитФормыВЗначение("Результат");
    
    // Заполняем его данными...
    ЗаполнитьМакетДанными(ТабДок);
    
    // Возвращаем данные обратно в реквизит формы
    ЗначениеВРеквизитФормы(ТабДок, "Результат");
    
    // Устанавливаем имя файла через свойства элементов формы!
    // "Результат" — это имя элемента (Поля табличного документа) на форме
    Элементы.Результат.ИспользуемоеИмяФайла = "Реестр_документов_на_подпись";
    
КонецПроцедуры

Этот способ гарантирует, что при фокусе на данном поле табличного документа и выборе команды сохранения система предложит корректное имя.

Решение №3: Работа в конфигурациях на базе БСП

Если вы ведете разработку в современных типовых решениях (таких как 1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей ред. 11, 1С:Бухгалтерия ред. 3.0), то вывод печатных форм происходит через механизмы БСП (Библиотеки Стандартных Подсистем).

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

Для управления именами сохраняемых файлов в механизме печати БСП предусмотрены два основных пути:

Путь А. Использование свойства СинонимМакета:
При заполнении коллекции печатных форм в модуле менеджера объекта БСП ориентируется на колонку СинонимМакета. Если вы переопределите это значение динамически, система подставит его в качестве имени сохраняемого файла:


// В модуле менеджера документа, в процедуре Печать
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Находим нужную печатную форму в коллекции
    ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "Накладная");
    Если ПечатнаяФорма <> Неопределено Тогда
        // Задаем динамический синоним, который станет именем файла при сохранении
        ПечатнаяФорма.СинонимМакета = "Накладная № " + МассивОбъектов[0].Номер;
    КонецЕсли;
    
КонецПроцедуры

Путь Б. Использование свойства ИмяФайлаПечатнойФормы:
Для более точечной настройки БСП предоставляет специальное свойство ИмяФайлаПечатнойФормы в параметрах вывода. В него передается соответствие, где ключом выступает ссылка на документ, а значением — желаемое имя сохраняемого файла:


// В процедуре Печать модуля менеджера объекта
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "Накладная");
Если ПечатнаяФорма <> Неопределено Тогда
    
    ИменаФайлов = Новый Соответствие;
    Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
        ИмяФайла = "Расходная_накладная_" + СсылкаНаДокумент.Номер;
        ИменаФайлов.Вставить(СсылкаНаДокумент, ИмяФайла);
    КонецЦикла;
    
    // Передаем соответствие в БСП
    ПечатнаяФорма.ИмяФайлаПечатнойФормы = ИменаФайлов;
    
КонецЕсли;

Использование штатных механизмов БСП гарантирует стабильную работу программы без конфликтов со стандартными библиотеками обновления. В качестве образца реализации кода печати можно использовать пример внешней печатной формы для БСП.

Решение №4: Собственная кнопка сохранения (Альтернативный вариант)

Иногда требования бизнеса бывают жесткими: например, нужно, чтобы файл сохранялся строго в определенном формате (только PDF или только Excel) без лишних вопросов пользователю, либо сохранение должно происходить в один клик по специальной кнопке на форме.

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

Давайте реализуем обработку нажатия такой кнопки на клиенте:


&НаКлиенте
Процедура СохранитьВФайлВыгрузки(Команда)
    
    // Инициализируем диалог выбора файла на клиенте
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
    Диалог.Заголовок = "Укажите путь для сохранения документа";
    
    // Настраиваем фильтр доступных форматов
    Диалог.Фильтр = "Лист Excel (*.xlsx)|*.xlsx|Документ PDF (*.pdf)|*.pdf|Табличный документ (*.mxl)|*.mxl";
    
    // Задаем предопределенное имя
    Диалог.ПолноеИмяФайла = "Накладная_№_" + Объект.Номер; 
    
    // Открываем диалог пользователю
    Если Диалог.Выбрать() Тогда
        
        ПутьСохранения = Диалог.ПолноеИмяФайла;
        
        // Определяем формат сохранения на основании расширения файла
        Расширение = ВРег(ПолучитьРасширениеФайла(ПутьСохранения));
        
        ТипФайла = ТипФайлаТабличногоДокумента.MXL; // По умолчанию
        
        Если Расширение = "XLSX" Тогда
            ТипФайла = ТипФайлаТабличногоДокумента.XLSX;
        ИначеЕсли Расширение = "PDF" Тогда
            ТипФайла = ТипФайлаТабличногоДокумента.PDF;
        КонецЕсли;
        
        // Получаем табличный документ из реквизита формы и записываем на диск
        ТабличныйДокументНаФорме = ПолучитьТабличныйДокумент(); 
        ТабличныйДокументНаФорме.Записать(ПутьСохранения, ТипФайла);
        
        ПоказатьПредупреждение(, "Файл успешно сохранен на диск!");
        
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Функция ПолучитьРасширениеФайла(ПолноеИмя)
    ПозицияТочки = Найти(ПолноеИмя, ".");
    Если ПозицияТочки = 0 Тогда
        Возврат "";
    КонецЕсли;
    Возврат Сред(ПолноеИмя, ПозицияТочки + 1);
КонецФункции

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

Резюме и рекомендации

Мы подробно разобрали особенности работы платформы 1С при сохранении табличных документов. Подведем краткие итоги нашей совместной работы:

Применение этих простых правил сделает работу пользователей с вашей программой комфортной, предсказуемой и избавит от лишних рутинных действий по переименованию файлов вручную.

← На главную