Как реализовать сохранение табличной части справочника в регистр сведений?

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

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

Постановка задачи и анализ ситуации

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

Разберем основные подходы, начиная от самых простых и заканчивая наиболее эффективными с точки зрения производительности системы.

Вариант 1. Использование менеджера записи (построчный перебор)

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


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

В данном примере мы используем метод ЗаполнитьЗначенияСвойств. Это очень удобная функция, которая автоматически копирует данные из колонок табличной части в одноименные измерения или ресурсы регистра. Однако у этого метода есть существенный минус: если в табличной части 100 строк, система выполнит 100 отдельных транзакций записи, что крайне негативно сказывается на быстродействии.

Вариант 2. Оптимальный метод — использование набора записей

Для профессиональной разработки рекомендуется использовать НаборЗаписей. Это позволяет записать все изменения одним пакетом. Кроме того, использование набора данных с установленным отбором позволяет автоматически очищать старые записи регистра, которые более не актуальны (например, если из табличной части справочника удалили строку).

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

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

Посмотрим на программную реализацию в модуле объекта:


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

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

Работа со ссылочными типами данных

Часто возникает вопрос: почему данные не переносятся, если в регистре поле имеет тип ссылки? Выясним причину. При использовании ЗаполнитьЗначенияСвойств система сопоставляет имена колонок и их типы. Если в табличной части колонка называется Товар и имеет тип СправочникСсылка.Номенклатура, а в регистре измерение называется также и имеет тот же тип, проблем не возникнет.

Если же вам нужно программно присвоить ссылку на другой объект, не присутствующий в строке напрямую, используйте обращение к метаданным или поиск:


// Пример получения ссылки из другого справочника
СсылкаНаСклад = Справочники.Склады.НайтиПоНаименованию("Основной склад");
НоваяЗапись.Склад = СсылкаНаСклад;

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

Типичные ошибки и советы по отладке

Рассмотрим ситуации, с которыми часто сталкиваются разработчики:

Проанализируем работу с функцией ЗаполнитьЗначенияСвойств подробнее. Для вызова справки по ней всегда можно использовать комбинацию клавиш Ctrl+F1. Она сопоставляет свойства источника и приемника по именам. Если вы хотите исключить какие-то поля из копирования, вы можете указать их в третьем параметре функции в виде строки через запятую.

Заключение

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

← На главную