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

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

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

Анализ проблемы и выбор стратегии

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

Выделим два основных пути решения задачи:

  1. Программное формирование реквизитов и элементов формы (динамическая таблица значений).
  2. Использование поля табличного документа для имитации ячеек ввода.

Разберем наиболее гибкий и современный метод — работу с динамическими реквизитами формы.

Способ 1: Программное создание колонок через ИзменитьРеквизиты()

Этот метод считается «золотым стандартом». Мы программно описываем структуру таблицы значений, которая будет служить буфером для данных регистра. Рассмотрим пошаговый алгоритм реализации.

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

Шаг 2: Создание новых реквизитов. Воспользуемся методом ИзменитьРеквизиты. Нам нужно создать массив объектов типа РеквизитФормы. Проанализируем пример кода:


// Массив для новых реквизитов
ДобавляемыеРеквизиты = Новый Массив;
Для Каждого ВидЦены Из СписокВидовЦен Цикл
    // Формируем уникальное имя колонки, так как GUID или ссылки напрямую использовать нельзя
    ИмяКолонки = "Цена_" + СтрЗаменить(Строка(ВидЦены.Ссылка.УникальныйИдентификатор()), "-", "_");
    ДобавляемыеРеквизиты.Add(Новый РеквизитФормы(ИмяКолонки, Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "ТаблицаЦен", "Цена: " + ВидЦены.Наименование));
КонецЦикла;

ЭтаФорма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);

Шаг 3: Визуализация данных. После создания реквизитов в памяти, их нужно вывести на экран. Для этого используем коллекцию Элементы. Важно привязывать каждый новый элемент к соответствующему пути данных: ТаблицаЦен.ИмяКолонки.


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

Способ 2: Использование Табличного документа для ввода

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

Выясним особенности этого подхода:

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

Оптимизация передачи данных и производительность

Работа с динамическими формами требует аккуратности в вопросах клиент-серверного взаимодействия. Рассмотрим критически важные моменты:

  1. Минимизация трафика. Не передавайте всю таблицу значений целиком, если в ней тысячи строк. Используйте постраничную навигацию или жесткие фильтры (например, по группе номенклатуры).
  2. Паттерн «Буферизация». Не записывайте изменения в регистр сведений при каждом изменении ячейки. Это создаст избыточную нагрузку на БД и постоянные серверные вызовы. Правильнее будет реализовать кнопку «Сохранить», которая в одной транзакции проанализирует измененные строки и обновит РегистрСведенийМенеджерЗаписи.
  3. Кэширование структуры. Если состав колонок меняется редко, можно хранить описание текущей структуры в скрытом реквизите формы, чтобы не перестраивать элементы при каждом открытии.

Алгоритм сохранения данных

Посмотрим, как эффективно перенести данные из нашей виртуальной таблицы обратно в регистр. Проанализируем пример функции сохранения:


Процедура ЗаписатьИзмененияНаСервере()
    // Проходим по строкам нашей динамической таблицы
    Для Каждого СтрокаДанных Из Объект.ТаблицаЦен Цикл
        Для Каждого Колонка Из СписокКолонокВидовЦен Цикл
            ИмяПоля = Колонка.Имя; // То самое имя, которое мы создавали динамически
            ЗначениеЦены = СтрокаДанных[ИмяПоля];
            
            // Используем менеджер записи для обновления данных в регистре
            МенеджерЗаписи = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
            МенеджерЗаписи.Номенклатура = СтрокаДанных.Номенклатура;
            МенеджерЗаписи.ВидЦены = Колонка.СсылкаНаВидЦены;
            МенеджерЗаписи.Период = ТекущаяДата();
            
            МенеджерЗаписи.Прочитать();
            Если МенеджерЗаписи.Выбран() Тогда
                Если ЗначениеЦены = 0 Тогда
                    МенеджерЗаписи.Удалить();
                Иначе
                    МенеджерЗаписи.Цена = ЗначениеЦены;
                    МенеджерЗаписи.Записать();
                КонецЕсли;
            ИначеЕсли ЗначениеЦены <> 0 Тогда
                МенеджерЗаписи.Цена = ЗначениеЦены;
                МенеджерЗаписи.Записать();
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры

Заключение

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

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

← На главную