Как передать ссылку на документ во внешнюю печатную форму в 1С 8.3 (управляемые формы)

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

Переход с обычных форм (например, УПП 1.3, УТ 10.3) на управляемые приложения и Библиотеку Стандартных Подсистем (БСП) в современных конфигурациях (УТ 11, ERP 2, КА 2, Бухгалтерия 3.0) принес множество изменений в привычную разработку. Одно из самых частых затруднений у разработчиков вызывает создание внешних печатных форм (ВПФ). В старых версиях для получения ссылки на документ использовался автоматически заполняемый реквизит СсылкаНаОбъект. В управляемом приложении этот механизм больше не работает.

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

1. Почему больше нет реквизита СсылкаНаОбъект?

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

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

2. Как зарегистрировать внешнюю печатную форму в БСП

Чтобы система «поняла», к какому документу относится печатная форма и какие команды нужно добавить в подменю «Печать», в модуле объекта обработки должна быть определена экспортная функция СведенияОВнешнейОбработке. Давайте подробно рассмотрим пример ее реализации:


Функция СведенияОВнешнейОбработке() Экспорт

    ПараметрыРегистрации = Новый Структура;
    
    // Определяем вид обработки - ПечатнаяФорма
    ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
    
    // Указываем документы, в которых будет доступна эта печатная форма
    МассивНазначений = Новый Массив;
    МассивНазначений.Добавить("Документ.ТребованиеНакладная");
    ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
    
    ПараметрыРегистрации.Вставить("Наименование", "Акт установки запчастей (ВПФ)");
    ПараметрыРегистрации.Вставить("Версия", "1.1");
    ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
    ПараметрыРегистрации.Вставить("Информация", "Дополнительная печатная форма Акт установки запчастей");
    
    // Создаем таблицу команд
    ТаблицаКоманд = ПолучитьТаблицуКоманд();
    
    // Добавляем команду печати
    // Параметры: ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение, Модификатор
    ДобавитьКоманду(ТаблицаКоманд, 
                    "Акт установки запчастей", 
                    "АктУстановкиЗапЧастей", 
                    "ВызовСерверногоМетода", 
                    Истина, 
                    "ПечатьMXL");
                    
    ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    
    Возврат ПараметрыРегистрации;

КонецФункции

Обратите внимание на параметр Использование со значением "ВызовСерверногоМетода". Это стандартный и наиболее производительный вариант запуска, при котором формирование печатной формы происходит полностью на стороне сервера без открытия вспомогательных окон.

Вспомогательные процедуры для подготовки таблицы команд выглядят стандартным образом:


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

Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
    НоваяКоманда = ТаблицаКоманд.Добавить;
    НоваяКоманда.Представление = Представление;
    НоваяКоманда.Идентификатор = Идентификатор;
    НоваяКоманда.Использование = Использование;
    НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
    НоваяКоманда.Модификатор = Модификатор;
КонецProcedures

3. Как передаются ссылки на объекты в процедуру печати

Для серверных печатных форм (режим "ВызовСерверногоМетода") точка входа — это экспортная процедура Печать в модуле объекта обработки. Давайте проанализируем её сигнатуру:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    // Здесь МассивОбъектов содержит ссылки на документы, из которых была вызвана печать.
КонецПроцедуры

Рассмотрим назначение ключевых параметров:

Если же вы используете открытие формы обработки перед печатью (режимы "ВызовКлиентскогоМетода" или "ОткрытиеФормы"), то в модуле формы обработки процедура печати принимает другие параметры:


&НаКлиенте
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    // ОбъектыНазначения - массив ссылок на исходные документы
КонецПроцедуры

4. Разбор типичных ошибок при разработке (на примере Требования-Накладной)

Давайте выясним причину, почему у некоторых разработчиков (как в сообщении №7 на форуме) печатная форма выводится на экран, но остается абсолютно пустой. Рассмотрим типичный ошибочный код и исправим его. Для автоматического поиска расхождений в данных после правок кода или доработок учета используется программа сверки бухгалтерских и налоговых проводок.

Ошибка №1: Неправильный обход результатов запроса во вложенных таблицах.
Часто разработчики выбирают данные табличной части через точку от шапки документа:


// ОШИБОЧНЫЙ ЗАПРОС
Запрос.Текст = "ВЫБРАТЬ ТребованиеНакладная.Материалы.(Номенклатура, Количество) ИЗ Документ.ТребованиеНакладная КАК ТребованиеНакладная ...";

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

Ошибка №2: Двойной вызов метода Следующий().
Посмотрите на этот фрагмент кода:


Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий(); // Первый сдвиг курсора (встали на 1-ю строку)

Пока Выборка.Следующий() Цикл // Второй сдвиг курсора!
    // Этот цикл никогда не выполнится, если в выборке всего один документ!
КонецЦикла;

