В практике разработчика 1С часто возникает задача не просто вывести отчет на экран, но и зафиксировать его результаты в базе данных. Это может быть необходимо для сохранения истории расчетов, последующего план-фактного анализа или передачи данных в другие подсистемы. В данной статье мы подробно разберем, как извлечь данные из сформированного отчета (даже если он построен не на СКД) и записать их в табличную часть нового документа.
Первым шагом в решении нашей задачи является получение «сырых» данных из визуальной формы отчета. Результатом работы большинства отчетов в 1С является ТабличныйДокумент. Чтобы программно обрабатывать строки и колонки, нам необходимо конвертировать его в объект ТаблицаЗначений. Рассмотрим универсальную функцию, которая обходит ячейки табличного документа и формирует таблицу.
Функция ТабличныйДокументВТаблицуЗначений(ВхТабДок)
ТаблицаДанныеДокумента = Новый ТаблицаЗначений;
// Создаем колонки в таблице значений по ширине отчета
Для СчетчикКолонок = 1 По ВхТабДок.ШиринаТаблицы Цикл
ИмяКолонки = "_" + СчетчикКолонок;
ТаблицаДанныеДокумента.Колонки.Добавить(ИмяКолонки);
КонецЦикла;
// Наполняем таблицу строками
Для СчетчикСтрок = 1 По ВхТабДок.ВысотаТаблицы Цикл
СтрокаТаблицы = ТаблицаДанныеДокумента.Добавить();
Для СчетчикКолонок = 1 По ВхТабДок.ШиринаТаблицы Цикл
ИмяКолонки = "_" + СчетчикКолонок;
ТекущаяЯчейка = ВхТабДок.Область(СчетчикСтрок, СчетчикКолонок);
// Извлекаем текст ячейки
СтрокаТаблицы[ИмяКолонки] = ТекущаяЯчейка.Текст;
КонецЦикла;
КонецЦикла;
Возврат ТаблицаДанныеДокумента;
КонецФункции
Важное замечание: При обходе табличного документа следует учитывать структуру отчета. Если в отчете присутствуют шапки, подвалы или пустые строки для оформления, их необходимо отсеивать при анализе полученной таблицы значений, чтобы не загрузить «мусорные» данные в документ.
После того как данные получены в виде таблицы значений, мы приступаем к созданию документа. Проанализируем алгоритм, который перебирает строки таблицы, ищет соответствующие элементы в справочнике Номенклатура и заполняет табличную часть ТЧ нового документа РегистраторСебестоимости.
Процедура ЗаписатьРезультатВДокумент(ВхТабДок)
// Конвертируем отчет в ТЗ
тз = ТабличныйДокументВТаблицуЗначений(ВхТабДок);
// Создаем объект нового документа
НовыйДок = Документы.РегистраторСебестоимости.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДата();
Для каждого стр Из тз Цикл
// Поиск номенклатуры по наименованию (колонка _2 в нашем примере)
НоменСсылка = Справочники.Номенклатура.НайтиПоНаименованию(стр._2, Истина);
// Если номенклатура не найдена, пропускаем строку (например, это заголовок или пустая строка)
Если НоменСсылка.Пустая() Тогда
Продолжить;
КонецЕсли;
// Добавляем строку в табличную часть документа
НоваяСтрокаТЧ = НовыйДок.ТЧ.Добавить();
НоваяСтрокаТЧ.Номенклатура = НоменСсылка;
// Преобразуем текст из колонки себестоимости в число
// Предположим, что себестоимость находится в колонке _10
НоваяСтрокаТЧ.Себестоимость = Число(стр._10);
КонецЦикла;
// Записываем и проводим документ
Попытка
НовыйДок.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Документ успешно создан: " + НовыйДок.Ссылка);
Исключение
Сообщить("Ошибка при записи документа: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Часто возникает ситуация, когда количество колонок с данными (например, себестоимость по разным складам или периодам) заранее неизвестно или их несколько. В 1С мы можем обращаться к колонкам таблицы значений по их имени, используя квадратные скобки: стр[ИмяКолонки]. Рассмотрим, как просуммировать данные из нескольких колонок, если их имена хранятся в массиве.
// Пример суммирования данных из динамического списка колонок
СуммаСебестоимости = 0;
МассивНужныхКолонок = Новый Массив;
МассивНужныхКолонок.Добавить("_10");
МассивНужныхКолонок.Добавить("_11");
МассивНужныхКолонок.Добавить("_12");
Для каждого ИмяКолонки Из МассивНужныхКолонок Цикл
Значение = стр[ИмяКолонки];
// Очищаем строку от неразрывных пробелов перед преобразованием
ЧистоеЗначение = СтрЗаменить(Значение, Символы.НПП, "");
СуммаСебестоимости = СуммаСебестоимости + Число(ЧистоеЗначение);
КонецЦикла;
НоваяСтрокаТЧ.Себестоимость = СуммаСебестоимости;
Чтобы код работал быстро и без ошибок на больших объемах данных, проанализируем следующие рекомендации:
НайтиПоНаименованию, лучше использовать свойство ПараметрРасшифровки. В большинстве отчетов в расшифровке ячейки уже лежит готовая ссылка на объект. Это исключит ошибки, связанные с опечатками в названиях или дублями.ТекущаяЯчейка.Текст), 1С часто добавляет неразрывные пробелы как разделители разрядов (например, "1 500,00"). Функция Число() выдаст ошибку, если их не удалить. Используйте СтрЗаменить(Текст, Символы.НПП, "").Соответствие. Это в десятки раз ускорит выполнение обработки.ТекущаяЯчейка.Уровень() или анализируйте содержимое соседних ячеек, чтобы обрабатывать только строки с конкретным товаром.ПостроительОтчета, вы можете вызвать метод Построитель.Результат.Выгрузить(). Это позволит получить таблицу значений напрямую из базы данных, сохранив типы (числа останутся числами, ссылки — ссылками), минуя этап парсинга табличного документа.Таким образом, задача сохранения данных отчета в документ сводится к правильному преобразованию визуального представления в структурную таблицу и корректному сопоставлению данных со справочниками системы. Использование предложенных методов позволит вам автоматизировать анализ изменений и упростить работу пользователей с результатами отчетов.