Как выбрать корреспондирующие счета в запросе бухгалтерских итогов в 1С 7.7

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

При разработке отчетов и обработок в среде 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью анализа корреспонденции счетов. Работа с механизмом бухгалтерских итогов в «семерке» имеет ряд специфических особенностей. Одна из наиболее распространенных проблем — когда цикл обхода корреспондирующих счетов ВыбратьКорСчета() визуально написан правильно, но при выполнении кода программа просто «проскакивает» его, не выдавая никаких результатов и не выводя ошибок. В рамках этой статьи мы подробно разберем, почему возникает эта проблема, как устроен механизм расчета сквозных оборотов и как правильно построить обход итогов с учетом аналитики.

Выясняем причину: почему выборка корсчетов оказывается пустой?

Проанализируем исходный код, с которым столкнулся автор темы. В его алгоритме инициализируется объект БухгалтерскиеИтоги, накладывается фильтр по субконто «Плательщик», а затем вызывается метод ВыполнитьЗапрос():


БИ = СоздатьОбъект("БухгалтерскиеИтоги");
БИ.ИспользоватьСубконто("Плательщик");
БИ.ВключатьСубсчета(1, 1);
БИ.ВыполнитьЗапрос(НачДата, КонДата, Счет);
БИ.ВыбратьСчета();
Пока БИ.ПолучитьСчет() = 1 Цикл
    БИ.ВыбратьКорСчета(1); 
    Пока БИ.ПолучитьКорСчет() = 1 Цикл
        Сообщить("Наз==");
    КонецЦикла;    
КонецЦикла;

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

ВыполнитьЗапрос(НачалоПериода, КонецПериода, Счет, КоррСчет, Валюта, ТипИтогов, Периодичность, ТипСуммы)

Особое внимание следует уделить шестому параметру — ТипИтогов. По умолчанию, если этот параметр не указан явным образом, платформа принимает его равным 1. Давайте разберем, что означают значения этого параметра:

  1. 1 (Остатки и обороты по счету в целом) — в этом режиме система оптимизирует SQL-запрос (или обращение к DBF-таблицам) и рассчитывает только остатки и совокупные обороты по счетам. Шахматная структура (обороты в разрезе корреспондирующих счетов) при этом не рассчитывается. Метод ВыбратьКорСчета() в таком случае всегда возвращает 0.
  2. 2 (Обороты между счетами) — рассчитываются исключительно обороты между счетами (шахматка). Остатки по счетам при таком запросе будут недоступны.
  3. 3 (И остатки, и обороты между счетами) — универсальный, но наиболее ресурсоемкий режим. Рассчитываются как конечные/начальные остатки, так и вся сетка корреспонденции счетов.

Для того чтобы решить проблему пустой выборки корсчетов, нам необходимо явно указать тип итогов 2 или 3 при вызове запроса.

Решение №1: Исправление метода ВыполнитьЗапрос

Рассмотрим, как должен выглядеть правильный вызов метода. Если в отчете нам нужны только обороты корреспонденции (без вывода начальных и конечных остатков по основному счету), мы можем использовать тип итогов 2. Если нужны и остатки, и корсчета — выбираем 3.

Посмотрим на пример правильной инициализации запроса:


// Передаем шестым параметром значение 3 для получения полной картины
Если БИ.ВыполнитьЗапрос(НачДата, КонДата, Счет, , , 3) = 0 Тогда
    Предупреждение("Не удалось выполнить запрос по бухгалтерским итогам!");
    Возврат;
EndIf;

Обратите внимание на пустые запятые. Мы пропускаем параметры КоррСчет и Валюта, оставляя их по умолчанию, но обязательно позиционируем шестой параметр.

Решение №2: Разрешение конфликта иерархии обхода (Группировки запроса)

Вторая важная деталь в коде автора — строка БИ.ИспользоватьСубконто("Плательщик");. Когда мы накладываем фильтр по субконто или просто указываем его использование в запросе, структура выборки объекта БухгалтерскиеИтоги кардинально меняется. Итоги начинают строиться с учетом иерархии аналитики.

Если мы объявили использование субконто, но в коде пытаемся сразу выполнить обход по счетам (БИ.ВыбратьСчета()), платформа может вернуть пустой результат или отработать некорректно. Нам нужно определиться со стратегией обхода данных. Разберем два сценария:

Сценарий А: Нам действительно нужен разрез по плательщикам. В этом случае перед обходом счетов мы обязаны открыть цикл по субконто. Посмотрим на правильную структуру вложенности циклов:


БИ = СоздатьОбъект("БухгалтерскиеИтоги");
БИ.ИспользоватьСубконто("Плательщик");
БИ.ВыполнитьЗапрос(НачДата, КонДата, Счет, , , 3);

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

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


БИ = СоздатьОбъект("БухгалтерскиеИтоги");
// Строку ИспользоватьСубконто удалили
БИ.ВыполнитьЗапрос(НачДата, КонДата, Счет, , , 3);

БИ.ВыбратьСчета();
Пока БИ.ПолучитьСчет() = 1 Цикл
    Сообщить("Счет: " + БИ.Счет);
    
    БИ.ВыбратьКорСчета(1);
    Пока БИ.ПолучитьКорСчет() = 1 Цикл
        Сообщить("--- КорСчет: " + БИ.КорСчет);
    КонецЦикла;
