Использование внешних файлов .mxl в качестве макетов — это отличный способ предоставить пользователям возможность оперативно редактировать печатные формы без вмешательства в конфигурацию. Однако при программной реализации этой задачи часто возникает путаница с тем, как правильно заполнять параметры и куда выводить итоговый результат. Разберем эту ситуацию подробно, проанализируем ошибки и найдем оптимальное решение.
Рассмотрим ситуацию, с которой столкнулся автор вопроса. При попытке прочитать внешний файл и вывести его области с заполненными параметрами, 1С выдает две страницы: одну с именами параметров (как в макете) и вторую — с реальными данными. Посмотрим на исходный код, который привел к такому результату:
ТабДок = новый ТабличныйДокумент;
табдок.Прочитать("C:\LNA\LNA.mxl");
Областьмакета = табдок.ПолучитьОбласть("ОбластьПечать");
Областьмакета.Параметры.ДатаДок = Формат(ТекущаяДата(), "ДФ='''""''дд''""'' ММММ гггг ''г.'''");
ТабДок.Вывести(областьмакета);
Табдок.Показать();
Выясним причину ошибки: когда мы вызываем метод Прочитать(), объект ТабДок перестает быть «чистым листом». Он превращается в сам макет. Когда мы получаем область из этого же документа и затем делаем ТабДок.Вывести(Областьмакета), мы просто дописываем (дублируем) в конец этого же макета еще одну область, но уже с заполненными параметрами. В итоге мы видим и исходный шаблон, и результат под ним.
Проанализируем правильный подход. Для корректного формирования документа нам необходимы два независимых объекта ТабличныйДокумент:
Разберем исправленный код, который решает задачу:
// 1. Создаем объект, который будет содержать наш макет
МакетИсточник = Новый ТабличныйДокумент;
МакетИсточник.Прочитать("C:\LNA\LNA.mxl");
// 2. Создаем чистый объект для формирования итогового отчета
ТабДокРезультат = Новый ТабличныйДокумент;
// 3. Извлекаем нужную область из макета-источника
Область = МакетИсточник.ПолучитьОбласть("ОбластьПечать");
// 4. Заполняем параметры в полученной области
Область.Параметры.ДатаДок = Формат(ТекущаяДата(), "ДФ='дд ММММ гггг'");
Область.Параметры.ФИО = "Иванов Иван Иванович";
// 5. Выводим заполненную область в итоговый документ
ТабДокРезультат.Вывести(Область);
// 6. Показываем результат пользователю
ТабДокРезультат.Показать("Печать документа из внешнего макета");
Чтобы код отработал корректно, сам внешний файл должен быть правильно подготовлен. Рассмотрим важные технические нюансы оформления .mxl:
Установка параметров в ячейках: в режиме 1С:Предприятие (при редактировании макета) выделите ячейку, нажмите правую кнопку мыши и выберите «Свойства». В поле «Заполнение» должно быть выбрано значение «Параметр». Если там стоит «Текст», 1С воспримет название параметра просто как обычную надпись и код Область.Параметры.ИмяПараметра выдаст ошибку.
Использование шаблонов: если вам нужно смешать статичный текст и динамические данные в одной ячейке (например, «Договор № [Номер] от [Дата]»), установите в свойстве «Заполнение» значение «Шаблон». Тогда текст внутри квадратных скобок будет программно доступен через коллекцию Параметры.
Именованные области: обязательно выделите строки или колонки, которые планируете выводить, и через меню «Таблица -> Имена -> Назначить имя» задайте имя области (например, ОбластьПечать). Именно к этому имени мы обращаемся в методе ПолучитьОбласть().
При использовании внешних файлов важно помнить о среде выполнения. Рассмотрим подробнее проблемы доступа к путям:
C:\LNA\LNA.mxl — это путь на локальном компьютере. Если код выполняется на стороне сервера, сервер 1С не увидит этот диск.Разберем пример безопасного чтения макета, если он хранится в справочнике как двоичные данные:
// Получаем двоичные данные из хранилища (примерная логика)
ДвоичныеДанныеМакета = Справочники.МакетыПечатныхФорм.НайтиПоНаименованию("МойМакет").Данные.Получить();
// Создаем временный файл
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("mxl");
ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
// Читаем макет
Макет = Новый ТабличныйДокумент;
Макет.Прочитать(ИмяВременногоФайла);
// Удаляем временный файл после использования
УдалитьФайлы(ИмяВременногоФайла);
Посмотрим на ситуацию с точки зрения ресурсов. Метод Прочитать() — достаточно «дорогой» для системы, так как обращается к диску. Если вы печатаете 100 документов в цикле, не стоит читать файл 100 раз.
Проанализируем правильный цикл: сначала мы один раз считываем макет в переменную-контейнер, а затем в цикле только получаем области и заполняем их. Это ускорит работу в разы, так как данные будут браться из оперативной памяти, а не с жесткого диска.
Важный момент: всегда проверяйте существование файла перед его чтением с помощью метода Файл.Существует(), чтобы избежать аварийного завершения работы программы при отсутствии макета на диске.