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