Как исправить дублирование записей при использовании вложенных циклов и правильно объединять строки в 1С?

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

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

Причина возникновения дубликатов во вложенных циклах

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


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

Когда мы вкладываем циклы друг в друга, количество итераций самого глубокого цикла вычисляется как произведение длин всех массивов. Это называется декартовым произведением. Если в каждом массиве будет хотя бы по 5 элементов, количество записей составит 5 * 5 * 5 * 5 * 5 = 3125. Если автор видит «четыре копии», это означает, что один из массивов содержит 4 элемента, которые перемножаются с остальными данными, создавая избыточность в тех измерениях, где она не предполагалась.

Выясним причину: часто программист ошибочно помещает перебор материалов (номенклатуры) внутрь перебора технических характеристик (двигатель, КПП), хотя логика задачи может подразумевать, что конкретный материал привязан только к определенной модели или виду ремонта. Чтобы исправить это, необходимо пересмотреть структуру вложенности или использовать запросы для предварительной подготовки данных.

Оптимизация работы с регистром сведений

Обратим внимание на важный архитектурный момент: использование СоздатьМенеджерЗаписи() внутри вложенных циклов является крайне непроизводительным. Рассмотрим, как это работает на уровне базы данных: на каждой итерации система создает отдельный объект, открывает транзакцию, записывает одну строку и закрывает транзакцию.

Вместо этого рекомендуется использовать объект НаборЗаписей. Проанализируем правильный алгоритм:

  1. Сформируем таблицу значений со всеми необходимыми данными.
  2. Создадим объект РегистрыСведений.НазваниеРегистра.СоздатьНаборЗаписей().
  3. Установим необходимые отборы (если нужно).
  4. Загрузим подготовленную таблицу в набор с помощью метода Набор.Загрузить(ТаблицаДанных).
  5. Выполним одну команду Набор.Записать().

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

Манипуляции со строками: формирование кодов и артикулов

Часто при заполнении регистров требуется сформировать уникальный «Код модели» или описание на основе нескольких параметров. Рассмотрим задачу: из строки 37CX920072015 нужно получить только первые три символа (37C), из года 2007 — последние две цифры (07) и соединить их через подчеркивание.

Для решения этой задачи в 1С применяются функции Лев() (взять символы слева), Прав() (взять символы справа) и Сред() (взять из середины). Разберем пример кода, предложенный в обсуждении:


Рег.КодМодели = стр5.НаименованиеТОЙОТА + "_" + Лев(стр2, 3) + "_" + Прав(стр4, 2) + "_" + Прав(НачПериода, 2) + "/" + Прав(КонПериода, 2); 

Важные правила конкатенации (сложения) строк:

Использование современных методов (СтрШаблон)

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


ШаблонКода = "%1_%2_%3_%4/%5";
Рег.КодМодели = СтрШаблон(ШаблонКода, 
    стр5.НаименованиеТОЙОТА, 
    Лев(стр2, 3), 
    Прав(стр4, 2), 
    Прав(Строка(Год(НачПериода)), 2), 
    Прав(Строка(Год(КонПериода)), 2)
);

Этот подход позволяет четко видеть структуру формируемой строки и легко вносить изменения в формат разделителей (нижнее подчеркивание, косая черта и т.д.).

Резюме для разработчика

Для предотвращения «задвоений» в циклах и повышения качества кода придерживайтесь следующих правил:

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