В процессе разработки часто возникает необходимость автоматизировать перенос данных из табличных частей справочников или документов в регистры сведений. Это позволяет более эффективно использовать механизмы среза последних, индексацию и обеспечивать быстроту получения итоговых данных. Рассмотрим по шагам, как реализовать такую обработку, проанализируем типичные ошибки и разберем наиболее эффективные программные методы записи.
В представленном примере автор пытается рассчитать вознаграждение менеджера на основе оборотов продаж и настроек из табличной части справочника. Процесс разбит на несколько этапов: получение данных через Запрос и последующая фиксация этих данных. Проанализируем запрос автора. В нем используется временная таблица для получения оборотов из регистра накопления Продажи.Обороты и левое соединение с табличной частью справочника Менеджеры.НастройкаВознаграждения.
Важный технический момент: при соединении таблиц по условию «больше или равно» (ВТ.СуммаОборот >= ТабМенеджеры.СуммаПродажЗаМесяц) на больших объемах данных производительность может снизиться. Рекомендуется сначала максимально ограничить выборку менеджеров, для которых производится расчет, используя параметры &НачалоПериода и &КонецПериода.
Основной вопрос, который возник у автора: «Как сделать запись в регистр?». Платформа 1С предлагает два основных способа записи данных во внеоборотные регистры (те, которые не подчинены регистратору):
РегистрСведенийМенеджерЗаписи) — подходит для создания или изменения одной конкретной записи. В рамках циклической обработки большого объема данных этот метод менее производителен.РегистрСведенийНаборЗаписей) — наиболее предпочтительный метод для массового переноса данных. Он позволяет записать группу записей одним транзакционным блоком, что значительно ускоряет процесс.Разберем, как дополнить исходный код процедурой записи. После того как РезультатЗапроса получен, нам необходимо перебрать его и заполнить набор записей. Рассмотрим пример реализации:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем объект набора записей
Набор = РегистрыСведений.НастройкаВознаграждения.СоздатьНаборЗаписей();
// Устанавливаем отбор, чтобы не перезаписать лишние данные
// Обычно отбор устанавливается по измерениям регистра
Набор.Отбор.Менеджер.Установить(Выборка.Ссылка);
// Создаем новую запись в наборе
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Менеджер = Выборка.Ссылка;
НоваяЗапись.Процент = Выборка.Поле1; // Значение из запроса
// Если регистр периодический, обязательно заполняем Период
// НоваяЗапись.Период = ТекущаяДата();
// Записываем набор (Истина означает замещение существующих записей по данному отбору)
Набор.Записать(Истина);
КонецЦикла;
В данном примере мы используем метод СоздатьНаборЗаписей(). Установка отбора перед записью критически важна. Если вызвать метод Записать(Истина) без установленного отбора, платформа может очистить весь регистр. При установленном отборе по менеджеру Набор.Отбор.Менеджер.Установить() будут перезаписаны данные только по конкретному сотруднику.
Если данных в результате запроса очень много, использование метода Загрузить() у объекта РегистрСведенийНаборЗаписей будет еще более эффективным. Выясним, как это работает: если имена колонок в таблице значений, полученной из запроса, полностью совпадают с именами измерений и ресурсов регистра, можно передать всю таблицу целиком в набор записей.
Проанализируем этот подход на примере:
ТЗ_Результат = РезультатЗапроса.Выгрузить();
// Имена колонок в ТЗ должны совпадать с именами полей в Регистре
Набор = РегистрыСведений.НастройкаВознаграждения.СоздатьНаборЗаписей();
// Если нужно загрузить всё сразу, отбор не устанавливаем или устанавливаем по общим признакам
Набор.Загрузить(ТЗ_Результат);
Набор.Записать();
Рассмотрим дополнительные аспекты, которые необходимо учитывать при разработке механизмов переноса данных:
Записать() выдаст ошибку.БлокировкаДанных. Это предотвратит попытки одновременного изменения одних и тех же записей разными пользователями и исключит возникновение взаимоблокировок.Таким образом, для успешного переноса данных из табличной части справочника «Менеджеры» в регистр сведений необходимо не только подготовить корректный запрос для получения данных, но и правильно использовать объект РегистрСведенийНаборЗаписей, не забывая про установку фильтров в свойстве Отбор.