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

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

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

Анализ основной ошибки: Ссылка против Строки

Рассмотрим ситуацию, когда в коде выполняется запрос к табличной части документа НачислениеЗарплаты. Автор пытается выполнить проверку условия следующим образом:


Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    Если Выборка.Организация = "Ромашка ООО" Тогда 
        // Определенные действия
    КонецЕсли;
КонецЦикла;

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

Решение 1: Обращение к свойствам через точку

Самый простой способ исправить ошибку «в лоб» — обратиться к текстовому представлению организации. У справочника есть стандартные реквизиты, такие как Наименование или Код. Проанализируем пример исправления кода:


// Вариант сравнения по наименованию
Если Выборка.Организация.Наименование = "Ромашка ООО" Тогда 
    // Действия для Ромашки
КонецЕсли;

// Вариант сравнения по коду (более надежный, так как код меняют реже)
Если Выборка.Организация.Код = "000000001" Тогда 
    // Действия по коду
КонецЕсли;

Однако помните, что обращение через точку в цикле (Выборка.Организация.Наименование) заставляет систему выполнять дополнительный неявный запрос к базе данных на каждой итерации цикла, чтобы получить это наименование. Это существенно замедляет работу программы, если строк в выборке много.

Решение 2: Оптимизация запроса (вынос полей в выборку)

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


ВЫБРАТЬ
    НачислениеЗарплатыНачисления.Ссылка.МесяцНачисления КАК МесяцНачисления,
    НачислениеЗарплатыНачисления.Сотрудник КАК Сотрудник,
    НачислениеЗарплатыНачисления.Ссылка.Организация.Наименование КАК ОрганизацияНаименование
ИЗ
    Документ.НачислениеЗарплаты.Начисления КАК НачислениеЗарплатыНачисления
ГДЕ
    НачислениеЗарплатыНачисления.Ссылка = &Ссылка

Теперь в цикле обработки результата запроса мы можем обращаться к уже готовой строке, что гораздо быстрее:


Пока Выборка.Следующий() Цикл
    Если Выборка.ОрганизацияНаименование = "Ромашка ООО" Тогда
        // Код сработает мгновенно без доп. обращений к серверу
    КонецЕсли;
КонецЦикла;

Решение 3: Использование конструкции ВЫБОР КОГДА в запросе

Рассмотрим еще более профессиональный подход. Если наша задача — определить, какую шапку макета выводить, мы можем переложить всю логику условий на сторону СУБД. Для этого используется конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ. Это позволит нам получить в результате запроса готовый признак или даже имя области макета.


ВЫБРАТЬ
    Начисления.Сотрудник,
    ВЫБОР
        КОГДА Начисления.Ссылка.Организация.Наименование ПОДОБНО "%Ромашка%" ТОГДА "ШапкаРомашка"
        КОГДА Начисления.Ссылка.Организация.Наименование ПОДОБНО "%Роза%" ТОГДА "ШапкаРоза"
        ИНАЧЕ "СтандартнаяШапка"
    КОНЕЦ КАК ИмяОбластиМакета
ИЗ
    Документ.НачислениеЗарплаты.Начисления КАК Начисления
ГДЕ
    Начисления.Ссылка = &Ссылка

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

Решение 4: Правильная структура вывода макета (проблема дублирования шапки)

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

Алгоритм правильного вывода:

  1. Выполняем запрос или получаем объект документа по ссылке.
  2. До начала цикла определяем организацию и выводим соответствующую ей шапку.
  3. Запускаем цикл по строкам (сотрудникам) и выводим только строки.
  4. После цикла выводим подвал.

Проанализируем пример кода, решающий проблему дублирования:


// 1. Получаем данные об организации один раз (из шапки документа)
ОрганизацияДокумента = СсылкаНаДокумент.Организация;

// 2. Выбираем нужную область макета до цикла
Если ОрганизацияДокумента.Наименование = "Ромашка ООО" Тогда
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка_Ромашка");
Иначе
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка_Общая");
КонецЕсли;

ТабличныйДокумент.Вывести(ОбластьШапка);

// 3. Теперь выводим строки в цикле
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    ОбластьСтрока.Параметры.Заполнить(Выборка);
    ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;

Рекомендации по оптимизации соединений

При написании запросов следует помнить, что обращение через точку к реквизитам (например, Начисления.Ссылка.Организация.Код) создает так называемые неявные левые соединения в SQL-запросе. Если поле имеет составной тип, это может привести к серьезным тормозам. Рассмотрим, как переписать запрос через явное ЛЕВОЕ СОЕДИНЕНИЕ, что считается «хорошим тоном» в разработке 1С:


ВЫБРАТЬ
    ТЧ_Начисления.Сотрудник КАК Сотрудник,
    Организации.Наименование КАК ОрганизацияНаименование
ИЗ
    Документ.НачислениеЗарплаты.Начисления КАК ТЧ_Начисления
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеЗарплаты КАК ДокШапка
        ПО ТЧ_Начисления.Ссылка = ДокШапка.Ссылка
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Организации КАК Организации
        ПО ДокШапка.Организация = Организации.Ссылка
ГДЕ
    ТЧ_Начисления.Ссылка = &Ссылка

Использование явных соединений делает структуру запроса прозрачной для других разработчиков и позволяет СУБД более эффективно строить план запроса.

Советы для профессиональной разработки

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

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

← На главную