Когда мы работаем с документами в 1С:Предприятии, часто возникает задача вывести на печать информацию из документов, которые являются основанием для текущего. Например, нам нужно добавить в печатную форму счета на оплату данные из договора или заказа покупателя. Давайте вместе разберем, какие подходы существуют для решения этой задачи, проанализируем их преимущества и недостатки, чтобы вы могли выбрать наиболее подходящий для вашей ситуации.
В ходе нашего исследования мы рассмотрим два основных метода получения реквизитов: прямое обращение к объекту через "точку" и использование запросов к базе данных. Каждый из них имеет свои особенности, которые мы подробно изучим.
Один из наиболее простых и часто используемых способов получения реквизитов документа-основания – это прямое обращение к ним через "точку", используя объектную модель 1С. Этот метод особенно эффективен, когда у нас уже есть ссылка на конкретный документ-основание, и нам необходимо получить несколько его реквизитов.
Давайте разберем, как работает кеширование, которое делает этот метод таким производительным. Платформа 1С:Предприятие активно использует механизм кеширования данных. Когда мы в первый раз обращаемся к любому реквизиту объекта по его ссылке (например, ДокументОснование.Номер или СчетНаОплатуПокупателю.Ссылка.Контрагент), система выполняет следующие действия:
После того как объект попал в кеш, все последующие обращения к любым другим реквизитам этого же объекта (например, ДокументОснование.Дата, ДокументОснование.СуммаДокумента) будут выполняться мгновенно, поскольку данные будут браться непосредственно из оперативной памяти, минуя повторные обращения к СУБД. Это значительно повышает производительность и снижает нагрузку на базу данных.
Следует также учитывать, что данные остаются в кеше до тех пор, пока не будут вытеснены другими объектами (при переполнении кеша), не будут изменены в базе данных или не истечет определенный интервал времени (обычно 20 минут). Этот жизненный цикл кеша обеспечивает актуальность данных при их повторном использовании.
Мы рекомендуем использовать этот подход в следующих случаях:
Посмотрим на пример использования этого метода:
// Предположим, что у нас есть ссылка на текущий документ (например, РеализацияТоваровУслуг)
// и у него есть реквизит "ДокументОснование", который ссылается на СчетНаОплатуПокупателю.
// Допустим, ПередаваемаяСсылка - это ссылка на документ, для которого формируется печать
// (например, ссылка на текущую Реализацию).
// Получим объект документа, чтобы обратиться к его реквизитам.
ДокументОбъект = ПередаваемаяСсылка.ПолучитьОбъект();
// Проверим, заполнено ли основание
Если ДокументОбъект.ДокументОснование.Пустая() Тогда
// Обработка ситуации, когда основания нет
НомерСчетаОснования = "";
ДатаСчетаОснования = "";
Иначе
// Первое обращение к реквизиту ДокументОснование.Номер
// приведет к загрузке всего объекта ДокументОснование в кеш
НомерСчетаОснования = ДокументОбъект.ДокументОснование.Номер;
// Последующие обращения к другим реквизитам того же объекта
// будут браться из кеша, без повторного обращения к СУБД
ДатаСчетаОснования = ДокументОбъект.ДокументОснование.Дата;
СуммаСчетаОснования = ДокументОбъект.ДокументОснование.СуммаДокумента;
КонтрагентСчетаОснования = ДокументОбъект.ДокументОснование.Контрагент;
КонецЕсли;
// Далее используем НомерСчетаОснования, ДатаСчетаОснования и другие переменные
// для формирования печатной формы.
Как видим, этот код прост и интуитивно понятен. Он позволяет эффективно получать данные, используя встроенные механизмы платформы.
Несмотря на эффективность обращения "через точку" для единичных объектов, существуют ситуации, когда запросы к базе данных становятся более предпочтительным, а иногда и единственно верным решением. Запросы предоставляют нам прямой и мощный инструмент для работы с данными на уровне СУБД.
Мы проанализируем ситуацию и выясним, когда стоит отдать предпочтение запросам:
Посмотрим на пример кода, который использует запрос для получения реквизитов:
// Предположим, нам нужно получить номер и дату СчетаНаОплатуПокупателю,
// который является основанием для некого документа.
// Мы передаем ссылку на этот документ-основание в запрос.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СчетНаОплатуПокупателю.Номер КАК НомерСчета,
| СчетНаОплатуПокупателю.Дата КАК ДатаСчета,
| СчетНаОплатуПокупателю.СуммаДокумента КАК СуммаСчета
|ИЗ
| Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
|ГДЕ
| СчетНаОплатуПокупателю.Ссылка = &СсылкаНаСчет";
// Устанавливаем параметр запроса.
// &СсылкаНаСчет должна быть ссылкой на конкретный документ СчетНаОплатуПокупателю.
Запрос.УстановитьПараметр("СсылкаНаСчет", <ТвояСсылкаНаСчет>);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
НомерСчетаОснования = Выборка.НомерСчета;
ДатаСчетаОснования = Выборка.ДатаСчета;
СуммаСчетаОснования = Выборка.СуммаСчета;
Иначе
// Обработка ситуации, когда счет не найден
НомерСчетаОснования = "";
ДатаСчетаОснования = "";
СуммаСчетаОснования = 0;
КонецЕсли;
// Далее используем полученные значения.
При использовании запросов мы должны быть особенно внимательны, если реквизит, ссылающийся на документ-основание, имеет составной тип (например, может быть ссылкой на Документ.СчетНаОплатуПокупателю, Документ.ЗаказПокупателя и т.д.).
ДокументОснование.Номер, где ДокументОснование может быть разных типов), платформа может выполнить неявные соединения со всеми таблицами, входящими в этот составной тип.ВЫРАЗИТЬ() в запросе, чтобы явно указать тип и ограничить количество неявных соединений, тем самым повысив производительность.Посмотрим на пример использования ВЫРАЗИТЬ():
// Предположим, у нас есть таблица ТАБЛИЦА_С_ОСНОВАНИЯМИ,
// в которой есть поле ДокументОснование составного типа.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВЫРАЗИТЬ(ТАБЛИЦА_С_ОСНОВАНИЯМИ.ДокументОснование КАК Документ.СчетНаОплатуПокупателю).Номер КАК НомерСчета,
| ВЫРАЗИТЬ(ТАБЛИЦА_С_ОСНОВАНИЯМИ.ДокументОснование КАК Документ.СчетНаОплатуПокупателю).Дата КАК ДатаСчета
|ИЗ
| НекаяТаблицаСДокументами КАК ТАБЛИЦА_С_ОСНОВАНИЯМИ
|ГДЕ
| ТАБЛИЦА_С_ОСНОВАНИЯМИ.Ссылка = &СсылкаНаДокумент";
Также мы должны избегать выполнения запросов в цикле, так как это приводит к многократным обращениям к СУБД и значительному снижению общей производительности. Старайтесь конструировать запросы таким образом, чтобы они выбирали все необходимые данные за один раз.
Мы выяснили причину, по которой существуют два основных подхода, и рассмотрели подробнее каждый из них. Выбор между обращением "через точку" и использованием запросов зависит от конкретной задачи:
Всегда анализируйте вашу конкретную задачу и выбирайте тот метод, который обеспечит наилучшую производительность и читаемость кода. Оба подхода являются мощными инструментами в арсенации разработчика 1С.
← К списку