Как программно посчитать количество заполненных ячеек в строке на управляемой форме

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

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

Постановка задачи и анализ структуры данных

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

Решение 1: Динамическое обращение к колонкам по имени в цикле

Если названия колонок имеют строгую нумерацию, самый простой и эффективный способ — организовать цикл по количеству дней. Разберем, как это сделать правильно в обработчике события ПриИзменении. Мы будем использовать конструкцию обращения к свойствам структуры через квадратные скобки.

Проанализируем пример кода, который можно разместить в модуле формы:


&НаКлиенте
Процедура ТЧПриИзмененииЯчейки(Элемент)
    
    // Получаем текущую строку, в которой произошло изменение
    СтрокаТаблицы = Элементы.ТвояТабличнаяЧасть.ТекущиеДанные;
    
    Если СтрокаТаблицы = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Инициализируем счетчик заполненных дней
    КоличествоДней = 0;
    
    // Предположим, мы считаем за полный месяц (31 день)
    Для НомерДня = 1 По 31 Цикл
        
        // Формируем имя колонки динамически
        ИмяКолонки = "День" + НомерДня;
        
        // Обращаемся к данным строки по имени колонки
        Если СтрокаТаблицы[ИмяКолонки] > 0 Тогда
            КоличествоДней = КоличествоДней + 1;
        КонецЕсли;
        
    КонецЦикла;
    
    // Записываем результат в итоговый реквизит строки
    СтрокаТаблицы.ВсегоОтработаноДней = КоличествоДней;
    
КонецПроцедуры

В данном примере мы используем ТекущиеДанные, что позволяет нам работать с объектом ДанныеФормыСтруктура. Это гарантирует, что изменения будут визуально отображены пользователю немедленно, без необходимости перезаписи всего объекта или обращения к серверу.

Решение 2: Использование метаданных для универсального обхода

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

Рассмотрим, как реализовать такой обход через коллекцию реквизитов табличной части:


&НаСервереБезКонтекста
Функция РассчитатьКоличествоЗаполненныхЯчеек(ДанныеСтроки)
    
    Результат = 0;
    // Получаем метаданные табличной части документа
    МетаданныеТЧ = Метаданные.Документы.ТабельУчетаРабочегоВремени.ТабличныеЧасти.Состав;
    
    Для Каждого Реквизит Из МетаданныеТЧ.Реквизиты Цикл
        // Проверяем, относится ли реквизит к колонкам с днями (по префиксу)
        Если Найти(Реквизит.Имя, "День") > 0 Тогда
            Если ДанныеСтроки[Реквизит.Имя] > 0 Тогда
                Результат = Результат + 1;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

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

Проблема расчета «по цвету» и правильный архитектурный подход

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

Выясним причину, почему это так. Оформление задается через УсловноеОформление формы. Чтобы правильно реализовать учет праздников или выходных, разберем следующие шаги:

  1. Создайте дополнительный (скрытый или видимый) реквизит для каждой колонки дня, например, ТипДня1, ТипДня2 (тип — ПеречислениеСсылка.ТипыДней: Явка, Выходной, Праздник).
  2. Настройте Условное оформление: если ТипДняN равен «Выходной», то цвет фона ячейки ДеньN — красный.
  3. При расчете итогов используйте проверку именно этого типа:

Для НомерДня = 1 По 31 Цикл
    Если СтрокаТаблицы["ТипДня" + НомерДня] = ПредопределенноеЗначение("Перечисление.ТипыДней.Праздник") 
         И СтрокаТаблицы["День" + НомерДня] > 0 Тогда
        // Считаем только выходы в праздничные дни
        КоличествоПраздничных = КоличествоПраздничных + 1;
    КонецЕсли;
КонецЦикла;

Оптимизация: использование коллекции элементов формы

Чтобы не перебирать все реквизиты объекта или не зашивать количество дней жестко в код, можно проанализировать коллекцию Элементы. Мы можем заранее определить, какие элементы формы (колонки таблицы) относятся к нашей задаче.

Посмотрим на пример предварительного сбора колонок в массив при создании формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Создаем массив имен колонок, которые нужно суммировать
    МассивКолонокДней = Новый Массив;
    Для Каждого Элемент Из Элементы.ТаблицаДанных.ПодчиненныеЭлементы Цикл
        Если Лев(Элемент.Имя, 4) = "День" Тогда
            МассивКолонокДней.Добавить(Элемент.Имя);
        КонецЕсли;
    КонецЦикла;
    
    // Сохраняем массив в параметрах формы для использования на клиенте
    КолонкиДляРасчета = ПоместитьВоВременноеХранилище(МассивКолонокДней, УникальныйИдентификатор);
    
КонецПроцедуры

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

Итоги и рекомендации

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

Используя эти методы, вы сможете создавать сложные интерактивные формы, такие как графики работ или производственные календари, которые будут работать стабильно и понятно для пользователя.

← На главную