При разработке и кастомизации конфигураций на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с задачей отображения дополнительных данных в списках. Типичный пример — необходимость вывести в форму списка регистра сведений не просто само измерение (например, ссылку на справочник Номенклатура), но и свойства этого измерения (например, Артикул, Код или Производитель).
Иногда при попытке настроить форму стандартными средствами разработчики обнаруживают, что в дереве доступных полей невозможно «провалиться» внутрь измерения, чтобы вытащить его реквизиты. Выясним причину этой проблемы и подробно разберем по шагам несколько эффективных способов её решения в зависимости от архитектуры вашей базы данных.
Прежде чем переходить к реализации, проанализируем ситуацию и поймем, почему платформа 1С блокирует стандартное раскрытие полей измерения через точку:
Номенклатура, так и на справочник ОсновныеСредства), платформа на этапе конфигурирования не может определить, реквизиты какого именно объекта нужно отобразить. В связи с этим дерево реквизитов для данного поля не раскрывается.ЗначенияСвойствОбъектов. Напрямую через ссылку на объект метаданных в конфигураторе к ним обратиться невозможно.Ниже мы рассмотрим подробные способы решения этой задачи для различных сценариев.
Если тип вашего измерения не является составным (например, строго тип СправочникСсылка.Номенклатура), то прибегать к написанию сложных запросов не требуется. Вы можете настроить отображение реквизитов прямо в редакторе формы:
ДинамическийСписок).Артикул, Штрихкод и т.д.).Список.Номенклатура.Артикул) и перетащите его в левую часть экрана — в дерево элементов формы, в группу колонок таблицы списка.Платформа автоматически создаст новое поле формы, свяжет его с данными и будет корректно отображать значение свойства при выводе списка.
Если тип измерения вашего регистра является **составным**, нам потребуется изменить схему выборки данных динамического списка. Разберем по шагам, как это сделать:
ВЫРАЗИТЬ.Рассмотрим пример такого запроса:
ВЫБРАТЬ
РегистрЦены.Период КАК Период,
РегистрЦены.Номенклатура КАК Номенклатура,
ВЫРАЗИТЬ(РегистрЦены.Номенклатура КАК Справочник.Номенклатура).Артикул КАК Артикул,
РегистрЦены.Цена КАК Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК РегистрЦены
После применения данного запроса поле Артикул появится в списке доступных полей компоновки данных. Вы сможете легко перетащить его на форму в качестве отдельной колонки.
Если вам нужно вывести в форму списка свойства, которые создаются пользователями в режиме «1С:Предприятие» (дополнительные реквизиты БСП), классический запрос через точку не поможет. В этом случае мы воспользуемся встроенным в динамический список механизмом характеристик:
ДополнительныеРеквизитыИСведения) и таблицу, где хранятся их значения (регистр сведений ЗначенияСвойствОбъектов).Пользователи смогут самостоятельно добавлять эти колонки на форму через меню Еще — Изменить форму, а также использовать их в стандартных отборах и группировках списка.
Представим ситуацию, когда ваша конфигурация находится на поддержке, и вы не хотите снимать её с поддержки или полностью замещать форму списка в расширении. В этом случае оптимальным решением будет программная модификация запроса динамического списка при создании формы.
Для безопасного изменения текста запроса без риска синтаксических ошибок рекомендуется использовать объект СхемаЗапроса. Посмотрим на практический пример реализации в модуле формы:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Инициализируем схему запроса текущего динамического списка
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(Список.ТекстЗапроса);
// Получаем первый пакет запроса
ВыборЗапроса = СхемаЗапроса.ПакетЗапросов[0].Операторы[0];
// Добавляем новое поле (вытаскиваем реквизит "Артикул" через точку)
ИндексПоля = ВыборЗапроса.ВыбираемыеПоля.Добавить("Список.Номенклатура.Артикул");
ВыборЗапроса.ВыбираемыеПоля[ИндексПоля].Псевдоним = "АртикулНоменклатуры";
// Возвращаем измененный текст обратно в динамический список
Список.ТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();
// Программно создаем колонку в таблице формы
НоваяКолонка = Элементы.Добавить("СписокАртикулНоменклатуры", Тип("ПолеФормы"), Элементы.Список);
НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
НоваяКолонка.ПутьКДанным = "Список.АртикулНоменклатуры";
НоваяКолонка.Заголовок = "Артикул";
КонецПроцедуры
Такой подход гарантирует, что при обновлении типовой конфигурации ваши изменения не «слетят», а форма сохранит свою работоспособность.
Иногда прямое добавление полей «через точку» в текст запроса динамического списка приводит к падению производительности системы. Это происходит из-за того, что СУБД вынуждена выполнять сложные соединения (LEFT JOIN) таблиц при пролистывании списка пользователем. Если ваша база данных содержит миллионы записей, список может начать заметно «тормозить».
Для оптимизации быстродействия мы можем применить событие ПриПолученииДанныхНаСервере, которое позволяет получать свойства объектов порционно — только для тех строк, которые в данный момент отображаются на экране пользователя (обычно это 30-45 строк).
Разберем пример реализации этого метода:
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Шаг 1. Собираем уникальные ссылки на измерения из отображаемых строк
МассивНоменклатуры = Новый Массив;
Для Каждого КлючИЗначение Из Строки Цикл
ДанныеСтроки = КлючИЗначение.Значение.Данные;
Если ДанныеСтроки.Свойство("Номенклатура") И ЗначениеЗаполнено(ДанныеСтроки.Номенклатура) Тогда
МассивНоменклатуры.Добавить(ДанныеСтроки.Номенклатура);
КонецЕсли;
КонецЦикла;
Если МассивНоменклатуры.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Шаг 2. Быстрым точечным запросом получаем реквизиты только для этих ссылок
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&МассивНоменклатуры)";
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
ТаблицаСвойств = Запрос.Выполнить().Выгрузить();
// Шаг 3. Заполняем полученные данные непосредственно в оформление строк формы
Для Каждого КлючИЗначение Из Строки Цикл
ДанныеСтроки = КлючИЗначение.Значение.Данные;
ОформлениеСтроки = КлючИЗначение.Значение.Оформление;
НайденнаяСтрока = ТаблицаСвойств.Найти(ДанныеСтроки.Номенклатура, "Ссылка");
Если НайденнаяСтрока <> Неопределено Тогда
// Артикул — это имя колонки, которую мы заранее добавили на форму
Если ОформлениеСтроки.Ячейки.Свойство("Артикул") Тогда
ОформлениеСтроки.Ячейки.Артикул.УстановитьТекст(НайденнаяСтрока.Артикул);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важное примечание: При использовании этого метода колонка формы (в нашем примере Артикул) должна быть добавлена на форму как текстовое поле, не связанное напрямую с реквизитами динамического списка (то есть её путь к данным должен оставаться пустым).
Мы подробно рассмотрели пять различных подходов к изменению формы списка регистра сведений. Выберите наиболее подходящий вариант в зависимости от типа данных ваших измерений, требований к производительности и возможности внесения изменений в типовую конфигурацию.