Как преобразовать элемент справочника в группу в 1С

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

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

Главная сложность этой задачи заключается в том, что системный реквизит ЭтоГруппа (в SQL-версии — IsFolder) доступен только для чтения после того, как объект был впервые записан в базу данных. Платформа 1С строго блокирует попытки прямой перезаписи этого свойства (код вида Объект.ЭтоГруппа = Истина вызовет критическую ошибку выполнения). Однако решить эту проблему можно. Разберем подробно четыре проверенных способа решения этой задачи — от самых безопасных и чистых до экстремальных.

Способ 1. Программная подмена объекта через GUID (рекомендуемый метод)

Этот способ является наиболее чистым, безопасным и корректным с точки зрения ссылочной целостности базы данных 1С. Суть метода заключается в том, чтобы запомнить уникальный идентификатор (GUID) ошибочного элемента, полностью удалить его из базы данных без проверки ссылок и сразу же создать на его месте полноценную группу с тем же самым GUID.

Поскольку все документы, регистры и другие справочники ссылаются на объекты базы данных именно по их уникальному идентификатору, новая группа мгновенно займет место старого элемента во всех связях. Ни одна ссылка в базе данных не станет «битой».

Рассмотрим по шагам алгоритм реализации этого метода:

  1. Сначала мы находим проблемный элемент справочника и получаем его ссылку.
  2. Извлекаем уникальный идентификатор (GUID) этого элемента.
  3. Считываем и временно сохраняем в переменные все важные реквизиты, которые должны быть у новой группы (Наименование, Код, Родитель).
  4. Удаляем исходный элемент из базы данных непосредственно. Важно использовать именно метод Удалить(), а не помечать объект на удаление. Чтобы обойти возможные блокировки со стороны бизнес-логики, рекомендуется использовать свойство ОбменДанными.Загрузка = Истина.
  5. Создаем новый объект группы с помощью метода СоздатьГруппу().
  6. Присваиваем новой группе ранее сохраненный GUID с помощью метода УстановитьСсылкуНового().
  7. Заполняем реквизиты новой группы сохраненными значениями и записываем ее.

Давайте посмотрим на пример программного кода, реализующего этот алгоритм:


// Ссылка на элемент, который ошибочно записан как элемент, но должен стать группой
СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоКоду("00000123");

Если СсылкаНаЭлемент.Пустая() Тогда
    ВызватьИсключение "Элемент не найден в базе данных!";
КонецЕсли;

// 1. Получаем GUID и основные реквизиты
УникальныйИдентификатор = СсылкаНаЭлемент.УникальныйИдентификатор();
СохраненноеНаименование   = СсылкаНаЭлемент.Наименование;
СохраненныйКод           = СсылкаНаЭлемент.Код;
СохраненныйРодитель       = СсылкаНаЭлемент.Родитель;

// 2. Получаем объект для удаления
ОбъектУдаления = СсылкаНаЭлемент.ПолучитьОбъект();
ОбъектУдаления.ОбменДанными.Загрузка = Истина;

Попытка
    // Удаляем объект без контроля ссылочной целостности
    ОбъектУдаления.Удалить();
