В практике администрирования и разработки на платформе 1С:Предприятие нередко возникает неприятная ситуация: в результате некорректно настроенного обмена данными (например, через правила «Конвертации данных 2», где забыли указать поиск по группе) иерархический справочник переносится неправильно. В итоге элементы, которые в базе-источнике являлись группами, в базе-приемнике записываются как обычные элементы. При этом на них уже могут ссылаться другие объекты базы данных как на родителей, что делает невозможным их простое удаление интерактивными средствами.
Главная сложность этой задачи заключается в том, что системный реквизит ЭтоГруппа (в SQL-версии — IsFolder) доступен только для чтения после того, как объект был впервые записан в базу данных. Платформа 1С строго блокирует попытки прямой перезаписи этого свойства (код вида Объект.ЭтоГруппа = Истина вызовет критическую ошибку выполнения). Однако решить эту проблему можно. Разберем подробно четыре проверенных способа решения этой задачи — от самых безопасных и чистых до экстремальных.
Этот способ является наиболее чистым, безопасным и корректным с точки зрения ссылочной целостности базы данных 1С. Суть метода заключается в том, чтобы запомнить уникальный идентификатор (GUID) ошибочного элемента, полностью удалить его из базы данных без проверки ссылок и сразу же создать на его месте полноценную группу с тем же самым GUID.
Поскольку все документы, регистры и другие справочники ссылаются на объекты базы данных именно по их уникальному идентификатору, новая группа мгновенно займет место старого элемента во всех связях. Ни одна ссылка в базе данных не станет «битой».
Рассмотрим по шагам алгоритм реализации этого метода:
Удалить(), а не помечать объект на удаление. Чтобы обойти возможные блокировки со стороны бизнес-логики, рекомендуется использовать свойство ОбменДанными.Загрузка = Истина.СоздатьГруппу().УстановитьСсылкуНового().Давайте посмотрим на пример программного кода, реализующего этот алгоритм:
// Ссылка на элемент, который ошибочно записан как элемент, но должен стать группой
СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоКоду("00000123");
Если СсылкаНаЭлемент.Пустая() Тогда
ВызватьИсключение "Элемент не найден в базе данных!";
КонецЕсли;
// 1. Получаем GUID и основные реквизиты
УникальныйИдентификатор = СсылкаНаЭлемент.УникальныйИдентификатор();
СохраненноеНаименование = СсылкаНаЭлемент.Наименование;
СохраненныйКод = СсылкаНаЭлемент.Код;
СохраненныйРодитель = СсылкаНаЭлемент.Родитель;
// 2. Получаем объект для удаления
ОбъектУдаления = СсылкаНаЭлемент.ПолучитьОбъект();
ОбъектУдаления.ОбменДанными.Загрузка = Истина;
Попытка
// Удаляем объект без контроля ссылочной целостности
ОбъектУдаления.Удалить();
Исключение
ЗаписатьЛогСобытий("Не удалось удалить элемент: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 3. Создаем новую группу на месте удаленного элемента
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
// Назначаем группе старый GUID
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылка(УникальныйИдентификатор);
НоваяГруппа.УстановитьСсылкуНового(НоваяСсылка);
// 4. Заполняем реквизиты
НоваяГруппа.Наименование = СохраненноеНаименование;
НоваяГруппа.Код = СохраненныйКод;
НоваяГруппа.Родитель = СохраненныйРодитель;
НоваяГруппа.ОбменДанными.Загрузка = Истина;
// 5. Записываем готовую группу
НоваяГруппа.Записать();
Этот способ работает безотказно как в файловом, так и в клиент-серверном варианте работы 1С. Он полностью безопасен, так как задействует только штатные объектные методы платформы.
Если в базе данных нет активных пользователей, у вас есть монопольный доступ и база находится на поддержке с возможностью изменения (или это собственная разработка), можно применить оригинальный визуальный трюк без написания программного кода.
Давайте разберем этот процесс по шагам:
Иерархия групп и элементов на значение Иерархия элементов.Иерархия групп и элементов.При обратной конвертации структуры данных платформа 1С проанализирует существующие связи. Обнаружив, что у нашего проблемного элемента есть подчиненный объект (а в режиме классической иерархии подчинение элемента элементу недопустимо), система автоматически и принудительно преобразует родительский элемент в статус группы.
После завершения обновления вам останется лишь зайти в режим «1С:Предприятие» и удалить созданный ранее временный («фиктивный») элемент.
Важное ограничение: Этот способ сработает корректно только в том случае, если у справочника отсутствуют дополнительные реквизиты, имеющие жесткую настройку использования «Только для элементов» или «Только для групп».
Для крупных клиент-серверных баз данных под управлением MS SQL Server или PostgreSQL существует возможность мгновенного исправления признака группы напрямую через SQL-запрос. Этот способ требует максимальной осторожности и предварительного создания резервной копии базы данных.
Давайте выясним физическую структуру хранения данных. На уровне таблиц СУБД таблица любого справочника имеет имя вида _ReferenceXXX (где XXX — это порядковый номер таблицы в вашей базе). В этой таблице за признак группы отвечает булево поле _Folder (в некоторых версиях СУБД это бинарное поле). Значение 0 (или 0x00, false) означает элемент, а значение 1 (или 0x01, true) определяет группу.
Для выполнения этой операции выполните следующие действия:
ПолучитьСтруктуруХраненияБазыДанных())._IDRRef в бинарном представлении, где байты перевернуты.
-- Будьте внимательны: предварительно сделайте резервную копию базы данных!
UPDATE _Reference123
SET _Folder = 0x01
WHERE _IDRRef = 0x80E200155D05070111E39BC725E5AD26
Критические риски и обязательные действия после SQL-апдейта:
NULL.Этот способ гораздо безопаснее прямого вмешательства в таблицы СУБД, поскольку он использует штатные и документированные механизмы платформы 1С, но при этом позволяет обойти ограничение «Только чтение» для реквизита ЭтоГруппа.
Проанализируем этот алгоритм по шагам:
<IsFolder>false</IsFolder>.<IsFolder>true</IsFolder> для всех ошибочных элементов.Почему этот способ работает? При импорте данных через XML-схемы платформа работает в специальном режиме: РежимЗагрузкиДанных = Истина. В этом режиме отключаются практически все проверки бизнес-логики платформы, включая жесткий запрет на модификацию системного признака группы. В результате элемент успешно и безопасно перезаписывается как полноценная группа.
Мы подробно рассмотрели четыре различных подхода к решению проблемы. Для быстрого и безопасного исправления единичных ошибок в рабочей базе настоятельно рекомендуется использовать Способ 1 (программная подмена GUID). Он легко оформляется в виде небольшой внешней обработки, не требует монопольного доступа к базе данных и гарантирует 100% сохранение всех ссылок в документах и регистрах без риска повредить физическую структуру таблиц СУБД.