Как определить статус оплаты («Оплачено», «Частично», «Не оплачено») в табличной части 1С?

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

В разработке на платформе 1С:Предприятие часто возникает задача анализа данных внутри табличной части документа или обработки. Типичный пример — определение общего агрегированного статуса документа на основе данных в строках. Представим ситуацию: у нас есть табличная часть с колонкой Оплачено (тип Булево), и нам нужно вывести в отчет или на форму краткий итог: «Оплачено» (если все строки помечены), «Частично» (если флаг стоит лишь в некоторых строках) или «Не оплачено» (если оплаты нет ни в одной строке).

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

Способ 1. Реализация через язык запросов (оптимально для отчетов)

Если ваша задача — вывести данные в отчет или получить результат для большого количества документов, использование запроса является самым быстрым и правильным методом. Рассмотрим подробнее логику работы с типом Булево в агрегатных функциях запроса.

В языке запросов 1С значение ИСТИНА считается «большим», чем ЛОЖЬ. Это позволяет нам использовать функции МИНИМУМ и МАКСИМУМ для анализа состояния всех строк. Разберем логику:

Посмотрим на пример реализации такого запроса:


ВЫБРАТЬ
    ВЫБОР
        КОГДА МИНИМУМ(ТЧ.Оплачено) = ИСТИНА ТАКЖЕ
            ТОГДА "Оплачено"
        КОГДА МАКСИМУМ(ТЧ.Оплачено) = ЛОЖЬ
            ТОГДА "Не оплачено"
        ИНАЧЕ "Частично"
    КОНЕЦ КАК СтатусОплаты
ИЗ
    Документ.ЗаказПокупателя.Товары КАК ТЧ
ГДЕ
    ТЧ.Ссылка = &Ссылка

Также в обсуждениях часто упоминается функция Количество(Различные ...). Мы можем проанализировать количество уникальных состояний. Если количество различных значений равно 1, значит все строки одинаковы (либо все оплачены, либо все нет). Однако этот метод требует дополнительной проверки, какое именно значение является единственным, поэтому вариант с МИНИМУМ/МАКСИМУМ более лаконичен.

Способ 2. Использование объектной техники (встроенный язык)

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

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

  1. Сначала проверим, есть ли вообще строки в табличной части.
  2. Затем поищем строки, где оплата ЛОЖЬ.
  3. Затем поищем строки, где оплата ИСТИНА.

Пример кода на встроенном языке:


ПараметрыПоискаЛожь = Новый Структура("Оплачено", Ложь);
ПараметрыПоискаИстина = Новый Структура("Оплачено", Истина);

КолвоЛожь = Объект.ТЧ.НайтиСтроки(ПараметрыПоискаЛожь).Количество();
КолвоИстина = Объект.ТЧ.НайтиСтроки(ПараметрыПоискаИстина).Количество();
ОбщееКолво = Объект.ТЧ.Количество();

Если ОбщееКолво = 0 Тогда
    Статус = "Нет данных";
ИначеЕсли КолвоЛожь = 0 Тогда
    Статус = "Оплачено";
ИначеЕсли КолвоИстина = 0 Тогда
    Статус = "Не оплачено";
Иначе
    Статус = "Частично";
КонецЕсли;

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

Способ 3. Метод «Итог» (быстрый расчет для числовых данных)

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

Если бы у нас была числовая колонка, где Истина = 1, а Ложь = 0, то:

В коде это можно реализовать через быстрый цикл, который прерывается при нахождении разных значений. Это самый производительный способ для «тонкого клиента»:


ЕстьОплата = Ложь;
ЕстьДолг = Ложь;

Для Каждого СтрокаТЧ Из Объект.ТЧ Цикл
    Если СтрокаТЧ.Оплачено Тогда
        ЕстьОплата = Истина;
    Иначе
        ЕстьДолг = Истина;
    КонецЕсли;
    
    Если ЕстьОплата И ЕстьДолг Тогда
        Прервать; // Уже понятно, что оплачено частично
    КонецЕсли;
КонецЦикла;

Если Не ЕстьОплата И Не ЕстьДолг Тогда
    Статус = "Пусто";
ИначеЕсли ЕстьОплата И Не ЕстьДолг Тогда
    Статус = "Оплачено";
ИначеЕсли Не ЕстьОплата И ЕстьДолг Тогда
    Статус = "Не оплачено";
Иначе
    Статус = "Частично";
КонецЕсли;

Способ 4. Реализация в СКД (Система компоновки данных)

Если вы разрабатываете отчет, то лучше всего вынести эту логику в ресурсы СКД. Проанализируем, как это сделать без написания программного кода. В поле «Выражение» для ресурса СтатусОплаты можно прописать конструкцию ВЫБОР, используя функции Минимум и Максимум, аналогично первому способу.

Также полезно использовать функцию ВычислитьВыражение. В СКД это выглядит так:

ВЫБОР КОГДА Минимум(Оплачено) = ИСТИНА ТОГДА "Оплачено" КОГДА Максимум(Оплачено) = ЛОЖЬ ТОГДА "Не оплачено" ИНАЧЕ "Частично" КОНЕЦ

Важные нюансы и обработка исключений

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

  1. Пустая табличная часть: Обязательно предусмотрите условие для случая, когда в таблице нет строк. С точки зрения логики бизнеса, отсутствие строк может трактоваться по-разному. В коде это проверяется через ТЧ.Количество() = 0.
  2. Производительность: Если проверка выполняется при открытии формы списка для каждой строки (в динамическом списке), используйте только запросы и старайтесь избегать сложных вычислений на стороне сервера для каждой строки отдельно.
  3. Тип данных: Помните, что в некоторых старых версиях платформы или при определенных настройках метаданных, значения могут быть NULL, если данные получены левым соединением. В этом случае используйте функцию ЕСТЬNULL(Поле, ЛОЖЬ).

Мы рассмотрели основные подходы к расчету агрегированного статуса по булевым полям. Выбор метода зависит от того, где именно должен отображаться результат: в печатной форме, в отчете СКД или непосредственно в интерфейсе документа при его редактировании пользователем.

← На главную