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