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