Как реализовать «необычную» табличную часть в виде кросс-таблицы в 1С?

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

При разработке сложных прикладных решений в системе 1С:Предприятие 8.3 часто возникает задача отображения данных в виде «шахматки» или кросс-таблицы. Классический пример — документ «Табель учета рабочего времени», где строки — это сотрудники, а колонки — дни месяца. В типовых конфигурациях, таких как 1С:ERP или ЗУП 3.1, такие интерфейсы встречаются повсеместно. Рассмотрим подробнее, как программно реализовать подобную таблицу, если стандартная табличная часть объекта (с фиксированным набором реквизитов) не подходит для удобного ввода данных.

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

Метод 1. Использование Поля табличного документа на форме

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

Проанализируем пошагово процесс реализации этого метода:

  1. Размещение элемента: Добавим на управляемую форму реквизит с типом ТабличныйДокумент и вынесем его на форму как Поле табличного документа.
  2. Программное формирование макета: При открытии формы или смене периода мы должны очистить табличный документ и заполнить его заново. Для этого используем метод Вывести() или прямое обращение к области Область().
  3. Включение интерактивности: Чтобы пользователь мог редактировать ячейки, необходимо для соответствующих областей установить свойство ТолькоПросмотр = Ложь.
  4. Обработка ввода данных: Это самый важный этап. Табличный документ не связан с данными объекта напрямую. Нам нужно создать обработчик события ПриИзмененииСодержимогоОбласти.

Рассмотрим пример кода для обработки ввода значения в ячейку:


&НаКлиенте
Процедура ТабличныйДокументПриИзмененииСодержимогоОбласти(Элемент, Область)
    // Определяем, в какой строке и колонке находится измененная ячейка
    СтрокаНомер = Область.Верх;
    КолонкаНомер = Область.Лево;
    
    // Получаем данные, которые ввел пользователь
    НовоеЗначение = Область.Текст;
    
    // Вызываем серверную процедуру для записи данных в настоящую ТЧ документа
    ОбновитьДанныеОбъектаНаСервере(СтрокаНомер, КолонкаНомер, НовоеЗначение);
КонецПроцедуры

Плюсы метода: Неограниченные возможности визуального оформления, поддержка сложного группирования колонок.

Минусы метода: Высокая трудоемкость реализации синхронизации данных и отсутствие стандартных функций таблицы (поиск, сортировка, фильтрация).

Метод 2. Динамическое создание колонок Таблицы формы

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

Суть заключается в том, что в конфигураторе мы создаем «плоскую» табличную часть, а на форме программно «разворачиваем» её. Для этого используются методы ИзменитьРеквизиты().

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

  1. Подготовка структуры: Создаем массив объектов РеквизитФормы. Каждый реквизит будет представлять собой колонку (например, конкретный день месяца).
  2. Добавление реквизитов: Используем ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов). Важно помнить, что добавлять их нужно к коллекции данных формы, связанной с вашей таблицей.
  3. Создание элементов формы: После создания реквизитов нужно создать визуальные элементы типа ПолеФормы и связать их с созданными реквизитами через свойство ПутьКДанным.

Посмотрим на пример создания динамических колонок:


&НаСервере
Процедура СоздатьДинамическиеКолонки(СписокДат)
    МассивРеквизитов = Новый Массив;
    Для Каждого ТекущаяДата Из СписокДат Цикл
        ИмяРеквизита = "Дата_" + Формат(ТекущаяДата, "ДФ=yyyyMMdd");
        НовыйРеквизит = Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("Число"), "Объект.ДанныеТаблицы", "Сумма за " + ТекущаяДата);
        МассивРеквизитов.Добавить(НовыйРеквизит);
    КонецЦикла;
    
    ЭтаФорма.ИзменитьРеквизиты(МассивРеквизитов);
    
    Для Каждого Реквизит Из МассивРеквизитов Цикл
        НовыйЭлемент = Элементы.Добавить(Реквизит.Имя, Тип("ПолеФормы"), Элементы.ТаблицаДанных);
        НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
        НовыйЭлемент.ПутьКДанным = "Объект.ДанныеТаблицы." + Реквизит.Имя;
    КонецЦикла;
КонецПроцедуры

Синхронизация данных в этом методе: Перед открытием формы необходимо заполнить динамические колонки данными из основной табличной части объекта (процесс «Pivot»). Перед записью документа нужно выполнить обратную операцию — собрать данные из динамических колонок и записать их в строки табличной части.

Сравнение и выбор решения

Проанализируем ситуацию: какой метод выбрать именно вам? Если ваша задача требует сложного оформления (например, выделение цветом выходных, разные уровни заголовков над датами, объединение ячеек по вертикали), то ваш выбор — Табличный документ. Он сложнее в программировании «логики сохранения», но дает полный контроль над «картинкой».

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

Важные рекомендации при работе с «необычными» таблицами:

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

← На главную