При разработке подсистем ценообразования в 1С программисты часто сталкиваются с требованием пользователей реализовать ввод данных в виде «матрицы». В такой матрице по строкам располагается Номенклатура, а по колонкам — различные ТипыЦен. Стандартная структура табличных частей 1С предполагает «плоский» вид (одна строка — одна цена), что неудобно для массового редактирования. В этой статье мы подробно разберем, как реализовать «нестандартный» документ установки цен с динамическими колонками.
Прежде всего, проанализируем важный архитектурный аспект: структура хранения данных в базе должна отличаться от структуры их представления на форме. В системе 1С данные о ценах хранятся в «плоском» виде в регистре сведений ЦеныНоменклатуры (измерения: Номенклатура, ТипЦен; ресурс: Цена). Пытаться создать документ с 20-ю жестко заданными колонками в табличной части — это ошибка, так как количество типов цен может меняться.
Рассмотрим правильный подход: в документе создается одна табличная часть Товары со следующими реквизитами:
Номенклатура (СправочникСсылка.Номенклатура)ТипЦен (СправочникСсылка.ТипыЦенНоменклатуры)Цена (Число)КлючСтроки (Число) — для связи экранной таблицы с данными документа.На форме же мы будем использовать вспомогательную ТаблицаЗначений, которую назовем ДеревоЦен или МатрицаЦен, и будем формировать её колонки программно.
Выясним, как добавить колонки на форму в режиме «1С:Предприятие». Для этого используется метод ИзменитьРеквизиты. Разберем алгоритм действий в процедуре ПриСозданииНаСервере:
// Массив для новых реквизитов
ДобавляемыеРеквизиты = Новый Массив;
ВыбранныеТипыЦен = ПолучитьСписокТиповЦен(); // Ваша функция получения типов цен
Для Каждого ТипЦен Из ВыбранныеТипыЦен Цикл
ИмяРеквизита = "Цена_" + СтрЗаменить(Строка(ТипЦен.УникальныйИдентификатор()), "-", "_");
ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("Число", 15, 2), "Объект.Товары"));
КонецЦикла;
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
После создания реквизитов необходимо программно добавить элементы формы (поля ввода), чтобы пользователь их увидел. Проанализируем пример кода:
Для Каждого ТипЦен Из ВыбранныеТипыЦен Цикл
ИмяРеквизита = "Цена_" + СтрЗаменить(Строка(ТипЦен.УникальныйИдентификатор()), "-", "_");
НовыйЭлемент = Элементы.Добавить(ИмяРеквизита, Тип("ПолеФормы"), Элементы.ТаблицаТовары);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "Объект.Товары." + ИмяРеквизита;
НовыйЭлемент.Заголовок = СокрЛП(ТипЦен.Наименование);
НовыйЭлемент.УстановитьДействие("ПриИзменении", "Подключаемое_ПриИзмененииЦены");
КонецЦикла;
Рассмотрим ситуацию, когда данные уже есть в табличной части документа, и их нужно «развернуть» в матрицу. Процесс трансформации данных из строк в колонки называется «пивот» (Pivot). Посмотрим на пример логики:
Товары в промежуточную таблицу значений.Номенклатура, чтобы получить уникальный список товаров.Важный момент: чтобы при прокрутке больших списков (более 1000 позиций) интерфейс не «тормозил», рекомендуется фиксировать левые колонки с названием товара. Для этого используем свойство ФиксацияСлева у элемента таблицы формы.
Когда пользователь меняет цену в динамической колонке, нам нужно записать это значение обратно в «плоскую» структуру данных документа. Разберем по шагам, как это работает в обработчике ПриИзменении:
Во-первых, определим, в какой колонке произошло изменение. Имя элемента формы даст нам понять, какой это ТипЦен. Во-вторых, найдем строку в табличной части документа по идентификатору текущей строки формы. Проанализируем пример обработчика:
&НаКлиенте
Процедура Подключаемое_ПриИзмененииЦены(Элемент)
ТекущиеДанные = Элементы.ТаблицаТовары.ТекущиеДанные;
ИмяКолонки = Элемент.Имя;
НоваяЦена = ТекущиеДанные[ИмяКолонки];
// Вызываем серверную процедуру для обновления реальной ТЧ объекта
ОбновитьЦенуВОбъекте(ТекущиеДанные.НомерСтроки, ИмяКолонки, НоваяЦена);
КонецПроцедуры
Посмотрим, как аналогичные задачи решаются в конфигурациях Управление торговлей 11 или ERP 2. Там часто используется механизм «зависимых цен». Например, если «Розничная» цена рассчитывается как «Закупочная + 20%», то при изменении колонки с закупочной ценой код должен автоматически пересчитать значения во всех зависимых динамических колонках этой строки.
Для реализации такой логики рекомендуем:
УсловноеОформление для подсветки цен, которые изменились по сравнению с предыдущим периодом (например, выделение красным при повышении и зеленым при снижении).В заключение отметим, что хотя визуально документ выглядит как широкая таблица, для системы 1С он остается набором строк. Главное — правильно настроить связь между экранными полями и данными объекта через КлючСтроки или Идентификатор. Это позволит сохранить целостность данных при записи документа в РегистрСведений.ЦеныНоменклатуры.