Как восстановить предопределенный элемент справочника, если он исчез или задублировался в 1С:Бухгалтерия?

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

В этой статье мы подробно разберем ситуацию, с которой сталкиваются пользователи и администраторы конфигурации "1С:Бухгалтерия предприятия" (редакция 3.0). Проблема проявляется следующим образом: в карточке организации перестает сохраняться поле E-mail (или другие виды контактной информации). Значение вводится, но после записи и повторного открытия поле оказывается пустым. При этом в справочнике "Виды контактной информации" нужный элемент может отсутствовать визуально, но существовать в конфигураторе.

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

Симптомы и причины проблемы

Чаще всего проблема обнаруживается случайно: пользователи жалуются, что не могут сохранить адрес электронной почты. При техническом анализе выясняется следующее:

  1. В пользовательском режиме в справочнике ВидыКонтактнойИнформации отсутствует элемент "Email".
  2. В Конфигураторе этот элемент является предопределенным и присутствует.
  3. Попытка создать такой элемент вручную приводит к появлению дублей на форме (два поля Email), но проблема сохранения не решается.
  4. Тестирование и исправление (ТиИ) не помогает, а иногда и усугубляет ситуацию, создавая битые ссылки «Объект не найден».

Основная причина: На версиях платформы 8.3.24 (особенно ранних сборках) была зафиксирована ошибка, возникающая после реструктуризации или ТиИ при наличии расширений. В результате теряется связь между предопределенным элементом в метаданных (конфигурации) и реальной записью в таблице базы данных. Поле ИмяПредопределенныхДанных у существующего элемента может "слететь" или элемент может быть помечен как непредопределенный, хотя его имя занято.

Диагностика ситуации

Прежде чем приступать к лечению, давайте убедимся, что мы имеем дело именно с потерей связи предопределенного элемента. Для этого воспользуемся консолью запросов или внешней обработкой. Нам нужно посмотреть, есть ли в базе элементы, которые "держат" системное имя, но не видны или испорчены.

Выполним следующий запрос:


ВЫБРАТЬ
    ВидыКИ.Ссылка,
    ВидыКИ.Наименование,
    ВидыКИ.ПометкаУдаления,
    ВидыКИ.Предопределенный,
    ВидыКИ.ИмяПредопределенныхДанных
ИЗ
    Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
ГДЕ
    ВидыКИ.ИмяПредопределенныхДанных ПОДОБНО "%Email%"

Если запрос вернет запись, обратите внимание на колонку Предопределенный. Если там стоит Ложь, но поле ИмяПредопределенныхДанных заполнено — это и есть наш "виновник". Система не дает создать новый правильный элемент или привязать существующий, так как имя уже занято.

Способ 1: Программное восстановление (Рекомендуемый)

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

Многие пытаются просто присвоить имя нужному элементу и получают ошибку: "Предопределенный элемент не уникален". Это происходит именно потому, что где-то в базе (возможно, среди удаленных) есть дубль, требующий чистки и восстановления целостности.

Давайте напишем алгоритм исправления. Этот код можно выполнить в обработке "Групповое изменение реквизитов" (в режиме "Выполнить произвольный алгоритм") или в простейшей внешней обработке.

Шаг 1. Освобождаем имя (если мешает помеченный объект, предварительно выполните удаление помеченных объектов с отбором)


// Ищем элемент, который сейчас занимает нужное имя
// В БП 3.0 для Email организации имя обычно "EmailОрганизации"
ИскомоеИмя = "EmailОрганизации"; 

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВидыКИ.Ссылка
    |ИЗ
    |	Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
    |ГДЕ
    |	ВидыКИ.ИмяПредопределенныхДанных = &Имя";

Запрос.УстановитьПараметр("Имя", ИскомоеИмя);
Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда
    // Получаем объект, чтобы изменить его
    БлокирующийЭлемент = Выборка.Ссылка.ПолучитьОбъект();
    
    // Очищаем имя, освобождая его для правильного элемента
    БлокирующийЭлемент.ИмяПредопределенныхДанных = "";
    
    // Пытаемся записать. Если элемент помечен на удаление или испорчен,
    // запись может пройти успешно, освободив имя.
    Попытка
        БлокирующийЭлемент.Записать();
        Сообщить("Имя освобождено у элемента: " + БлокирующийЭлемент.Наименование);
    Исключение
        Сообщить("Не удалось очистить имя: " + ОписаниеОшибки());
    КонецПопытки;
