Как исправить ошибку «Поле объекта недоступно для записи» при изменении реквизита управляемой формы из команды?

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

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

В процессе реализации этой задачи могут возникнуть две серьезные проблемы:

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

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

Причина №1: Путаница между элементами формы и реквизитами данных

Проанализируем исходный код, который вызвал ошибку у автора темы:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    ТекДог = ПараметрКоманды;
    СвДог = УстСвойствоНаСервере("Свойство_Договор партнера (Договоры с контрагентами)");
    
    Список = ПараметрыВыполненияКоманды.Источник.Свойства_ОписаниеДополнительныхРеквизитов;
    НайденныеСтроки = Список.НайтиСтроки(Новый Структура("Свойство", СвДог));
    Если НайденныеСтроки.Количество() > 0 Тогда
        ИмяДопРеквНаФорме = НайденныеСтроки[0].ИмяРеквизитаЗначение;
        Форма = ПараметрыВыполненияКоманды.Источник;
        Форма.элементы[ИмяДопРеквНаФорме] = ТекДог; // Ошибка тут!
    КонецЕсли;
КонецПроцедуры

Выясним причину падения платформы на строке Форма.элементы[ИмяДопРеквНаФорме] = ТекДог;. Здесь разработчик пытается записать значение напрямую в коллекцию элементов формы.

В управляемом интерфейсе 1С действует жесткое разделение на Данные (Реквизиты) и Отображение (Элементы):

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

Правильное решение: записывать значение необходимо непосредственно в реквизит формы, используя контекст формы-источника:


// Вместо Форма.Элементы[ИмяДопРеквНаФорме] = ТекДог;
Форма[ИмяДопРеквНаФорме] = ТекДог;

Причина №2: Влияние свойства команды «Изменяет сохраняемые данные»

После исправления первой ошибки разработчики часто сталкиваются со второй проблемой: код отрабатывает без ошибок, отладчик показывает, что значение в Форма[ИмяДопРеквНаФорме] успешно записалось, однако на экране пользователя поле ввода остается абсолютно пустым.

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

Когда этот флаг установлен в свойствах команды в конфигураторе, платформа «1С:Предприятие» запускает следующий автоматический жизненный цикл при ее выполнении:

  1. Блокировка объекта: Платформа пытается наложить пессимистическую блокировку на объект в базе данных, чтобы избежать конфликтов редактирования.
  2. Выполнение кода: Отрабатывает ваш алгоритм заполнения реквизитов.
  3. Принудительное перечитывание (сброс): Поскольку платформа считает, что команда «изменила данные» (подразумевается, что она изменила их в базе данных на сервере), сразу после завершения выполнения команды платформа выполняет автоматическое обновление формы — перечитывает данные объекта из БД.

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

Как правильно спроектировать решение задачи?

В зависимости от бизнес-логики вашей задачи, существует два архитектурно верных варианта реализации.

Вариант А. Изменение реквизитов на форме «на лету» (без немедленной записи в БД)

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

Пошаговый алгоритм реализации:

  1. Откройте свойства вашей команды в конфигураторе и снимите флаг «Изменяет сохраняемые данные».
  2. В коде команды измените реквизит формы.
  3. Принудительно установите флаг модифицированности формы, чтобы система знала, что данные были изменены пользователем программно, и предложила сохранить их при закрытии окна.

Рассмотрим пример готового кода для этого варианта:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    ТекДог = ПараметрКоманды;
    Форма = ПараметрыВыполненияКоманды.Источник;
    
    // Получаем описание доп. реквизитов с сервера
    СвДог = ПолучитьСвойствоНаСервере(); 
    Список = Форма.Свойства_ОписаниеДополнительныхРеквизитов;
    НайденныеСтроки = Список.НайтиСтроки(Новый Структура("Свойство", СвДог));
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        ИмяДопРеквНаФорме = НайденныеСтроки[0].ИмяРеквизитаЗначение;
        
        // Записываем данные в реквизит формы напрямую
        Форма[ИмяДопРеквНаФорме] = ТекДог;
        
        // Сообщаем форме, что данные изменены интерактивно
        Форма.Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

Вариант Б. Изменение данных напрямую в базе данных (с автообновлением формы)

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

Пошаговый алгоритм реализации:

  1. Флаг «Изменяет сохраняемые данные» в свойствах команды должен быть включен.
  2. Вся логика изменения переносится на сервер. Мы должны получить объект базы данных через метод ПолучитьОбъект(), внести изменения в его табличную часть дополнительных реквизитов (механизмы БСП) и вызвать метод Записать().
  3. Платформа, завершив выполнение серверного кода команды, сама перечитает измененный объект из базы данных, и новые значения красиво отобразятся в интерфейсе без дополнительных манипуляций.

Резюме

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

← На главную