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