При разработке собственных конфигураций на платформе «1С:Предприятие 8.3» программисты часто сталкиваются с задачей вывода связанных данных в списки документов. Типичный пример: в форме документа пользователь выбирает запчасть или товар, у которого есть артикул, хранящийся в справочнике. На форме самого документа всё отображается корректно, но при попытке вывести это же наименование артикула в форму списка документов колонка упорно остается пустой.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем внутренние механизмы платформы «1С», вызывающие этот сбой, и рассмотрим несколько надежных способов решения задачи — от простого восстановления путей к данным до оптимизированного программирования запросов динамического списка.
Для начала проанализируем ситуацию. Когда мы выводим на форму списка поле через цепочку реквизитов (например, Список.Ссылка.Номенклатура.Артикул), платформа должна динамически считать это значение из базы данных. Однако на практике колонка может не заполняться по трем основным причинам:
~ в XML-структуре формы) и колонка визуально исчезает или перестает обновляться.Товары, СписокЗЧ) прямо в запросе динамического списка через левое соединение, строки документов начинают дублироваться, ломая логику работы интерфейса.Разберем по шагам, как исправить каждую из этих проблем.
Если ранее колонка отображала данные, но после изменения текста запроса динамического списка она резко опустела, мы имеем дело с типичным поведением платформы, когда «слетают» пути к данным. Пересоздавать всю таблицу формы заново (как часто делают начинающие разработчики) вовсе не обязательно. Выполним следующие действия:
~Список.АртикулНаименование), значит, связь потеряна.Рассмотрим подробнее механизм оптимизации динамических списков. Если нам необходимо гарантировать, что поле (например, ссылка на номенклатуру или артикул) всегда будет доступно на клиенте — даже если пользователь скрыл соответствующую колонку через меню «Еще — Изменить форму» — нам поможет флаг «Использовать всегда».
Для настройки выполним следующие шаги:
Список).Артикул).Это гарантирует, что платформа включит данное поле в выборку SQL-запроса на сервере и передаст его на клиент в любом случае. Это критически важно, если мы планируем обращаться к этому полю в коде, например, в обработчике события ПриАктивизацииСтроки:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
// Обязательно проверяем на Неопределено и на тип строки группировки
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(ТекущиеДанные) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
Возврат;
КонецЕсли;
// Теперь мы можем безопасно обратиться к свойству, так как включена опция "Использовать всегда"
АртикулНоменклатуры = ТекущиеДанные.Артикул;
КонецПроцедуры
Самый надежный способ вывести любые связанные данные (включая реквизиты из других справочников) — это перевод динамического списка в режим использования произвольного запроса. Рассмотрим пример, когда нам нужно получить наименование артикула из подчиненного справочника.
Выполним настройку запроса по шагам:
Посмотрим на пример правильного запроса для динамического списка:
ВЫБРАТЬ
ДокументПриход.Ссылка КАК Ссылка,
ДокументПриход.ПометкаУдаления КАК ПометкаУдаления,
ДокументПриход.Номер КАК Номер,
ДокументПриход.Дата КАК Дата,
ДокументПриход.Проведен КАК Проведен,
ДокументПриход.Организация КАК Организация,
ДокументПриход.Контрагент КАК Контрагент,
// Получаем наименование артикула через левое соединение со справочником запчастей/номенклатуры
ЕСТЬNULL(СправочникНоменклатура.Артикул.Наименование, "") КАК НаименованиеАртикула
ИЗ
Документ.ПриходнаяНакладная КАК ДокументПриход
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
ПО ДокументПриход.Номенклатура = СправочникНоменклатура.Ссылка
Использование функции ЕСТЬNULL позволяет избежать пустых значений в интерфейсе, если номенклатура в документе по какой-то причине не заполнена.
Часто разработчики пытаются вывести реквизиты табличной части (например, список всех артикулов из спецификации документа) прямо в общую колонку списка документов. Если сделать это простым соединением таблиц в запросе динамического списка, СУБД вернет дублирующиеся строки для одного и того же документа (по одной строке на каждую строку табличной части).
Чтобы избежать этого, применим стандартный архитектурный шаблон «Мастер-Деталь» (Master-Detail). Мы разделим форму списка на две части:
Реализуем этот механизм программно. Для этого в обработчике события ПриАктивизацииСтроки основного списка документов будем вызывать серверную процедуру для обновления подчиненной таблицы:
&НаСервере
Процедура ОбновитьТабличнуюЧастьНаСервере(СсылкаНаДокумент)
// Очищаем вспомогательную таблицу на форме (тип: ТаблицаЗначений)
ТаблицаДеталей.Очистить();
Если Не ЗначениеЗаполнено(СсылкаНаДокумент) Тогда
Возврат;
КонецЕсли;
// Запрашиваем данные табличной части выбранного документа вместе с артикулами
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПриходнаяНакладнаяТовары.Номенклатура КАК Номенклатура,
| ПриходнаяНакладнаяТовары.Количество КАК Количество,
| ПриходнаяНакладнаяТовары.Цена КАК Цена,
| ПриходнаяНакладнаяТовары.Сумма КАК Сумма,
| ПриходнаяНакладнаяТовары.Номенклатура.Артикул КАК Артикул
|ИЗ
| Документ.ПриходнаяНакладная.Товары КАК ПриходнаяНакладнаяТовары
|ГДЕ
| ПриходнаяНакладнаяТовары.Ссылка = &СсылкаНаДокумент";
Запрос.УстановитьПараметр("СсылкаНаДокумент", СсылкаНаДокумент);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТаблицаДеталей.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Такой подход полностью исключает дублирование документов в основном списке, гарантирует высокую скорость работы интерфейса и позволяет выводить детальную информацию по артикулам и товарам в удобном и структурированном виде.