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

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

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

Постановка задачи

Представим ситуацию: у нас есть табличная часть с колонками ДатаГотовностиПирФакт и ДатаГотовностиСмрФакт. Нам необходимо вывести в две разные декорации на форме количество строк, где эти даты не заполнены. Пустая дата в первой колонке считается «Долгом А», во второй — «Долгом Б». Проблема заключается в том, что данные могут заполняться программно, и нам нужно корректно обновлять счетчики без лишней нагрузки на систему.

Метод 1: Использование функции НайтиСтроки

Первый и наиболее очевидный способ, который предоставляет платформа — это метод НайтиСтроки(). Этот метод позволяет получить массив строк, соответствующих определенному отбору. Разберем, как правильно его использовать.

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


// Создаем структуру для поиска пустых дат в первой колонке
ОтборПИР = Новый Структура;
ОтборПИР.Вставить("ДатаГотовностиПирФакт", '00010101'); // Пустая дата

// Получаем массив подходящих строк
НайденныеСтрокиПИР = Объект.ТЧ.НайтиСтроки(ОтборПИР);

// Выводим количество в декорацию на форме
Элементы.ДекорацияКоличествоПИР.Заголовок = "Кол-во долгов ПИР: " + НайденныеСтрокиПИР.Количество();

Обратите внимание, что для поиска пустых значений типа Дата мы используем литерал '00010101' или функцию Дата(1, 1, 1). Если колонка имеет составной тип, лучше использовать универсальный обход, о котором мы поговорим ниже.

Метод 2: Обход табличной части в цикле

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


// Инициализируем счетчики
СчетчикПИР = 0;
СчетчикСМР = 0;

// Перебираем строки табличной части
Для Каждого ТекущаяСтрока Из Объект.ТЧ Цикл
    
    // Проверяем условие для первого типа долга
    Если Не ЗначениеЗаполнено(ТекущаяСтрока.ДатаГотовностиПирФакт) Тогда
        СчетчикПИР = СчетчикПИР + 1;
    КонецЕсли;
    
    // Проверяем условие для второго типа долга
    Если Не ЗначениеЗаполнено(ТекущаяСтрока.ДатаГотовностиСмрФакт) Тогда
        СчетчикСМР = СчетчикСМР + 1;
    КонецЕсли;
    
КонецЦикла;

// Обновляем заголовки декораций
Элементы.ДолгиПИР.Заголовок = "Кол-во долгов ПИР - " + СчетчикПИР;
Элементы.ДолгиСМР.Заголовок = "Кол-во долгов СМР - " + СчетчикСМР;

Функция ЗначениеЗаполнено() является более надежной, чем прямое сравнение с пустой датой, так как она корректно обрабатывает значения NULL или Неопределено, которые могут возникнуть при программном заполнении или работе с внешними источниками данных.

Оптимизация производительности: Клиент или Сервер?

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

  1. На клиенте: Подсчет в цикле по данным Объект.ТЧ работает достаточно быстро, если количество строк не превышает нескольких тысяч. Это позволяет избежать контекстного вызова сервера, что делает интерфейс более отзывчивым.
  2. На сервере: Если таблица огромная или данные в ТЧ попадают в результате сложного запроса, расчет лучше проводить на сервере в той же процедуре, которая заполняет таблицу.

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

Продвинутое решение: Использование метода Итог()

Если вы хотите добиться максимальной элегантности и скорости работы, можно использовать платформенный метод Итог(). Однако он работает только с числовыми данными. Чтобы применить его для подсчета «пустых строк», выполним следующие шаги:

  1. Добавим в табличную часть два скрытых числовых реквизита: ФлагДолгаПИР и ФлагДолгаСМР.
  2. В обработчике события ПриИзменении для соответствующих дат будем записывать 1 в скрытый реквизит, если дата пустая, и 0, если заполнена.
  3. Тогда количество долгов можно будет получить мгновенно одной строкой кода.

// Пример использования метода Итог
ВсегоДолговПИР = Объект.ТЧ.Итог("ФлагДолгаПИР");
Элементы.ДекорацияПИР.Заголовок = "Всего долгов: " + ВсегоДолговПИР;

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

Где вызывать процедуру подсчета?

Чтобы данные в декорациях всегда были актуальными, процедуру подсчета (назовем ее ОбновитьСчетчикиДолгов()) необходимо вызывать в нескольких точках:

Рассмотрим пример правильной организации вызова:


&НаКлиенте
Процедура ТЧПриИзменении(Элемент)
    ОбновитьСчетчикиДолгов();
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьСчетчикиДолгов()
    // Здесь размещаем один из методов (Цикл или НайтиСтроки)
    // ... логика расчета ...
КонецПроцедуры

Заключение

Мы рассмотрели три способа решения задачи: использование НайтиСтроки, прямой обход коллекции в цикле и использование метода Итог. Для простых задач и небольших таблиц оптимальным будет цикл на стороне клиента с использованием ЗначениеЗаполнено(). Это обеспечит корректную работу с типами данных и не потребует лишних вызовов сервера. Для сложных высоконагруженных систем рекомендуется использовать скрытые колонки-флаги и метод Итог. Для автоматизации вывода итоговых показателей также можно воспользоваться готовым набором функций для организации итогов в подвале табличных частей.

← На главную