Как запретить изменение элементов управляемой формы при сохранении возможности редактирования отдельных реквизитов

Программист 1С v8.3 (Управляемые формы) Управленческий учет
← На главную

В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача: ограничить пользователю возможность редактирования документа (например, «Реализация товаров и услуг»), но при этом оставить доступными несколько конкретных полей (например, «Дата отгрузки» или «Комментарий») и сохранить функциональность кнопок проведения. Разберем, почему стандартные подходы не всегда работают и как правильно реализовать эту логику на управляемых формах.

Разбор проблемы: почему «не помогает» простая установка доступности

Рассмотрим ситуацию, с которой сталкиваются многие разработчики: при попытке заблокировать всю форму или обойти элементы в цикле, либо блокируется абсолютно всё (включая нужные поля), либо форма остается полностью доступной. Основная причина кроется в иерархической структуре элементов управляемой формы. Если вы устанавливаете Доступность = Ложь для группы (родительского элемента), то все дочерние элементы внутри этой группы автоматически становятся недоступными, даже если вы явно пропишете для них Доступность = Истина в коде ниже.

Проанализируем основные свойства, которые отвечают за запрет редактирования:

  1. Доступность (Enabled): Если установлено в Ложь, элемент становится «серым», его нельзя выделить, из него нельзя скопировать текст, и он полностью исключается из взаимодействия.
  2. ТолькоПросмотр (ReadOnly): Если установлено в Истина, данные в поле нельзя изменить, но их можно выделить и скопировать. Это более «мягкий» вариант ограничения, который предпочтителен для полей ввода.

Способ 1. Программный обход элементов с фильтрацией групп

Наиболее гибкий способ — это перебор всех элементов формы в цикле. Однако, чтобы не «убить» доступность нужных нам полей, мы должны игнорировать группы элементов (контейнеры) и менять состояние только у конечных полей ввода или кнопок. Выясним, как это реализовать правильно.

Рассмотрим пример кода, который можно разместить в процедуре ПриЧтенииНаСервере или ПриСозданииНаСервере:


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

Способ 2. Использование Условного оформления

Современный и наиболее производительный метод для управляемых форм — это Условное оформление. Оно работает на уровне платформы и позволяет динамически управлять свойствами элементов без написания сложных циклов. Посмотрим, как настроить его программно.

Этот метод хорош тем, что он автоматически обрабатывает появление новых элементов на форме и работает быстрее, чем ручной перебор коллекции Элементы.


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

Способ 3. Свойство формы «ТолькоПросмотр» и его нюансы

Существует самый быстрый способ заблокировать документ — установить ЭтаФорма.ТолькоПросмотр = Истина. Это свойство блокирует все данные, связанные с основным реквизитом Объект. Однако у этого метода есть два существенных недостатка для нашей задачи:

  1. Блокируется всё содержимое, и «разблокировать» отдельное поле Объект.ДатаОтгрузки внутри формы в режиме «Только просмотр» невозможно.
  2. Могут исчезнуть стандартные кнопки «Провести и закрыть».

Решение: Если вы используете этот метод, то поля, которые должны остаться доступными, не должны быть связаны с путем к данным Объект... напрямую, либо они должны управляться через дополнительные реквизиты формы, что усложняет логику записи. Поэтому для выборочной блокировки лучше использовать Способ 1.

Важные рекомендации по реализации

Проанализируем ситуацию с местом вызова кода. Крайне не рекомендуется использовать событие ПриОткрытии на клиенте для таких манипуляций. Рассмотрим почему:

Правильнее всего использовать серверный обработчик ПриЧтенииНаСервере. Он срабатывает при открытии существующего объекта и при его перечитывании (например, после записи). Если же нужно ограничить доступ и в новом (еще не записанном) документе, используйте ПриСозданииНаСервере.

Разберем еще один нюанс: Кнопки командной панели. Кнопки «Провести», «Записать» и другие команды часто находятся в автоматических группах. Если вы блокируете Доступность всей командной панели, вы не сможете оставить доступной кнопку проведения. Всегда проверяйте, не является ли элемент, который вы пытаетесь оставить доступным, частью заблокированного «родителя».

Резюме: алгоритм действий

Чтобы успешно решить задачу, пройдем по шагам:

  1. Определим четкий список Исключений (имена элементов формы).
  2. Выберем событие ПриЧтенииНаСервере для размещения кода.
  3. Реализуем цикл по ЭтаФорма.Элементы, в котором будем пропускать ГруппыФормы и элементы из списка Исключений.
  4. Для полей ввода используем ТолькоПросмотр = Истина, для кнопок — Доступность = Ложь.
  5. Если используется БСП (Библиотека стандартных подсистем), проанализируем возможность использования подсистемы «Запрет редактирования реквизитов объектов», которая позволяет управлять доступом более наглядно с помощью «замочков» на форме.

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

← На главную