При разработке отчетов и обработок в платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с ситуацией, когда цикл по выборке корреспондирующего субконто с помощью метода ПолучитьКорСубконто() просто не выполняется. Программа проходит мимо блока кода, не выдавая явных синтаксических ошибок, однако переменные остаются пустыми. Разберем по шагам, почему возникает эта ошибка в объекте БухгалтерскиеИтоги, какие архитектурные ограничения платформы необходимо учитывать и как правильно построить выборку аналитики корреспонденций.
Рассмотрим типовой фрагмент кода, в котором возникает ошибка обхода корреспондирующей аналитики:
БИ = СоздатьОбъект("БухгалтерскиеИтоги");
БИ.ИспользоватьСубконто();
БИ.ИспользоватьСубконто();
БИ.ИспользоватьКорСубконто();
БИ.ИспользоватьПланСчетов(ПланыСчетов.Основной);
СчДт = СчетПоКоду("631");
СчКт = СчетПоКоду("311");
БИ.ВыполнитьЗапрос(ДатаКон, ДатаКон, СчДт, , ,,,);
БИ.ВыбратьСубконто(1);
Пока БИ.ПолучитьСубконто() = 1 Цикл
БИ.ВыбратьСубконто(2);
Пока БИ.ПолучитьСубконто(2) = 1 Цикл
Если БИ.СКК()=0 Тогда
Продолжить;
КонецЕсли;
БИ.ВыбратьКорСубконто(1);
Пока БИ.ПолучитьКорСубконто(1) = 1 Цикл
// В этот цикл программа даже не заходит
КонецЦикла;
КонецЦикла;
КонецЦикла;
Выясним причину такого поведения. Здесь допущено сразу несколько принципиальных ошибок, связанных с механизмами хранения и расчета бухгалтерских итогов в 1С 7.7.
БИ.СКК() = 0, разработчик рассчитывает распределить остаток по счету на аналитику счета расчетов (например, расчетного счета). Но если за указанную дату (в примере с ДатаКон по ДатаКон) реальных проводок между дебетом 631 и кредитом 311 не было, оборот равен нулю, и выборка по корреспондирующим субконто всегда будет пустой.ВыполнитьЗапрос(<НачалоПериода>, <КонецПериода>, <Счет>, <КоррСчет>, <Валюта>, <ТипИтогов>, <Периодичность>, <ТипСуммы>). По умолчанию шестой параметр <ТипИтогов> равен 1 (расчет остатков и оборотов по счету в целом). В этом режиме платформа не рассчитывает матрицу перекрестных оборотов между счетами и субконто. Чтобы получить доступ к корреспонденциям, этот параметр обязательно должен принимать значение:
СчКт была определена в модуле, но четвертый параметр метода ВыполнитьЗапрос остался пустым. Если корсчет не зафиксирован на этапе запроса, для обхода корреспонденций платформа требует строгого соблюдения иерархии: сначала необходимо открыть выборку по корреспондирующим счетам через ВыбратьКорСчета() и ПолучитьКорСчет(), и только внутри нее обращаться к ВыбратьКорСубконто().ИспользоватьКорСубконто(<ВидСубконто>, <Значение>, <ТипФильтра>). Вызов без параметров часто сбивает внутреннее позиционирование колонок выборки.БИ.СКД(). На уровне корсчетов и корсубконто сальдовые функции не работают. Для считывания сумм оборотов необходимо использовать методы КорДО() (дебетовый оборот с корреспонденцией) или КорКО() (кредитовый оборот с корреспонденцией).Если задача заключается именно в получении оборотов между счетами за период с детализацией по субконто и корсубконто, перепишем код с учетом всех требований платформы:
БИ = СоздатьОбъект("БухгалтерскиеИтоги");
// Явно задаем виды аналитики основного счета и признак разворота (1)
БИ.ИспользоватьСубконто(ВидыСубконто.Контрагенты, , 1);
БИ.ИспользоватьСубконто(ВидыСубконто.Договоры, , 1);
// Явно объявляем аналитику корреспондирующего счета
БИ.ИспользоватьКорСубконто(ВидыСубконто.БанковскиеСчета, , 1);
СчДт = СчетПоКоду("631");
СчКт = СчетПоКоду("311");
// Передаем СчКт (4-й параметр) и ТипИтогов = 3 (6-й параметр)
БИ.ВыполнитьЗапрос(ДатаНач, ДатаКон, СчДт, СчКт, , 3);
БИ.ВыбратьСубконто(1);
Пока БИ.ПолучитьСубконто(1) = 1 Цикл
БИ.ВыбратьСубконто(2);
Пока БИ.ПолучитьСубконто(2) = 1 Цикл
// Переходим к корреспондирующей аналитике
БИ.ВыбратьКорСубконто(1);
Пока БИ.ПолучитьКорСубконто(1) = 1 Цикл
// На уровне корсубконто получаем оборот корреспонденции:
СуммаПроводки = БИ.КорДО();
Если СуммаПроводки = 0 Тогда
Продолжить;
КонецЕсли;
Опер.НоваяПроводка();
Опер.Кредит.Счет = СчКт;
Опер.Кредит.НашиДенежныеСчета = БИ.КорСубконто(1);
Опер.Дебет.Счет = СчДт;
Опер.Дебет.Контрагенты = БИ.Субконто(1);
Опер.Дебет.Заказы = БИ.Субконто(2);
Опер.Сумма = СуммаПроводки;
КонецЦикла;
КонецЦикла;
КонецЦикла;
Если требуется проанализировать движения за конкретный день или сформировать корректирующие проводки на основе уже существующих записей в журнале, гораздо проще и надежнее использовать объект Операция с методом ВыбратьОперацииСПроводками. Это избавляет от сложностей настройки матрицы итогов:
ОперВыборка = СоздатьОбъект("Операция");
// Отбираем все проводки между заданными счетами за период
ОперВыборка.ВыбратьОперацииСПроводками(ДатаКон, ДатаКон, СчДт, СчКт);
Пока ОперВыборка.ПолучитьПроводку() = 1 Цикл
// Доступны значения аналитики напрямую из проводки
ТекСубконтоДт1 = ОперВыборка.Дебет.Субконто(1);
ТекСубконтоДт2 = ОперВыборка.Дебет.Субконто(2);
ТекКорСубконто = ОперВыборка.Кредит.Субконто(1);
СуммаОперации = ОперВыборка.Сумма;
// Выполняем требуемые действия с полученными значениями
КонецЦикла;
Такой подход исключает ошибки позиционирования в объекте БухгалтерскиеИтоги и дает прямой доступ ко всем реквизитам операции и проводки.