Вызывая Выборка.Следующий() перед началом цикла Пока, вы сдвигаете указатель на первую запись. Заходя в цикл, вы снова сдвигаете его на вторую запись. Если печатается один документ, цикл просто пропускается, и табличный документ остается без строк.

Ошибка №3: Избыточное разыменование ссылок.
Конструкция МассивОбъектов[0].Ссылка не имеет смысла, так как элемент массива МассивОбъектов[0] уже является готовой ссылкой. Добавление свойства .Ссылка заставляет платформу делать лишнее неявное обращение к базе данных.

5. Правильный шаблон кода для внешней печатной формы

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


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

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

КонецПроцедуры

Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
    
    ТабДокумент = Новый ТабличныйДокумент;
    ТабДокумент.АвтоМасштаб = Истина;
    
    // Получаем макет, сохраненный во внешней обработке
    Макет = ПолучитьМакет("АктУстановкиЗапЧастей");
    
    ОбластьШапка = Макет.ПолучитьОбласть("ОбластьШапка");
    ОбластьСтрока = Макет.ПолучитьОбласть("ОбластьСтрока");
    ОбластьПодвал = Макет.ПолучитьОбласть("ОбластьПодвал");
    
    // Оптимальный запрос: выбираем данные напрямую из табличной части
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Материалы.Ссылка КАК Ссылка,
        |	Материалы.Ссылка.Номер КАК Номер,
        |	Материалы.Ссылка.Дата КАК Дата,
        |	Материалы.Номенклатура.Представление КАК НоменклатураПредставление,
        |	Материалы.Количество КАК Количество,
        |	Материалы.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
        |	Материалы.Себестоимость КАК Цена,
        |	Материалы.Количество * Материалы.Себестоимость КАК Сумма
        |ИЗ
        |	Документ.ТребованиеНакладная.Материалы КАК Материалы
        |ГДЕ
        |	Материалы.Ссылка В(&МассивОбъектов)
        |ИТОГИ BY
        |	Ссылка";
        
    // Выполняем запрос и обходим результаты по группировкам (по документам)
    ВыборкаПоДокументам = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    
    Пока ВыборкаПоДокументам.Следующий() Цикл
        
        // Заполняем параметры шапки для каждого отдельного документа
        ОбластьШапка.Параметры.Заполнить(ВыборкаПоДокументам);
        ОбластьШапка.Параметры.НомерДок = ПрефиксацияОбъектовКлиентСервер.ПолучитьНомерНаПечать(ВыборкаПоДокументам.Номер);
        ОбластьШапка.Параметры.ДатаДок = Формат(ВыборкаПоДокументам.Дата, "ДФ=dd.MM.yyyy");
        
        ТабДокумент.Вывести(ОбластьШапка);
        
        // Обходим строки табличной части текущего документа
        ВыборкаСтрок = ВыборкаПоДокументам.Выбрать();
        НомерСтроки = 0;
        ИтогоСумма = 0;
        
        Пока ВыборкаСтрок.Следующий() Цикл
            НомерСтроки = НомерСтроки + 1;
            
            ОбластьСтрока.Параметры.Заполнить(ВыборкаСтрок);
            ОбластьСтрока.Параметры.Сч = НомерСтроки;
            
            ТабДокумент.Вывести(ОбластьСтрока);
            
            ИтогоСумма = ИтогоСумма + ВыборкаСтрок.Сумма;
        КонецЦикла;
        
        // Заполняем и выводим подвал
        ОбластьПодвал.Параметры.СуммаИтог = ИтогоСумма;
        ОбластьПодвал.Параметры.СуммаПрописью = РаботаСЧислами.ЧислоПрописью(ИтогоСумма, "L=ru_RU", "рубль, рубля, рублей, м, копейка, копейки, копеек, ж, 2");
        
        ТабДокумент.Вывести(ОбластьПодвал);
        
        // Добавляем документ в список объектов печати для БСП
        УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабДокумент, НомерСтроки, ОбъектыПечати, ВыборкаПоДокументам.Ссылка);
        
        // Если документов несколько, выводим каждый на новой странице
        ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
        
    КонецЦикла;
    
    Возврат ТабДокумент;

КонецФункции

6. Специфика работы в нестандартных конфигурациях (Альфа-Авто и др.)

Важно помнить, что некоторые отраслевые конфигурации (например, решения от компании «Рарус», такие как «Альфа-Авто») могут использовать собственные механизмы для регистрации и формирования внешних печатных форм.

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

Резюме

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

  1. Всегда регистрируйте команду с использованием серверного метода БСП.
  2. Принимайте ссылки в процедуре Печать через первый параметр МассивОбъектов.
  3. Никогда не забывайте, что это массив, и обходить его для построения печатных форм нужно с помощью запросов с условием В(&МассивОбъектов).
← На главную