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