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

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

В практике разработчика 1С часто возникает задача не просто вывести отчет на экран, но и зафиксировать его результаты в базе данных. Это может быть необходимо для сохранения истории расчетов, последующего план-фактного анализа или передачи данных в другие подсистемы. В данной статье мы подробно разберем, как извлечь данные из сформированного отчета (даже если он построен не на СКД) и записать их в табличную часть нового документа.

Преобразование табличного документа в таблицу значений

Первым шагом в решении нашей задачи является получение «сырых» данных из визуальной формы отчета. Результатом работы большинства отчетов в 1С является ТабличныйДокумент. Чтобы программно обрабатывать строки и колонки, нам необходимо конвертировать его в объект ТаблицаЗначений. Рассмотрим универсальную функцию, которая обходит ячейки табличного документа и формирует таблицу.


Функция ТабличныйДокументВТаблицуЗначений(ВхТабДок)
    ТаблицаДанныеДокумента = Новый ТаблицаЗначений;
    
    // Создаем колонки в таблице значений по ширине отчета
    Для СчетчикКолонок = 1 По ВхТабДок.ШиринаТаблицы Цикл
        ИмяКолонки = "_" + СчетчикКолонок;
        ТаблицаДанныеДокумента.Колонки.Добавить(ИмяКолонки);
    КонецЦикла;

    // Наполняем таблицу строками
    Для СчетчикСтрок = 1 По ВхТабДок.ВысотаТаблицы Цикл
        СтрокаТаблицы = ТаблицаДанныеДокумента.Добавить();
        Для СчетчикКолонок = 1 По ВхТабДок.ШиринаТаблицы Цикл
            ИмяКолонки = "_" + СчетчикКолонок;
            ТекущаяЯчейка = ВхТабДок.Область(СчетчикСтрок, СчетчикКолонок);
            // Извлекаем текст ячейки
            СтрокаТаблицы[ИмяКолонки] = ТекущаяЯчейка.Текст;
        КонецЦикла;
    КонецЦикла;
    
    Возврат ТаблицаДанныеДокумента;
КонецФункции

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

Программное создание документа и заполнение табличной части

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


Процедура ЗаписатьРезультатВДокумент(ВхТабДок)
    // Конвертируем отчет в ТЗ
    тз = ТабличныйДокументВТаблицуЗначений(ВхТабДок);
    
    // Создаем объект нового документа
    НовыйДок = Документы.РегистраторСебестоимости.СоздатьДокумент();
    НовыйДок.Дата = ТекущаяДата();
    
    Для каждого стр Из тз Цикл
        // Поиск номенклатуры по наименованию (колонка _2 в нашем примере)
        НоменСсылка = Справочники.Номенклатура.НайтиПоНаименованию(стр._2, Истина);
        
        // Если номенклатура не найдена, пропускаем строку (например, это заголовок или пустая строка)
        Если НоменСсылка.Пустая() Тогда
            Продолжить;
        КонецЕсли;
        
        // Добавляем строку в табличную часть документа
        НоваяСтрокаТЧ = НовыйДок.ТЧ.Добавить();
        НоваяСтрокаТЧ.Номенклатура = НоменСсылка;
        
        // Преобразуем текст из колонки себестоимости в число
        // Предположим, что себестоимость находится в колонке _10
        НоваяСтрокаТЧ.Себестоимость = Число(стр._10);
    КонецЦикла;
    
    // Записываем и проводим документ
    Попытка
        НовыйДок.Записать(РежимЗаписиДокумента.Проведение);
        Сообщить("Документ успешно создан: " + НовыйДок.Ссылка);
    Исключение
        Сообщить("Ошибка при записи документа: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Работа с динамическими колонками

Часто возникает ситуация, когда количество колонок с данными (например, себестоимость по разным складам или периодам) заранее неизвестно или их несколько. В 1С мы можем обращаться к колонкам таблицы значений по их имени, используя квадратные скобки: стр[ИмяКолонки]. Рассмотрим, как просуммировать данные из нескольких колонок, если их имена хранятся в массиве.


// Пример суммирования данных из динамического списка колонок
СуммаСебестоимости = 0;
МассивНужныхКолонок = Новый Массив;
МассивНужныхКолонок.Добавить("_10");
МассивНужныхКолонок.Добавить("_11");
МассивНужныхКолонок.Добавить("_12");

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

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

Чтобы код работал быстро и без ошибок на больших объемах данных, проанализируем следующие рекомендации:

  1. Использование расшифровки: Вместо поиска номенклатуры по тексту ячейки через НайтиПоНаименованию, лучше использовать свойство ПараметрРасшифровки. В большинстве отчетов в расшифровке ячейки уже лежит готовая ссылка на объект. Это исключит ошибки, связанные с опечатками в названиях или дублями.
  2. Очистка чисел: При получении числа из текста табличного документа (ТекущаяЯчейка.Текст), 1С часто добавляет неразрывные пробелы как разделители разрядов (например, "1 500,00"). Функция Число() выдаст ошибку, если их не удалить. Используйте СтрЗаменить(Текст, Символы.НПП, "").
  3. Массовый поиск: Если расшифровка недоступна, не делайте поиск в цикле. Сначала соберите все наименования в массив, передайте его в запрос, получите соответствия "Наименование - Ссылка" и сохраните их в Соответствие. Это в десятки раз ускорит выполнение обработки.
  4. Проверка уровней группировки: Если ваш отчет содержит итоги по группам номенклатуры или иерархию, при простом переборе строк вы получите задвоение данных (попадут и детальные записи, и итоги). Проверяйте ТекущаяЯчейка.Уровень() или анализируйте содержимое соседних ячеек, чтобы обрабатывать только строки с конкретным товаром.
  5. Построитель отчета: Если ваш отчет использует старый механизм ПостроительОтчета, вы можете вызвать метод Построитель.Результат.Выгрузить(). Это позволит получить таблицу значений напрямую из базы данных, сохранив типы (числа останутся числами, ссылки — ссылками), минуя этап парсинга табличного документа.

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

← На главную