КонецЦикла;

Решение №3: Корректное обращение к видам субконто

Проанализируем замечание из сообщения 6 форума. Автор исходного кода использовал строковый идентификатор вида субконто: БИ.ИспользоватьСубконто("Плательщик");.

Платформа 1С 7.7 позволяет передавать имя субконто строкой, однако этот подход таит в себе скрытые угрозы:

Для повышения надежности кода настоятельно рекомендуется передавать вид субконто через предопределенное системное значение ВидыСубконто:


// Надежный способ обращения к метаданным
БИ.ИспользоватьСубконто(ВидыСубконто.Контрагенты);

Если на счете настроено несколько видов субконто (например, 1-й разрез — Контрагенты, 2-й разрез — Договоры), мы можем позиционировать их последовательно:


БИ.ИспользоватьСубконто(ВидыСубконто.Контрагенты, , 1); // Первое субконто (только по группам)
БИ.ИспользоватьСубконто(ВидыСубконто.Договоры, , 1);     // Второе субконто

Как правильно получать суммы и обороты по корсчетам?

Часто начинающие программисты допускают ошибку, пытаясь получить сумму проводки внутри цикла по корсчетам с помощью стандартных методов БИ.ДО() (Дебетовый оборот) или БИ.КО() (Кредитовый оборот). Эти методы внутри цикла по корсчетам будут продолжать возвращать общий оборот по основному счету, игнорируя конкретную корреспонденцию.

Для получения финансовых показателей именно в разрезе корреспондирующих счетов необходимо использовать специализированные методы объекта БухгалтерскиеИтоги:

Рассмотрим практический пример вывода оборотов в таблицу:


БИ = СоздатьОбъект("БухгалтерскиеИтоги");
СчетАнализа = СчетПоКоду("51"); // Расчетный счет
БИ.ВыполнитьЗапрос(НачДата, КонДата, СчетАнализа, , , 3);

БИ.ВыбратьСчета();
Пока БИ.ПолучитьСчет() = 1 Цикл
    БИ.ВыбратьКорСчета(1);
    Пока БИ.ПолучитьКорСчет() = 1 Цикл
        СуммаПоступления = БИ.КорДО(); // Дт 51 - Кт КорСчет
        СуммаСписания    = БИ.КорКО(); // Дт КорСчет - Кт 51
        
        Если (СуммаПоступления > 0) Или (СуммаСписания > 0) Тогда
            Сообщить("Корреспонденция счетом " + БИ.КорСчет.Код + ":");
            Сообщить("   Поступило: " + Шаблон("[СуммаПоступления] руб."));
            Сообщить("   Списано:   " + Шаблон("[СуммаСписания] руб."));
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Анализ субконто на стороне корреспондирующего счета

В сложных бухгалтерских отчетах иногда требуется узнать не просто код корреспондирующего счета, но и субконто, которое закреплено за этим корсчетом. Например, при списании материалов на затраты (Дт 20 - Кт 10) нам может потребоваться узнать, на какую конкретно номенклатурную группу (субконто счета 20) ушли материалы с кредита счета 10.

Для решения этой задачи в 1С 7.7 существует метод ИспользоватьКорСубконто(). Его использование аналогично обычному субконто, но применяется оно к корреспондирующей стороне:


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

БИ.ВыполнитьЗапрос(НачДата, КонДата, СчетПоКоду("10"), , , 3);

БИ.ВыбратьСубконто(1);
Пока БИ.ПолучитьСубконто(1) = 1 Цикл
    // Обходим наши материалы
    БИ.ВыбратьСчета();
    Пока БИ.ПолучитьСчет() = 1 Цикл
        БИ.ВыбратьКорСчета();
        Пока БИ.ПолучитьКорСчет() = 1 Цикл
            // Теперь мы можем обойти аналитику корсчета!
            БИ.ВыбратьКорСубконто(1);
            Пока БИ.ПолучитьКорСубконто(1) = 1 Цикл
                Сообщить("Материал: " + БИ.Субконто(1) + 
                         " списан на подразделение: " + БИ.КорСубконто(1) + 
                         " Сумма: " + БИ.КорКО());
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;
КонецЦикла;

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

Резюме и чек-лист для разработчика

Если у вас не выбираются корсчета в 1С 7.7, проверьте следующие моменты по нашему чек-листу:

  1. Указан ли шестой параметр в ВыполнитьЗапрос? Он должен быть равен 2 или 3.
  2. Если в запросе объявлен метод ИспользоватьСубконто(), убедитесь, что вы делаете выборку субконто (ВыбратьСубконто() и цикл ПолучитьСубконто()) перед тем, как переходить к счетам и корсчетам.
  3. Правильно ли указаны виды субконто? Избегайте строковых литералов, используйте системный справочник метаданных ВидыСубконто.
  4. Используются ли правильные функции получения сумм (КорДО() / КорКО()) внутри цикла по корреспондирующим счетам?

Соблюдение этих простых правил проектирования запросов к бухгалтерским итогам гарантирует быструю и корректную работу ваших отчетов без лишней нагрузки на базу данных 1С:Предприятия 7.7.

← На главную