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