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