При разработке алгоритмов занесения данных из одной группы документов в другой часто возникают ошибки, связанные с неверной логикой работы циклов или отсутствием промежуточных структур данных. В 1С 7.7 одна из распространенных проблем — перезапись значений переменных в цикле обхода строк документов, из-за чего в итоговый расчет попадает только значение из последней строки последнего документа.
Рассмотрим, в чем заключается эта проблема, проанализируем ошибки в коде и разберем правильные способы заполнения табличных частей.
Проанализируем типичный фрагмент кода, в котором выполняется попытка получить количество и адреса из существующих документов:
Док = СоздатьОбъект("Документ.Перерасчет");
Док.ВыбратьДокументы(НачМесяца(Дата1), КонМесяца(Дата2));
Пока Док.ПолучитьДокумент() > 0 Цикл
Если Док.Проведен() = 0 Тогда
Продолжить;
КонецЕсли;
Док.ВыбратьСтроки();
Пока Док.ПолучитьСтроку() = 1 Цикл
Количество = Док.Количество; // Ошибка: переменная постоянно перезаписывается!
КонецЦикла;
КонецЦикла;
В чем заключается ошибка? При выполнении внутреннего цикла по строкам Док.ПолучитьСтроку() переменная Количество перезаписывается на каждом шаге. После завершения циклов в ней останется только значение последней строки последнего прочитанного документа. Итоговый расчет с использованием этой переменной будет некорректным.
Если необходимо обработать данные табличной части документа-источника, оптимальным подходом является выгрузка данных во временную структуру с помощью ТаблицаЗначений, ее сводка и последующее заполнение целевой табличной части.
ВыгрузитьТабличнуюЧасть().Рассмотрим пример формирования структуры и заполнения через объект ТаблицаЗначений:
ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
ТабЗнач.НоваяКолонка("Адрес");
ТабЗнач.НоваяКолонка("Количество");
ТабЗнач.НоваяКолонка("Сумма");
// Наполнение таблицы значений из обработанных документов
Док = СоздатьОбъект("Документ.Перерасчет");
Док.ВыбратьДокументы(НачМесяца(Дата1), КонМесяца(Дата2));
Пока Док.ПолучитьДокумент() = 1 Цикл
Если (Док.Проведен() = 0) Или (Док.ПометкаУдаления() = 1) Тогда
Продолжить;
КонецЕсли;
Док.ВыбратьСтроки();
Пока Док.ПолучитьСтроку() = 1 Цикл
ТабЗнач.НоваяСтрока();
ТабЗнач.Адрес = Док.Адрес;
ТабЗнач.Количество = Док.Количество;
ТабЗнач.Сумма = Док.Сумма;
КонецЦикла;
КонецЦикла;
// Группируем показатели по адресу
ТабЗнач.Свернуть("Адрес", "Количество, Сумма");
// Переносим собранные данные в табличную часть формы
ТабЛС.УдалитьСтроки();
ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку() = 1 Цикл
ТабЛС.НоваяСтрока();
ТабЛС.Адрес = ТабЗнач.Адрес;
ТабЛС.Количество = ТабЗнач.Количество;
ТабЛС.Сумма = ТабЗнач.Сумма;
КонецЦикла;
Для повышения производительности при работе с большим объемом данных за период рекомендуется отказаться от последовательного перебора методом ВыбратьДокументы() в пользу встроенного языка запросов.
Преимущество запроса заключается в том, что платформа сразу выполняет фильтрацию по состоянию проведения, виду документа и группирует данные на уровне выборки.
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с (НачМесяца(Дата1)) по (КонМесяца(Дата2));
|Адрес = Документ.Перерасчет.Адрес;
|Количество = Документ.Перерасчет.Количество;
|Сумма = Документ.Перерасчет.Сумма;
|Функция ВсегоКоличество = Сумма(Количество);
|Функция ВсегоСумма = Сумма(Сумма);
|Группировка Адрес без групп;
|Условие(Документ.Перерасчет.Комментарий = ""Начало отопительного периода"");
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
ТабЛС.УдалитьСтроки();
Пока Запрос.Группировка("Адрес") = 1 Цикл
ТабЛС.НоваяСтрока();
ТабЛС.Адрес = Запрос.Адрес;
ТабЛС.Количество = Запрос.ВсегоКоличество;
ТабЛС.Сумма = Запрос.ВсегоСумма;
КонецЦикла;
КонецЕсли;
Если требуется заполнить новый документ на основании только одного конкретного документа, логичнее использовать штатный механизм конфигуратора:
ДокументОснование соответствующего типа.ВводНаОсновании(ДокОснование), в которой перенести реквизиты и строки табличной части через ВыгрузитьТабличнуюЧасть() или построчным перебором.Выбор конкретного решения зависит от задачи: для консолидации нескольких документов за период подходят Запросы и Таблицы Значений, а для переноса данных один-к-одному — штатный Ввод на основании.