Как изменить цвет фона заблокированных полей шапки документа (Номер, Дата) в 1С:Предприятие 8.3?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

При работе с документами в 1С:Предприятие часто возникает задача программно изменять оформление элементов формы, например, выделять цветом определенные реквизиты. Эта задача становится особенно актуальной, когда требуется привлечь внимание пользователя к заблокированным для редактирования полям. Однако, как показывает практика, изменение цвета фона для заблокированных полей шапки документа, таких как Номер и Дата, может оказаться неочевидной задачей. В данной статье мы подробно рассмотрим, почему возникают сложности с оформлением этих полей и какие эффективные методы можно применить для достижения желаемого результата.

Наш коллега столкнулся с ситуацией, когда стандартный функционал блокировки реквизитов документа через расширение работал отлично, но попытки выделить цветом эти же поля на форме не увенчались успехом. В отладчике свойство ЦветФона элемента формы успешно устанавливалось, но визуально на открытой форме цвет оставался стандартным. При этом поля табличной части успешно выделялись цветом. Давайте выясним причину такого поведения и предложим несколько рабочих решений.

Почему не удается изменить цвет фона заблокированных полей?

Основная причина, по которой свойство ЦветФона не применяется к заблокированным полям, особенно к стандартным реквизитам документа (таким как Номер и Дата), заключается в особенностях работы платформы 1С:Предприятие. Когда поле становится недоступным для редактирования (свойство ТолькоПросмотр = Истина или Доступность = Ложь), платформа может по-своему обрабатывать его отображение. Рассмотрим подробнее:

  1. Приоритет платформы: Для системных или заблокированных элементов платформа имеет приоритет в отображении. Это означает, что даже если мы программно установим свойство ЦветФона, платформа может проигнорировать его или переопределить своими внутренними стилями, чтобы единообразно отображать все недоступные для редактирования поля. Это особенно актуально для полей вида ПолеВвода.
  2. Особенности отрисовки: Платформа может использовать специфичные стили операционной системы или свои внутренние механизмы для отображения таких полей, которые не всегда позволяют переопределять цвет фона через прямые свойства элемента формы. Поля, предназначенные для ввода данных, при блокировке часто выглядят иначе, чем поля, предназначенные только для вывода информации.
  3. Контекст выполнения: Хотя порядок вызова событий формы (ПриСозданииНаСервере, ПриОткрытии) важен, в случае с заблокированными полями проблема чаще кроется не в этом, а именно в особенностях отрисовки платформой. Наш коллега подтвердил, что даже на конец процедуры ПриОткрытии свойство ЦветФона было установлено, но визуально изменений не происходило.

Теперь, когда мы понимаем причины, давайте перейдем к эффективным способам решения этой проблемы.

Решение 1: Использование условного оформления

Условное оформление – это мощный и предпочтительный инструмент платформы 1С для динамического изменения внешнего вида элементов формы. В отличие от прямого программного изменения свойства ЦветФона у элемента формы, условное оформление обрабатывается платформой на более высоком уровне и зачастую успешно применяется даже к заблокированным полям. Условное оформление можно настроить как интерактивно в конфигураторе, так и программно.

Мы рекомендуем использовать именно программное условное оформление, так как оно позволяет гибко управлять условиями и настройками в зависимости от логики нашего расширения.

Пошаговая реализация программного условного оформления:

Для применения условного оформления программно, необходимо выполнить следующие шаги в серверном обработчике формы, например, в процедуре ПриСозданииНаСервере или ПриЧтенииНаСервере:

  1. Создадим новый элемент условного оформления ЭлементУсловногоОформления.
  2. Зададим для него список полей, к которым должно применяться оформление (ЭлементУсловногоОформления.Поля).
  3. Определим свойства оформления, включая ЦветФона (ЭлементУсловногоОформления.Оформление).
  4. Укажем условие, при котором оформление будет применяться (ЭлементУсловногоОформления.Условие). В нашем случае условием может быть, например, статус блокировки реквизита.
  5. Добавим созданный элемент в коллекцию УсловноеОформление формы.

