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