Как найти все регистры, содержащие определенную номенклатуру, и перенести эти данные в другую базу

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

В процессе разработки часто возникает задача — найти все «следы» конкретного объекта (например, номенклатуры) во всей информационной базе. Это может быть продиктовано необходимостью очистки данных, анализа остатков или, как в нашем случае, задачей частичного переноса данных из одной базы 1С в другую. Разберем детально, как программно определить список регистров и правильно организовать передачу информации.

Метод 1. Программный перебор метаданных

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

Рассмотрим пример кода, который формирует список имен регистров, где встречается тип СправочникСсылка.Номенклатура:


Функция НайтиРегистрыСНоменклатурой()
    СписокРегистров = Новый СписокЗначений;
    ТипНоменклатура = Тип("СправочникСсылка.Номенклатура");

    // Перебираем регистры сведений
    Для Каждого МДРегистр Из Метаданные.РегистрыСведений Цикл
        Если СодержитТипНоменклатура(МДРегистр, ТипНоменклатура) Тогда
            СписокРегистров.Добавить(МДРегистр.ПолноеИмя());
        КонецЕсли;
    КонецЦикла;

    // Аналогично для регистров накопления
    Для Каждого МДРегистр Из Метаданные.РегистрыНакопления Цикл
        Если СодержитТипНоменклатура(МДРегистр, ТипНоменклатура) Тогда
            СписокРегистров.Добавить(МДРегистр.ПолноеИмя());
        КонецЕсли;
    КонецЦикла;

    Возврат СписокРегистров;
КонецФункции

Функция СодержитТипНоменклатура(МДОбъект, ЦелевойТип)
    // Проверяем измерения
    Для Каждого МДПоле Из МДОбъект.Измерения Цикл
        Если МДПоле.Тип.СодержитТип(ЦелевойТип) Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;

    // Проверяем ресурсы
    Для Каждого МДПоле Из МДОбъект.Ресурсы Цикл
        Если МДПоле.Тип.СодержитТип(ЦелевойТип) Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;

    // Проверяем реквизиты
    Для Каждого МДПоле Из МДОбъект.Реквизиты Цикл
        Если МДПоле.Тип.СодержитТип(ЦелевойТип) Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;

    Возврат Ложь;
КонецФункции

Важный нюанс: при проверке типов обязательно используйте метод СодержитТип(). Это критично, так как поле может иметь составной тип данных (например, ДокументСсылка.Реализация или СправочникСсылка.Номенклатура), и обычное сравнение типов здесь не сработает.

Метод 2. Использование системной функции НайтиПоСсылкам

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


МассивСсылок = Новый Массив;
МассивСсылок.Добавить(ВыбраннаяНоменклатура);
ТаблицаСсылок = НайтиПоСсылкам(МассивСсылок);

Для Каждого Строка Из ТаблицаСсылок Цикл
    Сообщить("Найдено в: " + Строка.Данные);
КонецЦикла;

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

Метод 3. Поиск в регистрах бухгалтерии и расчета

Не забудем про специфические виды регистров. В регистрах бухгалтерии номенклатура чаще всего выступает в роли субконто. Проверить это сложнее, так как связь идет через План Счетов. Нам нужно проанализировать виды субконто, установленные для счетов. В регистрах расчета номенклатура может быть как измерением, так и реквизитом. Для полной картины мы обязаны включить их в наш алгоритм перебора метаданных, используя коллекции Метаданные.РегистрыБухгалтерии и Метаданные.РегистрыРасчета.

Организация переноса данных: Сериализация

Когда список регистров получен и данные извлечены (например, в таблицу значений), встает вопрос их передачи в другую базу. Рассмотрим несколько вариантов:

  1. XDTO-сериализация: Это наиболее «профессиональный» метод. XDTO (XML Data Transfer Objects) позволяет сохранить структуру объекта и его типы в XML или JSON. Используем СериализаторXDTO для преобразования наборов записей или целых таблиц.
  2. Двоичные данные (Binary Data): Если структуры метаданных в базах идентичны, можно использовать методы ЗначениеВДанные() и ДанныеИзЗначения(). Это работает максимально быстро, так как данные упаковываются в компактный бинарный формат.
  3. JSON: Удобен для передачи через HTTP-сервисы. Однако при использовании JSON мы должны помнить, что ссылки (GUID) превратятся в строки, и в базе-приемнике их нужно будет восстанавливать.

Пример упаковки таблицы значений в строку для передачи:


// В базе-источнике
ДвоичныеДанные = ЗначениеВДанные(ТаблицаСДаннымиРегистров);
СтрокаДляПередачи = Base64Строка(ДвоичныеДанные);

// В базе-приемнике
ДвоичныеДанныеПрием = Base64Значение(СтрокаДляПередачи);
ТаблицаРезультат = ДанныеИзЗначения(ДвоичныеДанныеПрием);

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

Проанализируем критически важный момент: целостность ссылок. Если мы просто перенесем записи регистра «Цены номенклатуры», но в базе-приемнике сама номенклатура имеет другой УникальныйИдентификатор (даже при совпадающем артикуле и наименовании), записи регистра «потеряются». Они будут ссылаться на пустой объект «Объект не обнаружен».

Правильный алгоритм переноса:

  1. Сначала проверяем наличие объекта-владельца (Номенклатуры) в приемнике по GUID.
  2. Если объекта нет, создаем его с тем же самым GUID, что и в источнике.
  3. Переносим связанные справочники (Единицы измерения, Виды цен), иначе данные в регистрах будут неполными.
  4. Только после этого записываем данные в регистры.

Работа с виртуальными таблицами

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

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

Заключение

Подведем итог. Для качественного решения задачи мы должны сочетать программный анализ метаданных (для полноты охвата) с механизмами поиска ссылок. При переносе данных отдаем приоритет средствам платформенной сериализации (XDTO или ЗначениеВДанные) и обязательно следим за идентичностью УникальныхИдентификаторов. Такой комплексный подход гарантирует, что ни одна запись регистра не будет потеряна, а данные в целевой базе останутся консистентными.

← На главную