Рассмотрим пример кода:


// В процедуре формы ПриСозданииНаСервере или ПриЧтенииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // ... ваш код по блокировке реквизитов ...

    // Программное условное оформление для заблокированных полей
    ДобавитьУсловноеОформлениеЗаблокированныхПолей();

КонецПроцедуры

&НаСервере
Процедура ДобавитьУсловноеОформлениеЗаблокированныхПолей()
    // Создаем новый элемент условного оформления
    НовыйЭлементУО = УсловноеОформление.Элементы.Добавить();

    // Определяем поля, к которым будет применяться оформление
    ПолеУО = НовыйЭлементУО.Поля.Элементы.Добавить();
    ПолеУО.Поле = Новый ПолеКомпоновкиДанных("Объект.Номер"); // Для поля 'Номер'
    ПолеУО = НовыйЭлементУО.Поля.Элементы.Добавить();
    ПолеУО.Поле = Новый ПолеКомпоновкиДанных("Объект.Дата");  // Для поля 'Дата'
    // Добавьте сюда другие поля шапки, которые нужно выделить

    // Определяем само оформление
    НовыйЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветаСтиля.ФонЗаблокированногоПоля); // Пример цвета из стилей
    // Можно также установить ЦветТекста, Шрифт и другие параметры

    // Условие применения оформления
    // Например, если есть флаг или статус в объекте, что реквизиты заблокированы
    // Или если мы знаем, что эти поля всегда заблокированы при определенных условиях
    // В данном случае, так как мы хотим выделить именно заблокированные поля,
    // условие может быть связано с состоянием документа, которое приводит к блокировке.
    // Если блокировка происходит по общим правилам, можно просто применить оформление.
    // Пример условия (если есть реквизит в документе, который определяет блокировку):
    // УсловиеУО = НовыйЭлементУО.Условие.Элементы.Добавить(Тип("ЭлементУсловияКомпоновкиДанных"));
    // УсловиеУО.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.РеквизитБлокировки");
    // УсловиеУО.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    // УсловиеУО.ПравоеЗначение = Истина;

    // В нашем случае, поскольку мы хотим выделить поля, которые уже заблокированы другим механизмом,
    // и если мы знаем, что эти поля блокируются при создании формы, мы можем применять это оформление
    // безусловно, предполагая, что они уже 'ТолькоПросмотр'.
    // Если требуется более сложная логика, добавьте соответствующее условие.

КонецПроцедуры

Важный момент: убедитесь, что цвет ЦветаСтиля.ФонЗаблокированногоПоля или любой другой выбранный вами цвет хорошо читается с цветом текста. Для ЦветаСтиля вы можете выбрать любой из доступных цветов стиля или задать цвет напрямую с помощью функции Новый Цвет(Красный, Зеленый, Синий).

Решение 2: Программная замена полей ввода на поля надписи

Это обходное решение, предложенное одним из участников обсуждения, которое позволяет полностью обойти ограничения платформы для полей ввода. Суть метода заключается в том, что мы скрываем оригинальное ПолеВвода (которое не дает изменить фон при блокировке) и вместо него размещаем ПолеНадписи, которое значительно гибче в плане оформления и к которому не применяются ограничения заблокированных полей ввода.

Однако, здесь есть свои нюансы. Прямое изменение вида существующего элемента формы (например, ЭлементФормы.Вид = ВидПоляФормы.ПолеНадписи) может приводить к падениям базы данных в определенных версиях платформы или конфигурациях, как это было отмечено в исходном обсуждении. Поэтому мы рассмотрим более безопасный и надежный подход.

Безопасная реализация замены полей:

Вместо того чтобы менять Вид у существующего элемента, мы будем создавать новый элемент формы типа ПолеНадписи, позиционировать его поверх или рядом с исходным ПолеВвода, а исходное ПолеВвода скрывать. Это требует более сложной логики по синхронизации видимости и расположения, но исключает прямое изменение вида элемента, которое может быть причиной нестабильности.

