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