Иначе
    Сообщить("Элемент с таким именем предопределенных данных не найден. Можно создавать новый.");
КонецЕсли;

Шаг 2. Назначаем имя правильному элементу

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


// Находим элемент, который должен стать предопределенным
// Лучше искать по наименованию или создать новый
ИскомоеИмя = "EmailОрганизации"; 
НашеНазвание = "Email"; // Как он называется у вас в базе

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	ВидыКИ.Ссылка
    |ИЗ
    |	Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
    |ГДЕ
    |	ВидыКИ.Наименование = &Название
    |	И ВидыКИ.ИмяПредопределенныхДанных = """""; // Ищем тот, который еще не привязан

Запрос.УстановитьПараметр("Название", НашеНазвание);
Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда
    ПравильныйЭлемент = Выборка.Ссылка.ПолучитьОбъект();
    ПравильныйЭлемент.ИмяПредопределенныхДанных = ИскомоеИмя;
    
    Попытка
        ПравильныйЭлемент.Записать();
        Сообщить("Связь восстановлена успешно!");
    Исключение
        Сообщить("Ошибка при связывании: " + ОписаниеОшибки());
    КонецПопытки;
Иначе
    // Если элемента нет, создаем новый
    НовыйЭлемент = Справочники.ВидыКонтактнойИнформации.СоздатьЭлемент();
    НовыйЭлемент.Наименование = НашеНазвание;
    // Заполните остальные обязательные реквизиты (Тип, Вид и т.д.) согласно логике БП
    НовыйЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
    НовыйЭлемент.ВидОбъектаКонтактнойИнформации = Перечисления.ВидыОбъектовКонтактнойИнформации.Организации; // Пример
    НовыйЭлемент.ИмяПредопределенныхДанных = ИскомоеИмя;
    
    Попытка
        НовыйЭлемент.Записать();
        Сообщить("Создан новый предопределенный элемент.");
    Исключение
        Сообщить("Ошибка создания: " + ОписаниеОшибки());
    КонецПопытки;
КонецЕсли;

Способ 2: Восстановление через XML (Сложный)

Если программный метод вызывает затруднения или база сильно повреждена, можно воспользоваться методом прямой подмены данных через XML, как это сделал автор темы. Этот метод требует наличия резервной копии или "здоровой" базы с аналогичной конфигурацией.

Разберем алгоритм действий:

  1. Откройте "здоровую" базу (или демо-базу той же версии).
  2. Воспользуйтесь стандартной обработкой "Выгрузка и загрузка данных XML".
  3. Выгрузите справочник ВидыКонтактнойИнформации в файл.
  4. Выгрузите тот же справочник из вашей "больной" базы.
  5. Откройте оба файла в текстовом редакторе (например, Notepad++).
  6. В файле из "больной" базы найдите элемент, который соответствует Email, но имеет неправильные ссылки или отсутствует связь.
  7. Сравните его идентификаторы (Ref) и свойство PredefinedDataName с файлом из "здоровой" базы.
  8. Скорректируйте файл "здоровой" выгрузки так, чтобы Ref (Уникальный Идентификатор) совпадал с тем элементом, который реально используется у вас в регистрах сведений (где хранятся сами e-mail адреса), но добавьте ему правильное PredefinedDataName.
  9. Загрузите исправленный файл обратно в "больную" базу через ту же обработку.

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

Способ 3: Запуск обновления ИБ

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

Для принудительного запуска процедур начального заполнения можно запустить 1С с ключом запуска:

/C ЗапуститьОбновлениеИнформационнойБазы

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

Рекомендации по предотвращению

Исходя из опыта обсуждения проблемы, основной причиной является ошибка платформы 8.3.24 при проведении "Тестирования и исправления" на базах с расширениями. Чтобы избежать повторения ситуации:

← На главную