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