Исключение
    ЗаписатьЛогСобытий("Не удалось удалить элемент: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

// 3. Создаем новую группу на месте удаленного элемента
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();

// Назначаем группе старый GUID
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылка(УникальныйИдентификатор);
НоваяГруппа.УстановитьСсылкуНового(НоваяСсылка);

// 4. Заполняем реквизиты
НоваяГруппа.Наименование = СохраненноеНаименование;
НоваяГруппа.Код          = СохраненныйКод;
НоваяГруппа.Родитель     = СохраненныйРодитель;
НоваяГруппа.ОбменДанными.Загрузка = Истина;

// 5. Записываем готовую группу
НоваяГруппа.Записать();

Этот способ работает безотказно как в файловом, так и в клиент-серверном варианте работы 1С. Он полностью безопасен, так как задействует только штатные объектные методы платформы.

Способ 2. Обходной путь через изменение конфигурации

Если в базе данных нет активных пользователей, у вас есть монопольный доступ и база находится на поддержке с возможностью изменения (или это собственная разработка), можно применить оригинальный визуальный трюк без написания программного кода.

Давайте разберем этот процесс по шагам:

  1. Открываем базу данных в режиме Конфигуратор.
  2. Находим наш справочник в дереве метаданных и открываем его свойства.
  3. Переходим на вкладку «Иерархия» и временно меняем свойство Вид иерархии с значения Иерархия групп и элементов на значение Иерархия элементов.
  4. Выполняем обновление конфигурации базы данных (клавиша F7). При таком виде иерархии платформа позволяет подчинять любые элементы другим элементам напрямую, стирая жесткую грань между понятиями группы и элемента.
  5. Запускаем базу в режиме «1С:Предприятие». Находим наш проблемный элемент справочника (который должен стать группой).
  6. Создаем любой временный, «фиктивный» элемент в этом же справочнике и в поле «Родитель» принудительно указываем наш проблемный элемент. Записываем фиктивный элемент.
  7. Возвращаемся в Конфигуратор и меняем свойство Вид иерархии обратно на Иерархия групп и элементов.
  8. Запускаем обновление конфигурации базы данных.

При обратной конвертации структуры данных платформа 1С проанализирует существующие связи. Обнаружив, что у нашего проблемного элемента есть подчиненный объект (а в режиме классической иерархии подчинение элемента элементу недопустимо), система автоматически и принудительно преобразует родительский элемент в статус группы.

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

Важное ограничение: Этот способ сработает корректно только в том случае, если у справочника отсутствуют дополнительные реквизиты, имеющие жесткую настройку использования «Только для элементов» или «Только для групп».

Способ 3. Прямая модификация на уровне СУБД (SQL/PostgreSQL)

Для крупных клиент-серверных баз данных под управлением MS SQL Server или PostgreSQL существует возможность мгновенного исправления признака группы напрямую через SQL-запрос. Этот способ требует максимальной осторожности и предварительного создания резервной копии базы данных.

Давайте выясним физическую структуру хранения данных. На уровне таблиц СУБД таблица любого справочника имеет имя вида _ReferenceXXX (где XXX — это порядковый номер таблицы в вашей базе). В этой таблице за признак группы отвечает булево поле _Folder (в некоторых версиях СУБД это бинарное поле). Значение 0 (или 0x00, false) означает элемент, а значение 1 (или 0x01, true) определяет группу.

Для выполнения этой операции выполните следующие действия:

  1. Определите имя физической таблицы справочника в базе данных (это можно сделать с помощью функции платформы ПолучитьСтруктуруХраненияБазыДанных()).
  2. Определите внутренний идентификатор (GUID) элемента в формате SQL. Платформа 1С хранит GUID в поле _IDRRef в бинарном представлении, где байты перевернуты.
  3. Напишите и выполните SQL-запрос обновления. Пример запроса для MS SQL Server:

-- Будьте внимательны: предварительно сделайте резервную копию базы данных!
UPDATE _Reference123
SET _Folder = 0x01
WHERE _IDRRef = 0x80E200155D05070111E39BC725E5AD26

Критические риски и обязательные действия после SQL-апдейта:

  1. Если у справочника настроены реквизиты, предназначенные «Только для элементов», при обращении к новой группе через стандартные формы 1С возникнет критическая ошибка платформы. На уровне базы данных все эти реквизиты у измененной записи должны быть принудительно переведены в состояние NULL.
  2. Прямое изменение данных в обход сервера приложений 1С полностью рассинхронизирует индексы СУБД и внутренний кэш платформы. Это приведет к тому, что в динамических списках объект по-прежнему будет отображаться как элемент, а при попытке войти внутрь него платформа может аварийно завершить работу. После выполнения SQL-запроса обязательно запустите процедуру «Тестирование и исправление» (ТиИ) в Конфигураторе с установленными флагами «Реиндексация таблиц» и «Проверка логической целостности».

Способ 4. Корректировка через выгрузку и загрузку XML

Этот способ гораздо безопаснее прямого вмешательства в таблицы СУБД, поскольку он использует штатные и документированные механизмы платформы 1С, но при этом позволяет обойти ограничение «Только чтение» для реквизита ЭтоГруппа.

Проанализируем этот алгоритм по шагам:

  1. Установите стандартную обработку «Выгрузка и загрузка данных XML» (она входит в состав инструментов разработчика от фирмы 1С).
  2. С помощью этой обработки выгрузите только те элементы справочника, которые необходимо преобразовать в группы, в отдельный XML-файл. Настройте отбор по конкретным кодам или ссылкам, чтобы не выгружать весь справочник.
  3. Откройте полученный XML-файл в любом текстовом редакторе (рекомендуется использовать Notepad++ для работы с большими файлами).
  4. Найдите в структуре файла выгруженные объекты. У каждого элемента будет присутствовать тег <IsFolder>false</IsFolder>.
  5. Замените это значение вручную или с помощью автозамены на <IsFolder>true</IsFolder> для всех ошибочных элементов.
  6. Сохраните изменения в файле.
  7. Вернитесь в программу 1С и откройте обработку «Выгрузка и загрузка данных XML» на вкладке «Загрузка». Загрузите измененный XML-файл обратно в базу.

Почему этот способ работает? При импорте данных через XML-схемы платформа работает в специальном режиме: РежимЗагрузкиДанных = Истина. В этом режиме отключаются практически все проверки бизнес-логики платформы, включая жесткий запрет на модификацию системного признака группы. В результате элемент успешно и безопасно перезаписывается как полноценная группа.

Резюме и рекомендации

Мы подробно рассмотрели четыре различных подхода к решению проблемы. Для быстрого и безопасного исправления единичных ошибок в рабочей базе настоятельно рекомендуется использовать Способ 1 (программная подмена GUID). Он легко оформляется в виде небольшой внешней обработки, не требует монопольного доступа к базе данных и гарантирует 100% сохранение всех ссылок в документах и регистрах без риска повредить физическую структуру таблиц СУБД.

← На главную