Почему в запрос БухгалтерскиеИтоги в 1С 7.7 попадают лишние субконто и как это исправить

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет
← На главную

При работе с платформой 1С:Предприятие 7.7 программисты часто сталкиваются с ситуацией, когда объект БухгалтерскиеИтоги ведет себя неочевидно. Типичный пример: вы строите отчет на середину месяца (например, на 15-е число), а в выборку попадают субконто (например, партии товаров), движения по которым возникли только в конце месяца (например, 31-го числа). На первый взгляд это кажется ошибкой платформы, ведь на 15-е число остатка по этой партии еще не существовало. Однако это поведение обусловлено архитектурой хранения данных в «семерке».

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

Анализ механизма работы бухгалтерских итогов

Рассмотрим стандартный код запроса, который часто приводит к возникновению описанной проблемы:


БИ = СоздатьОбъект("БухгалтерскиеИтоги");
БИ.ИспользоватьСубконто(ВидыСубконто.МестаХранения, ВыбМагазины, 1);
БИ.ИспользоватьСубконто(ВидыСубконто.Номенклатура, ВыбТовары, 1);
БИ.ИспользоватьСубконто(ВидыСубконто.ПартииТоваров);
// ДатаОтчета = 15.05.17
БИ.ВыполнитьЗапрос(ДатаОтчета, , "41", , , , , "К");

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

Бухгалтерские итоги в 1С 7.7 хранятся в физических таблицах базы данных (например, 1SBKTTL) с определенной периодичностью — как правило, это месяц. Когда система выполняет метод ВыполнитьЗапрос, она обращается к записям за соответствующий период. Если в мае 2017 года по какой-то партии было хоть одно движение, запись об этой партии будет присутствовать в итогах за май. Метод ПолучитьСубконто() итерирует по всем комбинациям аналитики, которые «засветились» в базе за выбранный период, независимо от того, в какой именно день месяца произошло движение.

Разбор параметров метода ВыполнитьЗапрос

Часто разработчики пытаются решить проблему, манипулируя параметрами начала и конца периода. Рассмотрим, как это влияет на результат:

  1. БИ.ВыполнитьЗапрос(ДатаОтчета, , "41", ...) — если второй параметр (конец периода) не указан, система вычисляет начальные сальдо на момент, указанный в первом параметре. Однако объект все равно «видит» весь блок итогов текущего месяца.
  2. БИ.ВыполнитьЗапрос(ДатаОтчета, ДатаОтчета, "41", ...) — здесь мы явно ограничиваем период одним днем. Это может ускорить запрос, но из-за специфики хранения итогов по месяцам, «будущие» субконто все равно могут попасть в итератор выборки.
  3. Параметр "ТипИтогов" (флаг "К") — использование символьного ключа "К" или числового значения 4 указывает системе на работу с рассчитанными итогами. Это наиболее быстрый способ получения данных, но он не исключает попадания пустых строк в выборку.

Решение проблемы: Программная фильтрация остатков

Поскольку объект БухгалтерскиеИтоги в 1С 7.7 спроектирован так, чтобы возвращать все имеющиеся в периоде разрезы аналитики, единственным надежным способом является ручная проверка остатка внутри цикла обхода. Проанализируем правильный алгоритм реализации:


БИ.ВыбратьСубконто(1); // Места хранения
Пока БИ.ПолучитьСубконто(1) = 1 Цикл
    БИ.ВыбратьСубконто(2); // Номенклатура
    Пока БИ.ПолучитьСубконто(2) = 1 Цикл
        БИ.ВыбратьСубконто(3); // Партии
        Пока БИ.ПолучитьСубконто(3) = 1 Цикл
            
            // Вот ключевой момент фильтрации:
            // Проверяем Сальдо Начальное Дебетовое (или Кредитовое)
            // Если остатка на дату запроса нет — пропускаем итерацию
            Если (БИ.СНД("К") = 0) И (БИ.СНК("К") = 0) Тогда
                Продолжить;
            КонецЕсли;
            
            // Если код дошел сюда, значит по данной партии 
            // действительно есть остаток на ДатаОтчета
            Сообщить("Товар: " + БИ.Субконто(2) + " Партия: " + БИ.Субконто(3));
            
        КонецЦикла;
    КонецЦикла;
КонецЦикла;

В данном примере мы используем метод СНД("К") (Сальдо Начальное Дебетовое по количеству) или СНД() (по сумме). Обратите внимание, что если запрос был выполнен с одним параметром даты (как сальдо на начало), то для проверки нужно использовать именно «начальные» функции (СНД/СНК), так как обороты внутри запроса могут отсутствовать или не интересовать нас.

Дополнительные рекомендации по оптимизации

Для повышения стабильности и производительности ваших отчетов в 1С 7.7 стоит придерживаться следующих правил:

Подведем итог: появление субконто без остатков в выборке 1С 7.7 — это не баг, а особенность итератора БухгалтерскиеИтоги, который считывает все записи из месячного блока итогов. Использование проверки СНД() <> 0 или СКД() <> 0 внутри цикла является стандартным и наиболее корректным методом разработки профессиональных отчетов на данной платформе.

← На главную