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

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

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

Понимание типов данных: почему «Строка» — это тупик

Первое, что мы должны проанализировать, — это разница между строковым представлением и ссылкой. Если вы просто копируете Наименование одного элемента в Наименование другого, система воспринимает это как обычный текст. Программа «не знает», что этот текст как-то связан с другим объектом. Чтобы кнопка «Открыть» заработала, реквизит в справочнике-приемнике должен иметь тип СправочникСсылка.

Важно: в 1С невозможно изменить тип существующего реквизита программно в режиме «Предприятие». Все изменения типов производятся исключительно в «Конфигураторе». Если ваш реквизит уже определен как «Строка», запись в него ссылки приведет лишь к тому, что 1С преобразует ссылку в текст названия, и обратная навигация будет невозможна.

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

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

Алгоритм действий следующий:

  1. В Конфигураторе откройте справочник СистемыИзмерения.
  2. Добавьте новый реквизит, назовем его, например, ОбъектОснование.
  3. Установите для него тип СправочникСсылка.ОсновныеСредства.
  4. Вынесите этот реквизит на форму справочника.

Теперь проанализируем программный код, который выполнит создание элемента и установку связи:


// Предположим, у нас есть ссылка на элемент справочника ОсновныеСредства в переменной СсылкаОС
НовыйЭлемент = Справочники.СистемыИзмерения.СоздатьЭлемент();

// Заполняем стандартное наименование текстом из источника
НовыйЭлемент.Наименование = СсылкаОС.Наименование;

// Устанавливаем связь через созданный нами реквизит
// Здесь важно передавать именно Ссылку, а не сам объект или его название
НовыйЭлемент.ОбъектОснование = СсылкаОС;

// Записываем новый элемент в базу данных
НовыйЭлемент.Записать();

Способ 2: Использование механизма подчинения

Если логика вашей задачи подразумевает связь «Один ко многим» (например, у одного Основного Средства может быть несколько систем измерения), рассмотрим вариант подчинения справочников. В этом случае в справочнике СистемыИзмерения на уровне метаданных устанавливается Владелец — справочник ОсновныеСредства.

В коде это будет выглядеть так:


НовыйЭлемент = Справочники.СистемыИзмерения.СоздатьЭлемент();
НовыйЭлемент.Наименование = СсылкаОС.Наименование;
// Используем стандартный реквизит Владелец
НовыйЭлемент.Владелец = СсылкаОС;
НовыйЭлемент.Записать();

Проблема дублей и проверка на существование

Просто создавать элементы в цикле — плохая практика, так как при повторном запуске обработки вы получите сотни одинаковых записей. Выясним, как проверить, был ли элемент перенесен ранее. Самый простой способ — поиск по наименованию или по значению нашего ссылочного реквизита.

Проанализируем пример с проверкой:


// Ищем, нет ли уже в справочнике элемента, связанного с этим ОС
НайденнаяСсылка = Справочники.СистемыИзмерения.НайтиПоРеквизиту("ОбъектОснование", СсылкаОС);

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

ОбъектПриемник.Наименование = СсылкаОС.Наименование;
ОбъектПриемник.ОбъектОснование = СсылкаОС;
ОбъектПриемник.Записать();

Продвинутая техника: Уникальные идентификаторы (GUID)

Если вы хотите обеспечить максимально надежную связь, которая не разорвется даже при изменении наименования в справочнике-источнике, рекомендуется использовать уникальные идентификаторы. Каждая запись в 1С имеет свой UUID.

Вы можете получить его так: СсылкаОС.УникальныйИдентификатор(). Это значение можно сохранить в строковом реквизите справочника-приемника. Однако, если вы используете тип СправочникСсылка, 1С уже хранит этот идентификатор «под капотом», поэтому дополнительно сохранять GUID строкой обычно требуется только при обмене данными с внешними системами.

Оптимизация массового переноса

Если в вашем справочнике ОсновныеСредства тысячи элементов, использование метода Выбрать() и создание объектов в цикле будет работать медленно. В таких случаях мы рекомендуем использовать Запрос для получения данных и метод ОбменДанными.Загрузка = Истина для ускорения записи.

Рассмотрим пример оптимизированного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ОсновныеСредства.Ссылка КАК Ссылка,
    |   ОсновныеСредства.Наименование КАК Наименование
    |ИЗ
    |   Справочник.ОсновныеСредства КАК ОсновныеСредства";

РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

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

Резюме

Для реализации корректного переноса с возможностью открытия первоисточника необходимо:

  1. Типизировать данные: Реквизит в приемнике должен иметь ссылочный тип (СправочникСсылка).
  2. Использовать объектную модель: Работать через СоздатьЭлемент() или ПолучитьОбъект().
  3. Следить за ссылками: Присваивать в реквизит именно свойство .Ссылка объекта-источника.
  4. Контролировать дублирование: Всегда проверять наличие записи перед созданием новой.

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

← На главную