Для этого нам потребуется процедура, которая будет создавать или обновлять замещающие поля. Предполагаем, что эта процедура будет вызываться, например, в ПриСозданииНаСервере или ПриЧтенииНаСервере формы документа.


// В процедуре формы ПриСозданииНаСервере или ПриЧтенииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // ... ваш код по блокировке реквизитов ...

    // Пример вызова для заблокированных полей
    Для Каждого ЭлементФормы Из Элементы Цикл
        // Проверяем, если элемент формы заблокирован для изменений
        // и если это поле ввода, которое мы хотим заменить/оформить.
        // Здесь мы можем использовать тот же список реквизитов, который вы использовали
        // для блокировки через БСП.
        Если (ЭлементФормы.Имя = "Номер") Или (ЭлементФормы.Имя = "Дата") Тогда
            // Условие может быть более сложным, если блокировка зависит от данных
            Если ЭлементФормы.ТолькоПросмотр Тогда
                Если ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода Тогда
                    УстановитьЗаменуПолей(ЭтаФорма, ЭлементФормы);
                КонецЕсли;
            Иначе
                // Если поле не заблокировано, убедимся, что замещающее поле скрыто,
                // а исходное поле ввода видимо (если оно было заменено ранее)
                СкрытьЗамещающееПоле(ЭтаФорма, ЭлементФормы);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

// Вспомогательная процедура для создания/обновления замещающего поля
&НаСервере
Процедура УстановитьЗаменуПолей(Форма, ЭлементПоляВвода)
    ИмяЗамещающегоПоля = ЭлементПоляВвода.Имя + "Надпись"; // Генерируем уникальное имя для надписи

    // Попытаемся найти уже существующее замещающее поле
    ЗамещающееПоле = Форма.Элементы.Найти(ИмяЗамещающегоПоля);

    Если ЗамещающееПоле = Неопределено Тогда
        // Если замещающего поля нет, создаем его
        ЗамещающееПоле = Форма.Элементы.Добавить(ИмяЗамещающегоПоля, Тип("ДекорацияФормы"), ЭлементПоляВвода.Родитель);
        ЗамещающееПоле.Вид = ВидДекорацииФормы.Надпись;
        ЗамещающееПоле.ПутьКДанным = ЭлементПоляВвода.ПутьКДанным; // Привязываем к тем же данным
        ЗамещающееПоле.Гиперссылка = Ложь; // Если нужно, можно сделать гиперссылкой
        ЗамещающееПоле.ТолькоПросмотр = Истина; // Надпись всегда только для просмотра
        ЗамещающееПоле.ЦветФона = ЦветаСтиля.ФонЗаблокированногоПоля; // Задаем нужный цвет
        // Можно задать другие параметры оформления, например, ЦветТекста, Шрифт

        // Позиционируем замещающее поле точно как исходное
        ЗамещающееПоле.Лево = ЭлементПоляВвода.Лево;
        ЗамещающееПоле.Верх = ЭлементПоляВвода.Верх;
        ЗамещающееПоле.Ширина = ЭлементПоляВвода.Ширина;
        ЗамещающееПоле.Высота = ЭлементПоляВвода.Высота;
        ЗамещающееПоле.Якоря.Лево = ЭлементПоляВвода.Якоря.Лево;
        ЗамещающееПоле.Якоря.Право = ЭлементПоляВвода.Якоря.Право;
        ЗамещающееПоле.Якоря.Верх = ЭлементПоляВвода.Якоря.Верх;
        ЗамещающееПоле.Якоря.Низ = ЭлементПоляВвода.Якоря.Низ;
        ЗамещающееПоле.Порядок = ЭлементПоляВвода.Порядок + 1; // Отображаем поверх исходного поля
    КонецЕсли;

    // Скрываем исходное поле ввода и показываем замещающее
    ЭлементПоляВвода.Видимость = Ложь;
    ЗамещающееПоле.Видимость = Истина;

    // Обязательно устанавливаем заголовок для замещающей надписи,
    // если он отличается от значения поля, или чтобы он соответствовал заголовку поля
    Если НЕ ПустаяСтрока(ЭлементПоляВвода.Заголовок) Тогда
        ЗамещающееПоле.Заголовок = ЭлементПоляВвода.Заголовок;
    КонецЕсли;

