Как установить «Только просмотр» для определенных колонок в конкретной строке табличного поля 1С?

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

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

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

Выясняем причину: почему не работает очевидный вариант?

Давайте проанализируем типичную ошибку. Часто в кодовой базе можно встретить попытку решить задачу через событие ПриНачалеРедактирования или аналогичные интерактивные обработчики следующим образом:


Если Элемент.Значение = Истина Тогда
    ЭлементыФормы.ТабличноеПоле1.Колонки.Колонка1.ТолькоПросмотр = Истина;
    ЭлементыФормы.ТабличноеПоле1.Колонки.Колонка2.ТолькоПросмотр = Истина;
КонецЕсли;

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

Дело в архитектуре отображения табличных полей в обычных формах 1С. Объект КолонкаТабличногоПоля является общим описателем для всей вертикальной области таблицы. У него нет индивидуальных свойств для каждой отдельной строки. Когда мы пишем ЭлементыФормы.ТабличноеПоле1.Колонки.Колонка1.ТолькоПросмотр = Истина, мы принудительно даем команду платформе заблокировать отображение всей колонки целиком на уровне интерфейса. Чтобы управлять доступностью ячеек индивидуально в каждой строке, нам нужно использовать совершенно другие механизмы, ориентированные на работу с оформлением конкретных строк или перехватом событий ввода.

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

Метод 1. Динамическое оформление через событие «ПриВыводеСтроки»

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

Давайте посмотрим на практический пример реализации этого обработчика:


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

Обратите особое внимание на ветку Иначе! Это самая частая ошибка при использовании событий оформления. Платформа 1С в целях экономии оперативной памяти использует механизм виртуализации строк. При прокрутке таблицы визуальные элементы строк используются повторно для отображения новых данных. Если вы программно установили свойство ТолькоПросмотр = Истина для одной строки и не сбросили его обратно в Ложь в ветке Иначе для других строк, то при прокрутке списка «заблокированное» оформление хаотично применится к совершенно случайным строкам таблицы. Всегда явно очищайте измененные визуальные свойства!

Метод 2. Оптимизация производительности с помощью события «ПриПолученииДанных»

Метод с использованием ПриВыводеСтроки прост в написании, но у него есть существенный недостаток: это событие срабатывает по отдельности для каждой строки таблицы. Если пользователь быстро прокручивает большой список (сотни или тысячи строк), интерфейс может начать заметно «подтормаживать», так как процессор будет непрерывно занят вызовом кода для каждой строки.

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

Давайте разберем по шагам, как правильно реализовать данный подход:


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

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

Метод 3. Жесткий запрет изменения через событие «ПередНачаломИзменения»

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

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

Проанализируем пример кода:


Процедура ТабличноеПоле1ПередНачаломИзменения(Элемент, Отказ)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    ТекущаяКолонка = Элемент.ТекущаяКолонка;
    
    Если ТекущиеДанные <> Неопределено И ТекущаяКолонка <> Неопределено Тогда
        
        // Если в текущей строке установлен признак блокировки
        Если ТекущиеДанные.ФлажокБлокировки = Истина Тогда
            
            // Проверяем, в какую именно колонку пытается зайти пользователь
            Если ТекущаяКолонка.Имя = "Колонка1" Или ТекущаяКолонка.Имя = "Колонка2" Тогда
                
                // Устанавливаем системный отказ от редактирования ячейки
                Отказ = Истина; 
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

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

Метод 4. Динамическое переключение колонок в «ПриАктивизацииСтроки»

Существует еще один обходной путь. Поскольку пользователь в каждый конкретный момент времени может редактировать данные только в одной, текущей активной строке, мы можем динамически менять свойство ТолькоПросмотр для всей колонки «на лету» в зависимости от того, на какую строку сейчас установлен курсор.

Давайте посмотрим, как это реализовать через событие ПриАктивизацииСтроки:


Процедура ТабличноеПоле1ПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        
        // Если флаг установлен, делаем колонки недоступными
        СостояниеБлокировки = (ТекущиеДанные.ФлажокБлокировки = Истина);
        
        ЭлементыФормы.ТабличноеПоле1.Колонки.Колонка1.ТолькоПросмотр = СостояниеБлокировки;
        ЭлементыФормы.ТабличноеПоле1.Колонки.Колонка2.ТолькоПросмотр = СостояниеБлокировки;
        
    КонецЕсли;
    
КонецПроцедуры

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

Решение для Управляемых форм (УФ) через Условное оформление

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

Давайте по шагам разберем, как настроить блокировку ячеек в строке в управляемом интерфейсе:

  1. Откройте управляемую форму в конфигураторе.
  2. В окне свойств формы перейдите на вкладку «Условное оформление» и нажмите кнопку «Добавить».
  3. В появившемся окне настройки выполните следующие шаги:
    1. Вкладка «Оформление»: найдите свойство ТолькоПросмотр (или Доступность) и установите для него значение Истина (или Ложь соответственно).
    2. Вкладка «Условие»: добавьте новое условие. Например: Объект.ИмяВашейТабличнойЧасти.ФлажокБлокировки Равно Истина.
    3. Вкладка «Оформляемые поля»: выберите те колонки вашей таблицы, которые должны стать недоступными для редактирования при выполнении указанного условия.

На этом всё! Платформа самостоятельно оптимизирует этот процесс на уровне ядра. Вам не придется писать ни одной строки кода, а механизм будет работать максимально быстро, стабильно и без ошибок при прокрутке.

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

← На главную