В процессе разработки интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача динамического отображения итогов. Например, когда в табличной части (ТЧ) отображается список задач или договоров, и нам нужно мгновенно показать пользователю количество «проблемных» строк (долгов) в отдельной надписи (декорации) на форме. В данной статье мы подробно разберем, как реализовать раздельный подсчет элементов по условию, проанализируем ошибки новичков и выберем наиболее элегантные способы решения задачи.
Представим ситуацию: у нас есть табличная часть с колонками ДатаГотовностиПирФакт и ДатаГотовностиСмрФакт. Нам необходимо вывести в две разные декорации на форме количество строк, где эти даты не заполнены. Пустая дата в первой колонке считается «Долгом А», во второй — «Долгом Б». Проблема заключается в том, что данные могут заполняться программно, и нам нужно корректно обновлять счетчики без лишней нагрузки на систему.
Первый и наиболее очевидный способ, который предоставляет платформа — это метод НайтиСтроки(). Этот метод позволяет получить массив строк, соответствующих определенному отбору. Разберем, как правильно его использовать.
Основная ошибка при использовании этого метода заключается в неправильном формировании структуры отбора. Если вы добавите в одну структуру два поля, система будет искать строки, где одновременно выполняются оба условия (логическое "И"). Нам же нужно посчитать их раздельно. Рассмотрим правильный алгоритм:
// Создаем структуру для поиска пустых дат в первой колонке
ОтборПИР = Новый Структура;
ОтборПИР.Вставить("ДатаГотовностиПирФакт", '00010101'); // Пустая дата
// Получаем массив подходящих строк
НайденныеСтрокиПИР = Объект.ТЧ.НайтиСтроки(ОтборПИР);
// Выводим количество в декорацию на форме
Элементы.ДекорацияКоличествоПИР.Заголовок = "Кол-во долгов ПИР: " + НайденныеСтрокиПИР.Количество();
Обратите внимание, что для поиска пустых значений типа Дата мы используем литерал '00010101' или функцию Дата(1, 1, 1). Если колонка имеет составной тип, лучше использовать универсальный обход, о котором мы поговорим ниже.
Если логика подсчета становится сложной (например, нужно проверить несколько условий или зависимости от других реквизитов), метод НайтиСтроки() может стать неудобным. В этом случае мы воспользуемся простым перебором коллекции. Проанализируем ситуацию, когда нам нужно посчитать оба вида долгов за один проход, чтобы не нагружать сервер лишними итерациями.
// Инициализируем счетчики
СчетчикПИР = 0;
СчетчикСМР = 0;
// Перебираем строки табличной части
Для Каждого ТекущаяСтрока Из Объект.ТЧ Цикл
// Проверяем условие для первого типа долга
Если Не ЗначениеЗаполнено(ТекущаяСтрока.ДатаГотовностиПирФакт) Тогда
СчетчикПИР = СчетчикПИР + 1;
КонецЕсли;
// Проверяем условие для второго типа долга
Если Не ЗначениеЗаполнено(ТекущаяСтрока.ДатаГотовностиСмрФакт) Тогда
СчетчикСМР = СчетчикСМР + 1;
КонецЕсли;
КонецЦикла;
// Обновляем заголовки декораций
Элементы.ДолгиПИР.Заголовок = "Кол-во долгов ПИР - " + СчетчикПИР;
Элементы.ДолгиСМР.Заголовок = "Кол-во долгов СМР - " + СчетчикСМР;
Функция ЗначениеЗаполнено() является более надежной, чем прямое сравнение с пустой датой, так как она корректно обрабатывает значения NULL или Неопределено, которые могут возникнуть при программном заполнении или работе с внешними источниками данных.
Выясним важный технический нюанс: где выполнять этот код? Табличная часть на управляемой форме доступна и на клиенте, и на сервере.
Объект.ТЧ работает достаточно быстро, если количество строк не превышает нескольких тысяч. Это позволяет избежать контекстного вызова сервера, что делает интерфейс более отзывчивым.Проанализируем типичную ошибку: передача всей таблицы на сервер только ради подсчета строк. Это неэффективно. Старайтесь выполнять расчет там, где данные уже «находятся» в текущий момент выполнения кода.
Если вы хотите добиться максимальной элегантности и скорости работы, можно использовать платформенный метод Итог(). Однако он работает только с числовыми данными. Чтобы применить его для подсчета «пустых строк», выполним следующие шаги:
ФлагДолгаПИР и ФлагДолгаСМР.ПриИзменении для соответствующих дат будем записывать 1 в скрытый реквизит, если дата пустая, и 0, если заполнена.
// Пример использования метода Итог
ВсегоДолговПИР = Объект.ТЧ.Итог("ФлагДолгаПИР");
Элементы.ДекорацияПИР.Заголовок = "Всего долгов: " + ВсегоДолговПИР;
Этот метод работает на уровне ядра платформы 1С и является самым быстрым способом получения суммы по колонке, что особенно критично для мобильных приложений или очень больших документов.
Чтобы данные в декорациях всегда были актуальными, процедуру подсчета (назовем ее ОбновитьСчетчикиДолгов()) необходимо вызывать в нескольких точках:
ПриОткрытии на сервере или на клиенте.ПриИзменении самой табличной части, чтобы при удалении или добавлении строк цифры обновлялись.Рассмотрим пример правильной организации вызова:
&НаКлиенте
Процедура ТЧПриИзменении(Элемент)
ОбновитьСчетчикиДолгов();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьСчетчикиДолгов()
// Здесь размещаем один из методов (Цикл или НайтиСтроки)
// ... логика расчета ...
КонецПроцедуры
Мы рассмотрели три способа решения задачи: использование НайтиСтроки, прямой обход коллекции в цикле и использование метода Итог. Для простых задач и небольших таблиц оптимальным будет цикл на стороне клиента с использованием ЗначениеЗаполнено(). Это обеспечит корректную работу с типами данных и не потребует лишних вызовов сервера. Для сложных высоконагруженных систем рекомендуется использовать скрытые колонки-флаги и метод Итог. Для автоматизации вывода итоговых показателей также можно воспользоваться готовым набором функций для организации итогов в подвале табличных частей.