Как разрешить редактирование отдельного реквизита при режиме ТолькоПросмотр в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке и доработке документов в 1С 7.7 нередко возникает задача заблокировать всю форму от изменений, но оставить пользователю возможность редактировать один или два конкретных реквизита (например, флаг корректировки, комментарий или статус). Попытка включить общий режим просмотра через Форма.ТолькоПросмотр(1) и затем открыть доступ к нужному полю штатным методом или с помощью внешней компоненты FormEx часто приводит к неожиданным ошибкам или не дает визуального результата. Разберем детально, почему это происходит и как правильно решить поставленную задачу.

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

Рассмотрим, как функционируют механизмы управления доступностью элементов в платформе 1С 7.7:

  1. Приоритет платформенного режима ТолькоПросмотр: Метод Форма.ТолькоПросмотр(1) блокирует редактирование диалогового окна на системном уровне платформы. При этом блокируются абсолютно все поля ввода, переключатели и флажки. Свойство Доступность самого элемента программно может возвращать 1, однако визуально и функционально поле блокируется платформой. Ни штатные средства, ни внешняя компонента FormEx не могут переопределить это платформенное поведение для конкретного поля ввода. Исключение составляют только кнопки и текстовые поля с формулами — они сохраняют способность реагировать на нажатия мыши.
  2. Область видимости переменных расширения формы: Ошибка «Значение не представляет агрегатный объект (ПолучитьАтрибут)» возникает, когда переменная объекта РасширениеФормы объявлена локально внутри процедуры (например, ПриОткрытии) и недоступна в других процедурах модуля формы. Чтобы объект был доступен во всем модуле, переменную необходимо объявить в самом начале модуля вне процедур с помощью директивы Перем.
  3. Особенности нумерации атрибутов в FormEx: При обращении к атрибутам формы по числовому индексу через метод ПолучитьАтрибут() нумерация элементов в FormEx начинается с 0, а не с 1. Если на форме расположено 10 элементов, их индексы будут находиться в диапазоне от 0 до 9. Обращение по несуществующему индексу или неверному строковому имени приводит к отсутствию объекта атрибута.

Способ 1. Поэлементная блокировка формы через FormEx вместо ТолькоПросмотр

Проанализируем наиболее удобный и гибкий подход. Чтобы оставить определенный реквизит доступным, мы не должны использовать метод Форма.ТолькоПросмотр(1). Вместо этого мы оставляем форму доступной для редактирования, но программно отключаем доступность у всех элементов диалога, кроме нужного поля и кнопок управления.

Разберем реализацию универсальной процедуры обхода элементов. В самом начале модуля формы документа объявляем переменную расширения:

Перем РасшФормы;

Затем создаем процедуру выборочной настройки доступности. Ее можно вызывать в предопределенных процедурах ПослеОткрытия() или ПриОткрытии():


Процедура ЗаблокироватьВсеКроме(СписокРазрешенныхРеквизитов)
    Перем нАтр, ВсегоАтрибутов, АтрибутФормы;
    
    // Инициализируем расширение формы FormEx
    РасшФормы = СоздатьОбъект("РасширениеФормы");
    РасшФормы.УстановитьФорму(Форма);
    
    ВсегоАтрибутов = РасшФормы.КоличествоАтрибутов();
    
    // Нумерация атрибутов в FormEx начинается с 0
    Для нАтр = 0 По ВсегоАтрибутов - 1 Цикл
        АтрибутФормы = РасшФормы.ПолучитьАтрибут(нАтр);
        
        // Пропускаем кнопки (Тип = 1) и статические рамки/тексты (Тип = 4), чтобы сохранить интерфейс
        Если (АтрибутФормы.Тип = 1) Или (АтрибутФормы.Тип = 4) Тогда
            Продолжить;
        КонецЕсли;
        
        // Проверяем, входит ли идентификатор атрибута в список разрешенных
        Если Найти(СписокРазрешенныхРеквизитов, Врег(СокрЛП(АтрибутФормы.Идентификатор))) > 0 Тогда
            АтрибутФормы.Доступность = 1;
        Иначе
            АтрибутФормы.Доступность = 0;
        КонецЕсли;
    КонецЦикла;
    
    // Дополнительно блокируем кнопки проведения и перезаписи, если документ менять нельзя
    Если Выбран() = 1 Тогда
        Форма.кнПровести.Доступность(0);
        Форма.кнЗаписать.Доступность(0);
    КонецЕсли;
КонецПроцедуры

Вызов процедуры в коде модуля выглядит следующим образом:


Процедура ПослеОткрытия()
    Если УсловиеБлокировки = 1 Тогда
        // Передаем через запятую имена реквизитов, которые должны остаться активными
        ЗаблокироватьВсеКроме("КОРРЕКТИРОВКА,КОММЕНТАРИЙ");
    КонецЕсли;
КонецПроцедуры

Способ 2. Ввод значения через кнопку или формулу при включенном ТолькоПросмотр

Посмотрим на ситуацию, когда по требованиям конфигурации отказаться от Форма.ТолькоПросмотр(1) нельзя. Так как кнопки и элементы с назначенными формулами остаются кликабельными даже в режиме только для просмотра, мы можем организовать ввод значения через модальный диалог.

  1. Оставляем реквизит заблокированным платформой.
  2. Рядом с реквизитом размещаем кнопку или делаем текстовую надпись с формулой вызова процедуры (например, ИзменитьКорректировку()).
  3. В вызванной процедуре запрашиваем новое значение и программно обновляем реквизит документа.

Рассмотрим пример реализации такого обработчика:


Процедура ИзменитьКорректировку()
    Перем ВведенноеЗначение;
    
    ВведенноеЗначение = Корректировка;
    Если ВвестиЗначение(ВведенноеЗначение, "Укажите значение корректировки", "Число", 10, 2) = 1 Тогда
        Корректировка = ВведенноеЗначение;
        // При необходимости сохраняем изменение в базе данных
        Если Модифицированность() = 1 Тогда
            Записать();
        КонецЕсли;
        Форма.Обновить();
    КонецЕсли;
КонецПроцедуры

Способ 3. Вызов отдельной формы редактирования реквизитов

Проанализируем типовой подход, часто встречающийся в стандартных конфигурациях (например, «Торговля и Склад 7.7» или «Комплексная конфигурация»).

Когда документ проведен или заблокирован для редактирования пользователем, на форме создается кнопка «Изменить реквизиты». По нажатию кнопки модально открывается специализированная внешняя обработка, которой в качестве параметра передается контекст документа:


Процедура ПоКнопкеРедактироватьРеквизиты()
    ОткрытьФормуМодально("Обработка.РедактированиеРеквизитовШапки", Контекст);
КонецПроцедуры

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

← На главную