Как добавить данные из массива в набор записей регистра сведений 1С

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

При разработке на платформе 1С:Предприятие 8.3 разработчики нередко сталкиваются с ситуацией, когда требуется дополнить существующие записи независимого регистра сведений новыми значениями. Попытка использовать метод набора записей ЗагрузитьКолонку для добавления строк часто приводит к неожиданному поведению: количество записей не увеличивается, а имеющиеся данные перезаписываются или повреждаются. Разберем по шагам, почему так происходит, и рассмотрим правильные подходы к решению этой задачи.

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


НабЗап = РегистрыСведений.МойРегСвед.СоздатьНаборЗаписей();
НабЗап.Прочитать();
НабЗап.ЗагрузитьКолонку(НужныйМассив, "ПравильноеИмя");
НабЗап.Записать(Истина);

В этом примере после чтения в наборе находится 6 строк. Если НужныйМассив содержит элементы, разработчик ожидает увеличение общего количества записей (например, 6 + 1 = 7). Однако количество записей остается равным 6. Выясним причину такого поведения платформы.

Особенности работы метода ЗагрузитьКолонку

Посмотрим на назначение и правила работы метода ЗагрузитьКолонку, зафиксированные в синтакс-помощнике платформы 1С:Предприятие:

  1. Метод ЗагрузитьКолонку предназначен исключительно для заполнения значений в уже существующих строках набора, а не для добавления новых строк.
  2. Значения из переданного массива переносятся в указанную колонку строго по индексам строк. Нулевой элемент массива записывается в нулевую строку набора, первый — в первую и так далее.
  3. Если в массиве меньше элементов, чем строк в наборе записей, будут изменены только первые строки (соответствующие размеру массива), а остальные останутся без изменений.
  4. Если элементов в массиве больше, чем строк в наборе, лишние элементы массива просто игнорируются — новые строки платформой не порождаются.

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

Критический риск перезаписи регистра без отбора

Обратим внимание на вызов НабЗап.Записать(Истина) без предварительной установки отбора (Отбор). Если независимый регистр сведений перезаписывается без указания условий отбора с параметром замещения Истина, платформа очищает все остальные записи в базе данных, которые не вошли в текущий набор. Кроме того, чтение и запись всего регистра целиком приводят к блокировкам таблицы СУБД, что может парализовать работу пользователей в базе данных.

Разберем корректные способы добавления новых строк из массива в регистр сведений.

Способ 1. Обход массива в цикле и поштучное добавление записей

Самый надежный, простой и прозрачный способ добавить элементы массива в регистр — это последовательный перебор элементов массива с вызовом метода Добавить() у набора записей.

Если нам необходимо просто дописать новые строки в базу без предварительного считывания всей таблицы регистра, мы можем использовать пустой набор записей и метод Записать(Ложь):


НабЗап = РегистрыСведений.МойРегСвед.СоздатьНаборЗаписей();

// Обязательно устанавливаем отбор по измерению, если регистр подчинен или требуется обновить срез
// НабЗап.Отбор.Организация.Установить(ТекущаяОрганизация);

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

// Параметр Замещать = Ложь указывает платформе не очищать существующие записи
НабЗап.Записать(Ложь);

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

Способ 2. Формирование Таблицы Значений и пакетная загрузка

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

Рассмотрим, как подготовить таблицу значений для загрузки:


НабЗап = РегистрыСведений.МойРегСвед.СоздатьНаборЗаписей();

// Получаем пустую таблицу значений с точной структурой колонок регистра
ТЗ = НабЗап.ВыгрузитьКолонки();

// Добавляем в таблицу столько пустых строк, сколько элементов в массиве
Для Сч = 1 По НужныйМассив.Количество() Цикл
    ТЗ.Добавить();
КонецЦикла;

// Теперь ЗагрузитьКолонку отработает корректно, так как строки в ТЗ уже созданы
ТЗ.ЗагрузитьКолонку(НужныйМассив, "Номенклатура");

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

// Загружаем сформированную таблицу в набор записей
НабЗап.Загрузить(ТЗ);
НабЗап.Записать(Ложь);

Способ 3. Использование Менеджера Записи

Когда требуется добавить всего один элемент или небольшое количество записей с проверкой существования каждой строки, часто удобнее использовать объект МенеджерЗаписи. Он работает с единичной строкой регистра и позволяет избежать блокировок целых диапазонов таблицы:


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

Итоги и рекомендации

  1. Метод ЗагрузитьКолонку оперирует только существующими индексами строк и не создает новых записей в наборе.
  2. Для массового добавления данных из одномерного массива оптимальным решением является перебор массива в цикле с добавлением строк в пустой набор через метод Добавить().
  3. При записи набора записей всегда анализируйте необходимость использования параметра Замещать = Ложь и следите за установкой фильтров в свойстве Отбор, чтобы случайно не стереть данные регистра.
← На главную