Замена ссылок на объекты справочников и документов
Содержание
Ссылку уже записанного объекта в 1С напрямую отредактировать нельзя. Ссылка жёстко связана с внутренним идентификатором (GUID), который присваивается один раз при первой записи элемента справочника или документа и дальше не меняется.
Поэтому за фразой «изменить ссылку объекта» почти всегда стоит одна из трёх задач: заменить ссылки на один объект ссылками на другой (слияние дублей), сохранить или перенести идентификатор при обмене и миграции базы, либо создать объект с заранее заданным GUID. Ниже разберём каждый случай — от безопасного типового инструмента до кода обработки — и как всё откатить, если пошло не так.
УстановитьСсылкуНового. Смотрите раздел с кодом.Что такое ссылка объекта и почему её не переписать
В 1С каждый элемент справочника, документ, элемент плана видов характеристик и прочий ссылочный объект хранится в таблице базы под уникальным идентификатором. Этот идентификатор — тип УникальныйИдентификатор, то же самое, что GUID: 32 шестнадцатеричные цифры вида a1b2c3d4-....
Ссылка (СправочникСсылка.Контрагенты, ДокументСсылка.РеализацияТоваровУслуг и т. п.) — это и есть указатель на строку по её идентификатору. Когда в реквизите другого объекта, в движении документа или в регистре записана ссылка, физически там лежит именно этот GUID.
Отсюда два следствия, которые определяют всё дальнейшее:
- 🔒 Идентификатор объекту присваивается при первой записи и после этого неизменен. Кнопки «поменять ссылку» в режиме 1С:Предприятие нет и быть не может.
- 🔗 Ссылки хранятся в сотнях мест: реквизиты других справочников и документов, табличные части, движения по регистрам, значения в периодических сведениях. Переставить ссылку «в одном месте» обычно бессмысленно.
Когда говорят «изменить ссылку», на деле меняют не сам объект, а то, что на него ссылается. Либо все указатели на объект А переводят на объект Б, либо создают новый объект с нужным GUID, а старый убирают.
Замена ссылок типовым инструментом без кода
Самый частый сценарий — завелись два одинаковых контрагента, две одинаковые номенклатуры, и часть документов оформлена на один элемент, часть на другой. Нужно оставить один, а ссылки со второго перевести на первый.
Для этого в типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11 и др.) есть обработка «Поиск и удаление дублей». Она сама находит все места использования лишнего элемента, переставляет ссылки на оставленный и помечает дубль на удаление.
Как её открыть:
- Включите команду
Главное меню → Сервис → Параметры → Отображать команду «Все функции»(если ещё не включена). - Откройте
Главное меню → Все функции → Стандартные → Поиск и удаление дублей. В ряде конфигураций она же вынесена в разделАдминистрированиеилиНСИ. - Выберите область поиска (например, справочник «Контрагенты»), задайте правила сравнения и запустите поиск.
- В найденных группах укажите, какой элемент оставить (
Оставить), какие считать дублями, и нажмите удаление.
На шаге удаления программа как раз и переставляет ссылки: во всех документах и регистрах, где фигурировал дубль, подставляется оставленный элемент.
Если нужно заменить не дубли, а любое значение на другое (например, везде поменять одну организацию на другую), подойдёт универсальная внешняя обработка «Поиск и замена значений» с диска ИТС. Она ищет конкретную ссылку по всей базе и меняет её на указанную. Открывается через Файл → Открыть (нужны права на открытие внешних обработок) либо подключается в список дополнительных обработок.
Перед заменой ссылок сделайте резервную копию базы. Операция затрагивает движения документов и не имеет кнопки «отменить». Выполняйте её в нерабочее время: при обработке больших справочников возможны длительные блокировки, из-за которых у пользователей начнут «зависать» операции.
Ссылки при обмене данными и переносе базы
При переносе базы поведение ссылок зависит от способа переноса.
Выгрузка и загрузка .dt (Конфигуратор → Администрирование → Выгрузить/Загрузить информационную базу) — это полная копия базы байт в байт. Все идентификаторы сохраняются, ссылки остаются валидными. Этот способ ссылки не меняет вообще.
Распределённая база (РИБ) — узлы обмениваются объектами вместе с их идентификаторами, поэтому один и тот же контрагент в центральной базе и в филиале имеет одинаковый GUID. Ссылки между узлами совпадают автоматически.
Обмен через правила конвертации (КД 2.0/3.0, формат EnterpriseData) — другое дело. Здесь объекты в базе-приёмнике ищутся не по GUID, а по полям поиска из правил (ИНН, код, наименование). Если поля сопоставления заданы неточно, получаются либо дубли, либо «склейка» разных объектов в один. «Побитые ссылки» после обмена — это почти всегда ошибка в правилах сопоставления, а не в самих ссылках.
Что с этим делать:
- Проверьте в правилах конвертации, по каким полям сопоставляются объекты, и совпадают ли они в источнике и приёмнике.
- Уже появившиеся дубли уберите через «Поиск и удаление дублей» (раздел выше).
- Если нужно, чтобы объект в приёмнике получил конкретный идентификатор из источника, это задаётся программно до записи — смотрите следующий раздел.
Как найти все места, где используется ссылка
Прежде чем что-то менять, полезно увидеть полную картину: где именно фигурирует ссылка. Для этого есть глобальная функция НайтиПоСсылкам.
СтарыйКонтрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Старое");
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СтарыйКонтрагент);
ТаблицаИспользования = НайтиПоСсылкам(МассивСсылок);
Для Каждого Строка Из ТаблицаИспользования Цикл
// в колонке Ссылка — объект, который использует искомую ссылку
Сообщить(Строка(Строка.Ссылка));
КонецЦикла;
Функция возвращает таблицу значений с перечнем объектов, которые ссылаются на переданные ссылки. В колонке Ссылка — объект-источник (документ, элемент справочника), который содержит ссылку на искомый объект.
Это удобно и как диагностика перед удалением: если таблица пустая, объект нигде не используется и его безопасно помечать на удаление.
Для анализа «вширь» — сколько документов за период, какие суммы — используют запрос. Конструктор запросов (кнопка в контекстном меню модуля или в консоли запросов) помогает собрать выборку: например, все документы реализации, где указан данный контрагент. Запросом ссылку не изменить — язык запросов только читает данные, — но он незаменим, чтобы оценить масштаб и отобрать объекты для обработки.
НайтиПоСсылкам показывает прямые ссылки на объект. Косвенные связи (например, через подчинённый справочник) она не раскручивает — для сложной иерархии проходите по уровням.
Замена ссылок в коде обработки
Когда типовой инструмент не подходит (нетиповая конфигурация, своя логика отбора), замену делают обработкой. Общий алгоритм:
- Собрать массив старых ссылок, которые нужно заменить.
- Найти объекты-потребители через
НайтиПоСсылкам. - Для каждого объекта получить его
ПолучитьОбъект(), заменить значение реквизита или строки табличной части и записать. - Перепровести документы, у которых поменялись реквизиты, влияющие на движения.
Ручная замена реквизит за реквизитом хрупкая: легко пропустить табличную часть или реквизит движения, и база останется в несогласованном виде. Поэтому в конфигурациях на БСП замену лучше вызывать через механизм подсистемы «Поиск и удаление дублей» — он уже знает все места использования и корректно перепроводит документы. Самописный перебор оправдан только для простых случаев с заранее известным набором реквизитов.
При записи объектов в цикле замены ставьте флаг обмена, чтобы не плодить лишние проведения и не запускать бизнес-логику повторно без необходимости:
Объект = Строка.Ссылка.ПолучитьОбъект();
Объект.Контрагент = НовыйКонтрагент;
Объект.ОбменДанными.Загрузка = Истина; // отключить лишние проверки при записи
Объект.Записать();
Флаг ОбменДанными.Загрузка = Истина отключает проверки заполнения и часть бизнес-логики. Ставьте его осознанно и только там, где уверены, что проверки не нужны: иначе в базу попадут некорректно заполненные документы.
Отдельный случай — создать объект с заранее нужным идентификатором. Изменить GUID существующего объекта нельзя, но у нового, ещё не записанного, ссылку можно задать явно:
Ид = Новый УникальныйИдентификатор("a1b2c3d4-e5f6-4789-0abc-def012345678");
НужнаяСсылка = Справочники.Контрагенты.ПолучитьСсылку(Ид);
Объект = Справочники.Контрагенты.СоздатьЭлемент();
Объект.УстановитьСсылкуНового(НужнаяСсылка);
Объект.Наименование = "ООО Новое";
Объект.Записать();
Метод ПолучитьСсылку(Идентификатор) возвращает ссылку с заданным GUID, даже если объекта с ним ещё нет. УстановитьСсылкуНового работает только до первой записи. Именно так переносят идентификаторы при миграции, чтобы ссылки из внешней системы указывали на правильные объекты.
Пакетная обработка и временные таблицы
Если заменить нужно не один объект, а тысячи (например, после массового задвоения при обмене), обработка «в лоб» упрётся в память и в длинную транзакцию. Помогают временные таблицы и обработка порциями.
Список заменяемых ссылок удобно поместить во временную таблицу запроса и соединять с ней документы — так поиск использований идёт по индексу, а не перебором:
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ Ссылка ПОМЕСТИТЬ ВТ_Замена
ИЗ &ТаблицаЗамен КАК Т
ИНДЕКСИРОВАТЬ ПО Ссылка";
Запрос.УстановитьПараметр("ТаблицаЗамен", ТаблицаЗамен);
Запрос.Выполнить();
Дальше во втором запросе соединяете нужные документы с временной таблицей ВТ_Замена и получаете только затронутые объекты.
Саму запись ведите пачками по несколько сотен объектов, фиксируя каждую пачку отдельной транзакцией. Это снижает нагрузку на буфер транзакции и уменьшает риск блокировок. Не заворачивайте десятки тысяч записей в одну транзакцию — её откат при сбое занимает столько же, сколько сама операция, и всё это время база заблокирована.
Тяжёлую замену запускайте в фоновом задании и в нерабочее время. Промежуточный результат логируйте, чтобы при обрыве продолжить с места остановки, а не начинать заново.
Проверка результата, перепроведение и откат
Замена ссылок почти всегда задевает движения документов. Если у документа поменялся реквизит, по которому строятся проводки или записи регистров, движения нужно пересчитать.
Что проверить после замены:
- 📄 Перепроведение. Документы, затронутые заменой, перепроведите (групповое перепроведение за период или типовое «Проведение документов»). Типовой инструмент «Поиск и удаление дублей» предлагает это сделать сам.
- 🔎 Остаточные ссылки. Прогоните
НайтиПоСсылкампо старому объекту ещё раз. Пустая таблица означает, что ссылок на него не осталось. - 🗑 Удаление старого объекта. Пометьте его на удаление и запустите
Операции → Удаление помеченных объектов(или одноимённую обработку в разделе «Администрирование»). Платформа не даст удалить объект, пока на него что-то ссылается, — это защита от битых ссылок.
Отдельно держите в голове закрытые периоды. Если замена ссылок затрагивает документы за уже закрытый месяц и требует их перепроведения, сначала проверьте дату запрета изменения данных: при включённом запрете перепроведение в закрытом периоде не пройдёт. Либо временно сдвиньте дату запрета, либо согласуйте правку с тем, кто отвечает за закрытие периода , чтобы не разошлись отчётность и учётные данные.
Отдельной кнопки «отменить замену ссылок» в 1С нет. Единственный надёжный откат — восстановление из резервной копии, сделанной до операции. Поэтому копия перед заменой не формальность, а реальный план отступления. Если база большая и восстановление целиком затянется, заранее прикиньте время простоя и выбирайте для операции окно, когда этот простой допустим.
Частые вопросы
Можно ли изменить GUID уже записанного объекта?
УстановитьСсылкуНового, а затем перевести на него ссылки и удалить старый.Что происходит со старым объектом после замены ссылок?
Нужно ли перепроводить документы после замены?
Чем `ПолучитьСсылку` отличается от `НайтиПоКоду` или `НайтиПоНаименованию`?
НайтиПоКоду ищет существующий элемент по реквизиту и возвращает пустую ссылку, если не нашёл. ПолучитьСсылку(Идентификатор) формирует ссылку по заданному GUID, даже если объекта с таким идентификатором ещё нет в базе.Сохранятся ли ссылки при переносе базы через выгрузку `.dt`?
.dt — это полная копия базы, все идентификаторы и ссылки сохраняются без изменений. Ссылки «переезжают» только при обмене через правила конвертации, где объекты ищутся по полям сопоставления.