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

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

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

Метод 1. Перебор с отслеживанием смены даты

Этот способ является самым популярным и простым в реализации. Он основывается на последовательном обходе массива. Важным условием здесь является предварительная сортировка данных по дате. Если массив не будет упорядочен, алгоритм создаст новый документ для каждой строки, где дата отличается от предыдущей, что приведет к дублям.

Разберем алгоритм по шагам. Мы будем хранить дату текущего обрабатываемого документа в специальной переменной. Если дата очередного элемента массива не совпадает с сохраненной, мы записываем текущий документ и начинаем создание нового.

Проанализируем пример кода, реализующий эту логику:


ТекущаяОбрабатываемаяДата = Дата(1,1,1);
ТекущийЗаполняемыйДокумент = Неопределено;

// Предположим, что СтруктураМассивЧеков уже отсортирована по дате
Для каждого ЭлементМоейСтруктуры из СтруктураМассивЧеков Цикл
    // Приводим дату к концу дня или началу дня для корректного сравнения суток
    ДатаЭлемента = НачалоДня(ЭлементМоейСтруктуры.date);
    
    Если ДатаЭлемента <> ТекущаяОбрабатываемаяДата Тогда
        
        // Если это не первая итерация, записываем предыдущий созданный документ
        Если ТекущийЗаполняемыйДокумент <> Неопределено Тогда 
            ТекущийЗаполняемыйДокумент.Записать(РежимЗаписиДокумента.Запись);
        КонецЕсли;
        
        // Создаем новый документ и заполняем шапку
        ТекущийЗаполняемыйДокумент = Документы.ЧекККМ.СоздатьДокумент();
        ТекущийЗаполняемыйДокумент.Дата = ДатаЭлемента;
        // Заполнение других реквизитов шапки (склад, организация)
        // ...
        
        ТекущаяОбрабатываемаяДата = ДатаЭлемента;
    КонецЕсли;
    
    // Заполнение табличной части текущего документа
    Для каждого ДанныеСтроки из ЭлементМоейСтруктуры.Строки Цикл
        НоваяСтрока = ТекущийЗаполняемыйДокумент.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ДанныеСтроки);
    КонецЦикла;
    
КонецЦикла;

// Важно не забыть записать самый последний документ после завершения цикла
Если ТекущийЗаполняемыйДокумент <> Неопределено Тогда 
    ТекущийЗаполняемыйДокумент.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;

Метод 2. Группировка данных через Таблицу Значений

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

Рассмотрим этот подход подробнее:

  1. Загружаем данные из массива в ТаблицаЗначений.
  2. Добавляем колонку ДатаДень, где храним дату без времени.
  3. Создаем копию таблицы, оставляем в ней только колонку ДатаДень и используем метод Свернуть("ДатаДень").
  4. Обходим свернутую таблицу циклом, создавая документы, а строки выбираем методом НайтиСтроки() из основной таблицы.

Метод 3. Использование запроса к временной таблице

Выясним причину, почему для больших объемов данных лучше использовать запросы. Запрос в 1С позволяет выполнить группировку на уровне СУБД (или во временной таблице в памяти), что значительно быстрее ручного перебора. Мы можем передать ТаблицуЗначений в запрос как параметр.

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


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ;
               |ВЫБРАТЬ * ИЗ ВТ_Данные ИТОГИ ПО НачалоПериода(Дата, ДЕНЬ)";
Запрос.УстановитьПараметр("ТЗ", ИсходнаяТаблица);

РезультатЗапроса = Запрос.Выполнить();
ВыборкаПоДатам = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

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

Рекомендации по оптимизации процесса

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

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

2. Режим загрузки данных. Если вы уверены в качестве входных данных и вам не нужно запускать тяжелые проверки (например, проверку остатков или сложные расчеты в модуле объекта), используйте свойство ОбменДанными.Загрузка = Истина. Это отключит стандартные обработчики ПередЗаписью и ПриЗаписи, что колоссально сэкономит время.

3. Кеширование ссылок. Избегайте поиска ссылок (номенклатуры, складов) внутри цикла создания строк табличной части. Поиск методом НайтиПоНаименованию внутри цикла — главная причина медленной работы. Рекомендуется заранее собрать все уникальные идентификаторы товаров из файла, одним запросом получить их ссылки и сохранить в объект Соответствие. В цикле просто извлекайте готовую ссылку из памяти.

4. Установка времени. Если вы создаете документы "задним числом", используйте метод УстановитьВремя(). Это позволит правильно расположить документы в последовательности, особенно если за один день их создается несколько.

5. Проверка на дубли. Перед вызовом СоздатьДокумент() всегда проверяйте, не был ли этот файл загружен ранее. Это можно сделать простым запросом по дате и какому-либо уникальному идентификатору загрузки (например, номеру чека или ID из внешней системы).

Разберем по шагам финальную схему идеальной загрузки: Сбор данных -> Группировка по датам -> Открытие транзакции -> Создание документов с установкой флага Загрузка -> Фиксация транзакции. Соблюдение этой структуры гарантирует стабильную и быструю работу вашей обработки.

← На главную