В процессе работы с программами на платформе 1С:Предприятие 8.3 пользователи часто сталкиваются с необходимостью визуально выделять важные для них документы. Стандартный механизм условного оформления отлично справляется с задачами, когда критерии раскраски строго определены разработчиком (например, выделить просроченные задачи красным цветом или закрытые заказы серым). Однако на практике пользователи часто просят дать им инструмент «ручного» маркера: возможность кликнуть на любой документ в списке и покрасить его строку в произвольный цвет — зеленый, синий, желтый — без привязки к жестким бизнес-правилам.
В этой статье мы подробно разберем, как реализовать такую интерактивную раскраску документов в динамическом списке на управляемых формах 1С 8.3. Мы спроектируем систему хранения пользовательских цветов, создадим удобный интерфейс выбора цвета и рассмотрим два различных механизма вывода цвета на экран, включая современный высокопроизводительный метод для платформы версии 8.3.10 и выше.
Для того чтобы система помнила, какой документ в какой цвет раскрашен, нам необходимо организовать надежное хранение этих данных в базе данных. Поскольку раскраска должна быть индивидуальной для каждого пользователя, хранить цвет непосредственно в реквизитах самого документа — не лучшая идея. Наиболее правильным архитектурным решением является создание нового регистра сведений.
Создадим новый независимый непериодический Регистр сведений с именем ПользовательскиеЦветаДокументов. Настроим его структуру следующим образом:
Измерения регистра:
Пользователь (тип: СправочникСсылка.Пользователи) — определяет, кто именно раскрасил документ. Это позволит разным сотрудникам настраивать списки под себя, не мешая коллегам.Документ (тип: ДокументСсылка или определяемый тип, включающий нужные виды документов) — ссылка на конкретный документ, который подлежит раскраске.Ресурсы регистра:
Хранить системный тип 1С Цвет в базе данных напрямую нельзя. Мы можем использовать несколько подходов к сериализации цвета, но самый простой, надежный и быстродействующий при запросах — это хранение цвета в виде трех числовых компонентов RGB (Red, Green, Blue):
Красный (тип: Число, длина 3, точность 0, неотрицательное).Зеленый (тип: Число, длина 3, точность 0, неотрицательное).Синий (тип: Число, длина 3, точность 0, неотрицательное).Теперь добавим на форму списка документов возможность выбора цвета. Для этого создадим команду формы, например, УстановитьЦветДокумента, и выведем ее на командную панель формы списка в виде кнопки с понятным заголовком «Пометить цветом».
Разберем программный код, который будет выполняться при нажатии на эту кнопку. Сначала на клиенте мы должны получить текущую строку динамического списка и открыть стандартный диалог выбора цвета 1С.
&НаКлиенте
Процедура УстановитьЦветДокумента(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
ПоказатьПредупреждение(, "Пожалуйста, выберите документ из списка!");
Возврат;
КонецЕсли;
// Инициализируем диалог выбора цвета
ДиалогВыбора = Новый ДиалогВыбораЦвета;
// Зададим цвет по умолчанию (например, светло-серый)
ДиалогВыбора.Цвет = Новый Цвет(240, 240, 240);
// Открываем диалог асинхронно
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораЦвета", ЭтотОбъект, ТекущиеДанные.Ссылка);
ДиалогВыбора.Показать(ОписаниеОповещения);
КонецПроцедуры
После того как пользователь выберет нужный оттенок в палитре и нажмет «ОК», управление передается в процедуру оповещения. В ней мы извлекаем RGB-составляющие выбранного цвета и отправляем их на сервер для записи в наш регистр сведений.
&НаКлиенте
Процедура ПослеВыбораЦвета(ВыбранныйЦвет, ДокументСсылка) Экспорт
Если ВыбранныйЦвет = Неопределено Тогда
Возврат; // Пользователь отказался от выбора
КонецЕсли;
// Извлекаем компоненты цвета
Красный = ВыбранныйЦвет.Красный();
Зеленый = ВыбранныйЦвет.Зеленый();
Синий = ВыбранныйЦвет.Синий();
// Записываем настройки цвета в базу данных на сервере
ЗаписатьЦветДокументаНаСервере(ДокументСсылка, Красный, Зеленый, Синий);
// Обновляем отображение динамического списка
Элементы.Список.Обновить();
КонецПроцедуры
Процедура записи на сервере выполняет стандартные манипуляции с менеджером записи регистра сведений:
&НаСервереБезContext
Процедура ЗаписатьЦветДокументаНаСервере(ДокументСсылка, Красный, Зеленый, Синий)
ТекущийПользователь = Пользователи.ТекущийПользователь();
МенеджерЗаписи = РегистрыСведений.ПользовательскиеЦветаДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Пользователь = ТекущийПользователь;
МенеджерЗаписи.Документ = ДокументСсылка;
// Если выбран белый цвет или близкий к нему, можно удалить запись, чтобы сбросить оформление
Если Красный = 255 И Зеленый = 255 И Синий = 255 Тогда
МенеджерЗаписи.Удалить();
Иначе
МенеджерЗаписи.Красный = Красный;
МенеджерЗаписи.Зеленый = Зеленый;
МенеджерЗаписи.Синий = Синий;
МенеджерЗаписи.Записать(Истина);
КонецЕсли;
КонецПроцедуры
Когда данные сохранены в регистре, нам остается решить ключевую задачу: как покрасить строки динамического списка на форме. Рассмотрим два эффективных метода реализации этого шага.
Это самый современный и производительный способ решения задачи. Начиная с версии платформы 8.3.10, разработчикам доступен обработчик событий таблицы формы ПриПолученииДанныхНаСервере. Он заменяет старое событие обычных форм ПриВыводеСтроки и работает оптимально: платформа передает в него только те строки, которые в данный момент реально отображаются на экране пользователя (обычно от 20 до 45 строк).
Для реализации этого метода выполним следующие шаги:
Список.ПриПолученииДанныхНаСервере и создадим его обработчик.Проанализируем программный код этого обработчика:
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Соберем массив ссылок на документы, которые сейчас выводятся на экран
МассивДокументов = Новый Массив;
Для Каждого СтрокаСписка Из Строки Цикл
МассивДокументов.Добавить(СтрокаСписка.Ключ);
КонецЦикла;
Если МассивДокументов.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Выберем цвета оформления для этих документов из регистра сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цвета.Документ КАК Документ,
| Цвета.Красный КАК Красный,
| Цвета.Зеленый КАК Зеленый,
| Цвета.Синий КАК Синий
|ИЗ
| РегистрСведений.ПользовательскиеЦветаДокументов КАК Цвета
|ГДЕ
| Цвета.Пользователь = &ТекущийПользователь
| И Цвета.Документ В(&МассивДокументов)";
Запрос.УстановитьПараметр("ТекущийПользователь", Пользователи.ТекущийПользователь());
Запрос.УстановитьПараметр("МассивДокументов", МассивДокументов);
Выборка = Запрос.Выполнить().Выбрать();
// Соответствие для быстрого поиска цвета по ссылке документа
ТаблицаЦветов = Новый Соответствие;
Пока Выборка.Следующий() Цикл
ЦветСтроки = Новый Цвет(Выборка.Красный, Выборка.Зеленый, Выборка.Синий);
ТаблицаЦветов.Вставить(Выборка.Документ, ЦветСтроки);
КонецЦикла;
// Применяем оформление к строкам динамического списка
Для Каждого СтрокаСписка Из Строки Цикл
НайденныйЦвет = ТаблицаЦветов[СтрокаСписка.Ключ];
Если НайденныйЦвет <> Неопределено Тогда
// Красим фон всей строки
СтрокаСписка.Значение.Оформление.УстановитьЗначениеПараметра("ЦветФона", НайденныйЦвет);
// Альтернативно можно красить только определенную колонку, например "Номер"
// СтрокаСписка.Значение.Оформление["Номер"].УстановитьЗначениеПараметра("ЦветТекста", НайденныйЦвет);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Преимущества метода: Высочайшая скорость работы. База данных не нагружается лишними вычислениями, оформление применяется «на лету» только к видимой области экрана, а прокрутка списка остается плавной и быстрой.
Если ваша конфигурация работает на более старых версиях платформы или вы хотите использовать штатный механизм Условного Оформления формы, можно динамически формировать правила УО при открытии списка документов.
Этот способ хорошо подходит, когда уникальных раскрашенных документов в системе относительно немного. Мы прочитаем все персональные настройки пользователя для данного типа документов и программно добавим элементы условного оформления в коллекцию УсловноеОформление формы.
Разберем, как реализовать этот алгоритм в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьУсловноеОформлениеСписка();
КонецПроцедуры
&НаСервере
Процедура ОбновитьУсловноеОформлениеСписка()
// Очистим ранее созданные программные элементы оформления, чтобы избежать дублирования
Индекс = УсловноеОформление.Элементы.Количество() - 1;
Пока Индекс >= 0 Цикл
ЭлементУО = УсловноеОформление.Элементы[Индекс];
// Помечаем наши программные элементы особым свойством или просто удаляем все элементы с отбором по документам
Если ЭлементУО.ИдентификаторПользовательскойНастройки = "ПрограммнаяРаскраскаДокументов" Тогда
УсловноеОформление.Элементы.Удалить(ЭлементУО);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
// Получаем настройки цвета из регистра сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цвета.Документ КАК Документ,
| Цвета.Красный КАК Красный,
| Цвета.Зеленый КАК Зеленый,
| Цвета.Синий КАК Синий
|ИЗ
| РегистрСведений.ПользовательскиеЦветаДокументов КАК Цвета
|ГДЕ
| Цвета.Пользователь = &ТекущийПользователь";
Запрос.УстановитьПараметр("ТекущийПользователь", Пользователи.ТекущийПользователь());
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем новый элемент условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ЭлементОформления.ИдентификаторПользовательскойНастройки = "ПрограммнаяРаскраскаДокументов";
// 1. Устанавливаем оформление (цвет фона)
ЦветФона = Новый Цвет(Выборка.Красный, Выборка.Зеленый, Выборка.Синий);
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветФона);
// 2. Настраиваем отбор: красим только строку с конкретным документом
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Выборка.Документ;
// 3. Указываем поля, которые будут раскрашены (если пусто — красится вся строка)
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Список");
КонецЦикла;
КонецПроцедуры
Важное предупреждение: Метод динамического УО отлично работает, когда количество разукрашенных документов исчисляется десятками. Если же пользователь раскрасит несколько тысяч документов, создание такого объема элементов условного оформления в памяти приведет к значительному замедлению открытия и отрисовки формы списка. В таких случаях настоятельно рекомендуется использовать Вариант А с обработчиком ПриПолученииДанныхНаСервере.
Мы успешно разработали полноценную систему кастомизации интерфейса динамического списка. Теперь ваши пользователи смогут самостоятельно выделять важные документы любыми маркерами на свой вкус. Описанный подход с использованием регистра сведений гарантирует сохранность данных и независимость настроек каждого сотрудника, а применение современных методов платформы 1С 8.3 обеспечит стабильную работу даже на больших объемах данных.