Как правильно вывести на печать реквизиты документов-оснований в 1С:Предприятии?

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

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

В ходе нашего исследования мы рассмотрим два основных метода получения реквизитов: прямое обращение к объекту через "точку" и использование запросов к базе данных. Каждый из них имеет свои особенности, которые мы подробно изучим.

Подход 1: Обращение к реквизитам через "точку" (объектная модель) с использованием кеширования

Один из наиболее простых и часто используемых способов получения реквизитов документа-основания – это прямое обращение к ним через "точку", используя объектную модель 1С. Этот метод особенно эффективен, когда у нас уже есть ссылка на конкретный документ-основание, и нам необходимо получить несколько его реквизитов.

Механизм кеширования объектов

Давайте разберем, как работает кеширование, которое делает этот метод таким производительным. Платформа 1С:Предприятие активно использует механизм кеширования данных. Когда мы в первый раз обращаемся к любому реквизиту объекта по его ссылке (например, ДокументОснование.Номер или СчетНаОплатуПокупателю.Ссылка.Контрагент), система выполняет следующие действия:

  1. Она считывает все данные этого объекта (не только тот реквизит, к которому мы обращаемся) из базы данных.
  2. Помещает эти данные в специальную область оперативной памяти – кеш.

После того как объект попал в кеш, все последующие обращения к любым другим реквизитам этого же объекта (например, ДокументОснование.Дата, ДокументОснование.СуммаДокумента) будут выполняться мгновенно, поскольку данные будут браться непосредственно из оперативной памяти, минуя повторные обращения к СУБД. Это значительно повышает производительность и снижает нагрузку на базу данных.

Следует также учитывать, что данные остаются в кеше до тех пор, пока не будут вытеснены другими объектами (при переполнении кеша), не будут изменены в базе данных или не истечет определенный интервал времени (обычно 20 минут). Этот жизненный цикл кеша обеспечивает актуальность данных при их повторном использовании.

Когда применять обращение "через точку"?

Мы рекомендуем использовать этот подход в следующих случаях:

Посмотрим на пример использования этого метода:


// Предположим, что у нас есть ссылка на текущий документ (например, РеализацияТоваровУслуг)
// и у него есть реквизит "ДокументОснование", который ссылается на СчетНаОплатуПокупателю.

// Допустим, ПередаваемаяСсылка - это ссылка на документ, для которого формируется печать
// (например, ссылка на текущую Реализацию).
// Получим объект документа, чтобы обратиться к его реквизитам.
ДокументОбъект = ПередаваемаяСсылка.ПолучитьОбъект();

// Проверим, заполнено ли основание
Если ДокументОбъект.ДокументОснование.Пустая() Тогда
    // Обработка ситуации, когда основания нет
    НомерСчетаОснования = "";
    ДатаСчетаОснования = "";
Иначе
    // Первое обращение к реквизиту ДокументОснование.Номер
    // приведет к загрузке всего объекта ДокументОснование в кеш
    НомерСчетаОснования = ДокументОбъект.ДокументОснование.Номер;
    
    // Последующие обращения к другим реквизитам того же объекта
    // будут браться из кеша, без повторного обращения к СУБД
    ДатаСчетаОснования = ДокументОбъект.ДокументОснование.Дата;
    СуммаСчетаОснования = ДокументОбъект.ДокументОснование.СуммаДокумента;
    КонтрагентСчетаОснования = ДокументОбъект.ДокументОснование.Контрагент;
КонецЕсли;

// Далее используем НомерСчетаОснования, ДатаСчетаОснования и другие переменные
// для формирования печатной формы.

Как видим, этот код прост и интуитивно понятен. Он позволяет эффективно получать данные, используя встроенные механизмы платформы.

Подход 2: Использование запросов для получения реквизитов документов-оснований

Несмотря на эффективность обращения "через точку" для единичных объектов, существуют ситуации, когда запросы к базе данных становятся более предпочтительным, а иногда и единственно верным решением. Запросы предоставляют нам прямой и мощный инструмент для работы с данными на уровне СУБД.

Когда запросы более эффективны?

Мы проанализируем ситуацию и выясним, когда стоит отдать предпочтение запросам:

Посмотрим на пример кода, который использует запрос для получения реквизитов:


// Предположим, нам нужно получить номер и дату СчетаНаОплатуПокупателю,
// который является основанием для некого документа.
// Мы передаем ссылку на этот документ-основание в запрос.

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

// Устанавливаем параметр запроса.
// &СсылкаНаСчет должна быть ссылкой на конкретный документ СчетНаОплатуПокупателю.
Запрос.УстановитьПараметр("СсылкаНаСчет", <ТвояСсылкаНаСчет>);

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

Если Выборка.Следующий() Тогда
    НомерСчетаОснования = Выборка.НомерСчета;
    ДатаСчетаОснования = Выборка.ДатаСчета;
    СуммаСчетаОснования = Выборка.СуммаСчета;
Иначе
    // Обработка ситуации, когда счет не найден
    НомерСчетаОснования = "";
    ДатаСчетаОснования = "";
    СуммаСчетаОснования = 0;
КонецЕсли;

// Далее используем полученные значения.

Особенности работы с составными ссылочными типами в запросах

При использовании запросов мы должны быть особенно внимательны, если реквизит, ссылающийся на документ-основание, имеет составной тип (например, может быть ссылкой на Документ.СчетНаОплатуПокупателю, Документ.ЗаказПокупателя и т.д.).

Посмотрим на пример использования ВЫРАЗИТЬ():


// Предположим, у нас есть таблица ТАБЛИЦА_С_ОСНОВАНИЯМИ,
// в которой есть поле ДокументОснование составного типа.

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

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

Какой подход выбрать?

Мы выяснили причину, по которой существуют два основных подхода, и рассмотрели подробнее каждый из них. Выбор между обращением "через точку" и использованием запросов зависит от конкретной задачи:

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

← К списку