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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Управленческий учет
← На главную

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

Постановка задачи и структура данных

Рассмотрим ситуацию: нам необходимо дополнить печатную форму «Счета на оплату» данными из дополнительных сведений, такими как «Маркировка», «Товарный код» или «Вес». Основная информация о документе находится в таблице Документ.СчетНаОплатуПокупателю, а дополнительные сведения — в регистре РегистрСведений.ДополнительныеСведения.

Ключевым полем для связи является измерение Объект регистра сведений, которое имеет тип ЛюбаяСсылка. Именно здесь хранится ссылка на наш документ.

Вариант 1. Получение данных через запрос с соединением

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

Важный нюанс: Не следует обращаться к полю Объект.Ссылка. Поле Объект само по себе уже является ссылкой. Лишнее обращение через точку создает неявное соединение таблиц, что замедляет работу программы.

Рассмотрим пример построения запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Счет.Ссылка КАК Ссылка,
    |	Счет.Номер КАК Номер,
    |	Счет.Дата КАК Дата,
    |	ДопСведения.Свойство.Наименование КАК ИмяСвойства,
    |	ДопСведения.Значение КАК ЗначениеСвойства
    |ИЗ
    |	Документ.СчетНаОплатуПокупателю КАК Счет
    |		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения
    |		ПО Счет.Ссылка = ДопСведения.Объект
    |ГДЕ
    |	Счет.Ссылка = &СсылкаНаОбъект";

Запрос.УстановитьПараметр("СсылкаНаОбъект", СсылкаНаОбъект);
РезультатЗапроса = Запрос.Выполнить();

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

Вариант 2. Заполнение параметров макета через структуру

Чтобы не заполнять каждый параметр вручную, можно использовать метод Заполнить(). Для этого удобно сначала собрать все дополнительные сведения в структуру, где ключом будет имя параметра в макете, а значением — данные из регистра.

Рассмотрим алгоритм обработки результатов запроса:


Выборка = РезультатЗапроса.Выбрать();
ОбластьДанные = Макет.ПолучитьОбласть("Данные");

// Создаем структуру для хранения доп. полей
ДопПоля = Новый Структура;

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

// Массовое заполнение параметров в области макета
ОбластьДанные.Параметры.Заполнить(ДопПоля);
ТабДок.Вывести(ОбластьДанные);

Оптимизация: Транспонирование строк в колонки на уровне запроса

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

Проанализируем пример такого запроса с использованием агрегатных функций:


Запрос.Текст = 
    "ВЫБРАТЬ
    |	МАКСИМУМ(ВЫБОР КОГДА ДопСведения.Свойство.Наименование ПОДОБНО ""Маркировка%"" ТОГДА ДопСведения.Значение ИНАЧЕ NULL КОНЕЦ) КАК Маркировка,
    |	МАКСИМУМ(ВЫБОР КОГДА ДопСведения.Свойство.Наименование ПОДОБНО ""Вес%"" ТОГДА ДопСведения.Значение ИНАЧЕ NULL КОНЕЦ) КАК Вес
    |ИЗ
    |	РегистрСведений.ДополнительныеСведения КАК ДопСведения
    |ГДЕ
    |	ДопСведения.Объект = &СсылкаНаОбъект";

Этот метод более производителен, так как минимизирует количество итераций цикла при обработке результата.

Использование механизмов БСП (Библиотека стандартных подсистем)

Если вы работаете в современной конфигурации (например, БСП 2.0 и выше), крайне рекомендуется использовать встроенные функции общего назначения. Метод УправлениеСвойствами.ПолучитьЗначенияСвойств позволяет получить все дополнительные сведения объекта одним вызовом, не заботясь о структуре регистра.

Посмотрим, как это выглядит в коде:


// Получаем таблицу всех свойств объекта
ТаблицаСвойств = УправлениеСвойствами.ПолучитьЗначенияСвойств(СсылкаНаОбъект);

// Ищем конкретное значение
ПараметрыПоиска = Новый Структура("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Маркировка"));
НайденныеСтроки = ТаблицаСвойств.НайтиСтроки(ПараметрыПоиска);

Если НайденныеСтроки.Количество() > 0 Тогда
    ОбластьДанные.Параметры.Маркировка = НайденныеСтроки[0].Значение;
КонецЕсли;

Советы по надежности кода

  1. Идентификация свойств: Поиск по наименованию через СтрНачинаетсяС или НайтиПоНаименованию опасен тем, что пользователи могут переименовать свойство в пользовательском режиме. По возможности используйте программные идентификаторы или предопределенные элементы.
  2. Типизация: Помните, что значение в регистре имеет тип Характеристика.ДополнительныеСведения. Если вам нужно специфическое форматирование (например, для даты или числа), приводите тип значения перед выводом в ТабличныйДокумент.
  3. Тип ссылки: При работе с большими объемами данных в секции ГДЕ запроса полезно явно ограничивать тип объекта с помощью оператора ССЫЛКА, например: ДопСведения.Объект ССЫЛКА Документ.СчетНаОплатуПокупателю. Это помогает оптимизатору СУБД лучше использовать индексы.

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

← На главную