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