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

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

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

Проблема хранения: 31 колонка против нормализованной таблицы

Первое побуждение разработчика — добавить в табличную часть документа 31 реквизит для значений каждого дня и еще 31 реквизит-флаг для признака расчета. Однако создание жесткой структуры из десятков реквизитов имеет серьезные недостатки:

  1. Негибкость метаданных: месяцы имеют разное количество дней (28, 29, 30, 31), из-за чего часть колонок будет пустовать или требовать постоянного скрытия.
  2. Сложность запросов и проведения: выборка и запись данных из десятков колонок в регистры накопления или сведений превращается в громоздкий запрос с объединением десятков подзапросов.
  3. Избыточность структуры данных: добавление новых признаков умножает число колонок в геометрической прогрессии.

Рассмотрим правильный подход: разделение модели хранения данных и модели их отображения на форме. Этот паттерн применяется в типовых конфигурациях (например, в документе Установка цен номенклатуры или Табель учета рабочего времени).

Архитектура хранения данных (бэкенд)

В структуре метаданных документа табличную часть организуют в нормализованном (вертикальном) виде. Для этого достаточно небольшого набора реквизитов:

  1. Параметр (или ссылка на аналитику, строку расчетов).
  2. ДеньМесяца (или Дата / Период).
  3. Значение (Число).
  4. ПоСреднему (Булево — признак расчета по среднему значению).

Такая табличная часть скрывается на управляемой форме. При проведении документа данные из такой структуры считываются максимально быстро и прозрачно одной простой выборкой.

Построение интерфейса: динамические колонки на форме

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

Разберем по шагам алгоритм создания такой матрицы на сервере:

  1. При создании формы или при смене месяца формируется массив новых реквизитов формы через метод ИзменитьРеквизиты().
  2. Для каждого дня месяца создаются реквизиты: поле значения и (при необходимости) поле флага или статуса.
  3. Создаются соответствующие элементы формы (поля ввода) с привязкой к созданным реквизитам.
  4. Данные из скрытой табличной части разворачиваются (pivot) в строки таблицы формы.

Посмотрим на пример программного добавления колонок на форму:


&НаСервере
Процедура СформироватьКолонкиДнейНаСервере(КоличествоДней)

    // 1. Удаляем старые динамические элементы и реквизиты (если были)
    // 2. Описываем новые реквизиты
    ДобавляемыеРеквизиты = Новый Массив;
    
    Для День = 1 По КоличествоДней Цикл
        ИмяРеквизита = "День_" + Формат(День, "ЧЦ=2; ЧВН=");
        ДобавляемыеРеквизиты.Добавить(
            Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "ТаблицаМатрицы")
        );
    КонецЦикла;
    
    ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    
    // 3. Создаем элементы формы
    ТаблицаЭлемент = Элементы.ТаблицаМатрицы;
    Для День = 1 По КоличествоДней Цикл
        ИмяКолонки = "День_" + Формат(День, "ЧЦ=2; ЧВН=");
        ЭлементКолонка = Элементы.Добавить(ИмяКолонки, Тип("ПолеФормы"), ТаблицаЭлемент);
        ЭлементКолонка.Вид = ВидПоляФормы.ПолеВвода;
        ЭлементКолонка.ПутьКДанным = "ТаблицаМатрицы." + ИмяКолонки;
        ЭлементКолонка.Заголовок = Строка(День);
    КонецЦикла;

КонецПроцедуры

Обращение к колонкам по динамическому имени

Частый вопрос разработчиков: как обратиться к ячейке таблицы, если имя колонки хранится в переменной? Попытка использовать точечную нотацию вроде Объект.ТЧ[НомерСтроки].ИмяПеременной приводит к ошибке компиляции. Для динамического доступа используется синтаксис квадратных скобок:


// Правильное обращение к колонке по имени переменной:
СтрокаДанных = ТаблицаМатрицы[НомерСтроки];
СтрокаДанных[ИмяКолонки] = РассчитанноеЗначение;

Интерактивная пометка ячеек и расчет по среднему

Чтобы не загромождать интерфейс двойным количеством колонок (число + флажок для каждого дня), можно применить более эргономичные подходы:

  1. Контекстное меню или кнопка на командной панели: пользователь активирует нужную ячейку (или выделяет диапазон) и нажимает команду «Рассчитать по среднему».
  2. Условное оформление: признак расчета по среднему фиксируется во внутренней структуре данных строки, а ячейка выделяется цветом фона или шрифтом через УсловноеОформление формы. Это дает наглядную картину без лишних флажков.
  3. Альтернатива: Поле табличного документа. Вместо таблицы формы можно использовать табличный документ в режиме ввода данных. В нем легко отслеживать клики, устанавливать расшифровки и менять оформление конкретных ячеек на лету.

Где выполнять расчет среднего значения?

Проанализируем места выполнения расчета:

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

Не рекомендуется откладывать расчет среднего исключительно на этап формирования отчетов или проведения по регистрам. Фиксация рассчитанных значений непосредственно в данных документа гарантирует воспроизводимость истории и позволяет пользователю сверить и проверить все показатели перед проведением.

← На главную