Как исправить ошибку «Поле объекта недоступно для записи (Ссылка)» в 1С?

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

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

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

Причина возникновения ошибки

Проанализируем ситуацию на примере вызова функции, в которую передается параметр:


Функция АрендаАТ(Сотрудник1)
    ...
    Если ЕстьПодмена = 1 Тогда
        Сотрудник1 = СотрудникПодмена; // Здесь возникает ошибка
    КонецЕсли;
КонецФункции

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

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

Способ 1. Использование ключевого слова Знач

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

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

Посмотрим на пример правильного объявления функции:


Функция АрендаАТ(Знач Сотрудник1)
    // Код поиска подмены
    ...
    Если ЕстьПодмена = 1 Тогда
        Сотрудник1 = СотрудникПодмена;
    КонецЕсли;
    
    Возврат Сотрудник1;
КонецФункции

Способ 2. Корректный возврат значения через оператор Возврат

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

Перепишем алгоритм по правилам платформы:


Функция ПолучитьПодменяющегоСотрудника(Знач ИсходныйСотрудник)
    
    РезультатСотрудник = ИсходныйСотрудник;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	СоответствиеСотрудников.СотрудникПодмена КАК СотрудникПодмена
        |ИЗ
        |	РегистрСведений.СоответствиеСотрудников КАК СоответствиеСотрудников
        |ГДЕ
        |	СоответствиеСотрудников.Сотрудник = &Сотрудник";
        
    Запрос.УстановитьПараметр("Сотрудник", ИсходныйСотрудник);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        РезультатСотрудник = Выборка.СотрудникПодмена;
    КонецЕсли;
    
    Возврат РезультатСотрудник;
    
КонецФункции

При вызове такой функции полученный результат присваивается локальной переменной в вызывающем коде:

ТекущийСотрудник = ПолучитьПодменяющегоСотрудника(Ссылка.Сотрудник1);

Способ 3. Оптимизация получения данных из регистра сведений

Посмотрим на работу с регистром сведений. Если регистр сведений является непериодическим, создание и выполнение объекта Новый Запрос при каждом вызове функции существенно снижает производительность системы (особенно если обработка выполняется в цикле по списку сотрудников).

Для оптимизации вызова вместо запроса выгодно использовать встроенный метод менеджера регистра Получить():


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

Методологические рекомендации при работе с сотрудниками в «1С:ЗУП»

Разберем методологическую сторону подмены сотрудников. В конфигурации «Зарплата и Управление Персоналом» прямая подмена сотрудников в печатных формах и отчетах может привести к нарушениям регламентированного учета.

  1. Оформление выплаты заработной платы родственникам: Согласно ст. 136 ТК РФ, перечисление заработной платы третьему лицу (включая супругов) осуществляется на основании письменного заявления работника и доверенности или дополнительного соглашения.
  2. Сохранение учета в программе: В кадровом и налоговом учете (НДФЛ, страховые взносы, отчетность в СФР) сотрудником должен оставаться тот, на кого оформлен трудовой договор. Меняются только платежные реквизиты или получатель при оформлении выплатных документов.
← На главную