КонецПроцедуры

// Вспомогательная процедура для скрытия замещающего поля
// и возвращения видимости исходного поля ввода
&НаСервере
Процедура СкрытьЗамещающееПоле(Форма, ЭлементПоляВвода)
    ИмяЗамещающегоПоля = ЭлементПоляВвода.Имя + "Надпись";
    ЗамещающееПоле = Форма.Элементы.Найти(ИмяЗамещающегоПоля);

    Если ЗамещающееПоле <> Неопределено Тогда
        ЗамещающееПоле.Видимость = Ложь;
    КонецЕсли;
    // Возвращаем видимость исходному полю, если оно не заблокировано
    ЭлементПоляВвода.Видимость = Истина;
КонецПроцедуры

Важные замечания к этому решению:

  1. При использовании этого подхода вы по сути управляете двумя элементами формы: оригинальным полем ввода и надписью, которая его замещает. Важно синхронизировать их видимость.
  2. Метод УстановитьЗаменуПолей должен вызываться для каждого поля, которое мы хотим оформить таким образом.
  3. Для стандартных реквизитов, таких как Номер и Дата, мы используем ПутьКДанным = ЭлементПоляВвода.ПутьКДанным, чтобы надпись отображала актуальное значение реквизита.
  4. Позиционирование нового элемента ЗамещающееПоле должно точно соответствовать исходному ЭлементПоляВвода, чтобы не нарушать макет формы. Мы копируем свойства Лево, Верх, Ширина, Высота и Якоря.
  5. Если документ может изменять свой статус блокировки после открытия, необходимо предусмотреть логику, которая будет динамически менять видимость полей (либо надписи, либо поля ввода) и применять/отменять цвет фона.

Общие рекомендации и выводы

При работе с оформлением заблокированных полей в 1С:Предприятие 8.3 следует учитывать следующие моменты:

  1. Выбирайте подходящий инструмент: Для изменения визуального оформления всегда предпочтительнее использовать Условное оформление, так как это штатный и гибкий механизм платформы. Он реже приводит к непредсказуемым результатам и лучше интегрируется с остальной логикой формы.
  2. Понимайте ограничения платформы: Стандартные реквизиты и заблокированные поля ввода имеют особый статус. Платформа может накладывать на них свои правила отрисовки, игнорируя прямые программные установки некоторых свойств.
  3. Будьте осторожны с изменением вида элементов: Если вы решите использовать метод замены элементов (как ПолеВвода на ПолеНадписи), то всегда предпочтительнее создавать новые элементы и управлять их видимостью, а не изменять свойство Вид у существующих, чтобы избежать потенциальных падений базы данных.
  4. Контекст выполнения кода: Всегда размещайте код, изменяющий оформление или структуру формы, в подходящих серверных событиях, таких как ПриСозданииНаСервере или ПриЧтенииНаСервере. После отрисовки формы (т.е. после ПриОткрытии) многие изменения уже не будут применены или могут вызвать ошибки.
  5. Работа с расширениями: При использовании расширений всегда учитывайте, что ваши изменения могут конфликтовать с базовой конфигурацией или другими расширениями. Это еще одна причина, по которой механизмы, специально предназначенные для оформления (как условное оформление), являются более надежными.

В заключение, проблема с окрашиванием заблокированных полей, особенно стандартных (Номер, Дата), в 1С:Предприятие 8.3 является известной особенностью платформы. Мы рассмотрели два основных подхода к ее решению: использование программного условного оформления и программную замену полей ввода на поля надписи. Оба метода имеют свои преимущества и особенности реализации. Выбирайте тот, который лучше соответствует вашим требованиям и обеспечивает необходимую стабильность работы.

← На главную