В процессе разработки часто возникает задача сделать интерфейс более информативным для пользователя. Одна из типичных хотелок заказчика или руководителя — видеть состав документа (например, список товаров через запятую) прямо в форме списка, не заходя в каждый документ. Разберем, как реализовать эту задачу максимально эффективно, сохранив при этом производительность системы.
Проанализируем самый надежный метод, который используется в типовых конфигурациях, таких как Зарплата и управление персоналом или ERP. Суть заключается в том, чтобы не вычислять строку при каждом открытии списка, а хранить её в самом документе.
Рассмотрим пошагово процесс реализации:
ЗаказПоставщику новый реквизит КраткийСостав с типом Строка (длина 500-1000 символов или неограниченная).ПередЗаписью и добавим код для формирования этой строки.Разберем пример кода для заполнения этого реквизита:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Ограничим количество выводимых позиций, чтобы не перегружать строку
МаксимальноеКоличество = 5;
МассивНаименований = Новый Массив;
Для Каждого СтрокаТЧ Из Товары Цикл
МассивНаименований.Добавить(Строка(СтрокаТЧ.Номенклатура));
Если МассивНаименований.Количество() >= МаксимальноеКоличество Тогда
МассивНаименований.Добавить("...");
Прервать;
КонецЕсли;
КонецЦикла;
КраткийСостав = СтрСоединить(МассивНаименований, ", ");
КонецПроцедуры
Важный момент: если вы работаете с уже существующей базой, вам потребуется обработка для первичного заполнения этого реквизита в старых документах. Чтобы не менять дату изменения документа и не провоцировать лишние миграции в обмене данными, используйте ОбменДанными.Загрузка = Истина.
Если по каким-то причинам добавлять реквизит в документ нельзя (например, конфигурация на полной поддержке и нельзя использовать расширения для данных), можно попробовать решить задачу на уровне запроса динамического списка. Выясним, как использовать для этого возможности Системы компоновки данных.
В настройках динамического списка на вкладке "Вычисляемые поля" можно использовать агрегатную функцию СоединитьСтроки. Однако помните, что это сработает только в том случае, если основной запрос списка позволяет группировку по документам с объединением вложенных таблиц.
Рассмотрим выражение для вычисляемого поля:
СоединитьСтроки(Массив(Товары.Номенклатура.Наименование), ", ")
Внимание! Этот метод может значительно замедлить прокрутку списка, так как для каждой строки списка системе придется выполнять тяжелую операцию по сборке массива строк. Мы рекомендуем использовать этот подход только на небольших объемах данных.
Иногда требуется выводить информацию, но при этом запрещено изменять сами документы (например, они находятся в закрытом периоде). В такой ситуации проанализируем вариант с созданием независимого Регистра сведений.
Алгоритм действий следующий:
СоставДокументовДляСписков.Документ (тип ДокументСсылка.ЗаказПоставщику).ТекстСостава (тип Строка).Левое Соединение с этим регистром по полю Ссылка.Этот способ позволяет обновлять информацию о составе документов фоновым заданием или при записи, не затрагивая сам объект документа и его версию (что критично для синхронизации данных).
Выясним причину, по которой иногда стоит отказаться от колонки в пользу удобства интерфейса. Если номенклатуры в заказе очень много, строка "через запятую" станет нечитаемой. Вместо этого можно разместить в форме списка документов еще один динамический список (таблицу), который будет отображать состав текущего выделенного документа.
Разберем, как это настроить:
Товары (табличная часть документа).ПараметрыСвязиДанных или настроим отбор в событии ПриАктивизацииСтроки основного списка.Пример кода для обновления состава:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Устанавливаем отбор для подчиненного списка товаров
Элементы.ГруппаСостав.Заголовок = "Состав заказа: " + ТекущиеДанные.Номер;
ОбновитьПодчиненныйСписок(ТекущиеДанные.Ссылка);
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию с точки зрения нагрузки на SQL-сервер. Динамический список по умолчанию старается выбирать только те данные, которые видны пользователю на экране. Если вы используете подзапросы или сложные функции соединения строк внутри запроса 1С, SQL-сервер не сможет эффективно использовать индексы.
Рекомендации:
Таким образом, мы рассмотрели различные подходы к реализации задачи. Выбор конкретного метода зависит от ваших ограничений (возможность изменения конфигурации) и требований к производительности системы.