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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Если мы используем стандартное условие Счет В ИЕРАРХИИ (&МассивСчетов), виртуальная таблица 1С вернет нам остатки в разрезе конечных субсчетов (например, 10.01, 10.02, 10.05), на которых непосредственно велся учет. Но наша цель — получить свернутую сумму по счету 10, если именно он был передан в массиве параметров. Простое условие Счет В (&МассивСчетов) также не сработает, ведь на самих счетах-родителях (счетах верхнего уровня) прямых проводок обычно нет, и запрос вернет пустой результат.

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

Способ 1. Использование временной таблицы соответствия (оптимальный по лаконичности)

Поскольку структура плана счетов в любой конфигурации 1С имеет строго ограниченную глубину вложенности (обычно это 2–3 уровня, например: Счет -> Субсчет -> Субсубсчет), мы можем прямо в запросе построить карту соответствия каждого субсчета его целевому родителю из переданного массива.

Для этого мы сначала выберем все счета, входящие в иерархию переданного массива, и с помощью конструкции ВЫБОР КОГДА определим для каждого субсчета его «главного» родителя. Затем мы соединим полученную таблицу с виртуальной таблицей остатков.

Рассмотрим пример такого запроса:


ВЫБРАТЬ
    Хозрасчетный.Ссылка КАК Субсчет,
    ВЫБОР
        КОГДА Хозрасчетный.Ссылка В (&МассивСчетов)
            ТОГДА Хозрасчетный.Ссылка
        КОГДА Хозрасчетный.Родитель В (&МассивСчетов)
            ТОГДА Хозрасчетный.Родитель
        КОГДА Хозрасчетный.Родитель.Родитель В (&МассивСчетов)
            ТОГДА Хозрасчетный.Родитель.Родитель
        ИНАЧЕ НЕОПРЕДЕЛЕНО
    КОНЕЦ КАК ЦелевойСчет
ПОМЕСТИТЬ ВТ_СоответствиеСчетов
ИЗ
    ПланСчетов.Хозрасчетный КАК Хозрасчетный
ГДЕ
    Хозрасчетный.Ссылка В ИЕРАРХИИ(&МассивСчетов)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_СоответствиеСчетов.ЦелевойСчет КАК Счет,
    СУММА(ХозрасчетныйОстатки.СуммаОстаток) КАК Сумма
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет В ИЕРАРХИИ (&МассивСчетов), , ) КАК ХозрасчетныйОстатки
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СоответствиеСчетов КАК ВТ_СоответствиеСчетов
    ПО ХозрасчетныйОстатки.Счет = ВТ_СоответствиеСчетов.Субсчет

СГРУППИРОВАТЬ ПО
    ВТ_СоответствиеСчетов.ЦелевойСчет

Преимущества данного подхода:

  1. Запрос остается единым, его удобно использовать внутри динамических списков или в простых отчетах.
  2. Высокая скорость работы: виртуальная таблица остатков сразу фильтруется по индексу благодаря условию В ИЕРАРХИИ в параметрах.
  3. Результат получается сразу сгруппированным до нужных счетов верхнего уровня.

Способ 2. Динамическое построение текста запроса через ОБЪЕДИНИТЬ ВСЕ

Если производительность СУБД критична, а количество счетов в массиве параметров относительно невелико, лучшим решением с точки зрения скорости выполнения будет динамическая генерация текста запроса.

Для СУБД выполнение нескольких простых точечных запросов с последующим их объединением через ОБЪЕДИНИТЬ ВСЕ происходит быстрее и проще, чем обработка сложного логического условия В ИЕРАРХИИ со списком значений. План запроса в этом случае получается максимально простым и эффективным.

Проанализируем пример кода на встроенном языке 1С, реализующий этот метод:


ТекстыЗапроса = Новый Массив;
Для Индекс = 0 По МассивСчетов.Количество() - 1 Цикл
    ИмяПараметра = "Счет_" + Индекс;
    ТекстБлока = 
        "ВЫБРАТЬ
        |   &" + ИмяПараметра + " КАК Счет,
        |   ЕСТЬNULL(СУММА(Остатки.СуммаОстаток), 0) КАК Сумма
        |ИЗ
        |   РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет В ИЕРАРХИИ (&" + ИмяПараметра + "), , ) КАК Остатки";
    ТекстыЗапроса.Добавить(ТекстБлока);
КонецЦикла;

ТекстЗапроса = СтрСоединить(ТекстыЗапроса, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС);

Запрос = Новый Запрос(ТекстЗапроса);
Для Индекс = 0 По МассивСчетов.Количество() - 1 Цикл
    Запрос.УстановитьПараметр("Счет_" + Index, МассивСчетов[Индекс]);
КонецЦикла;

Результат = Запрос.Выполнить();

Преимущества данного подхода:

  1. Максимальное быстродействие на уровне базы данных SQL.
  2. Полная универсальность: глубина иерархии плана счетов в вашей конфигурации может быть абсолютно любой — алгоритм не привязан к количеству уровней вложенности.

Способ 3. Использование итогов запроса (ТОЛЬКО ИЕРАРХИЯ)

Платформа 1С обладает мощным встроенным механизмом расчета иерархических итогов. Мы можем выбрать детальные записи по всем субсчетам, а затем поручить платформе самостоятельно рассчитать итоги по иерархии счетов "снизу вверх".

Давайте посмотрим на пример запроса с расчетом итогов:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет КАК Счет,
    ХозрасчетныйОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет В ИЕРАРХИИ (&МассивСчетов), , ) КАК ХозрасчетныйОстатки
ИТОГИ
    СУММА(СуммаОстаток)
ПО
    Счет ТОЛЬКО ИЕРАРХИЯ

При программном обходе результатов такого запроса во встроенном языке 1С мы используем обход по группировкам. На самом верхнем уровне выборки окажутся именно те счета, которые мы передали в параметре &МассивСчетов. При этом суммы по ним будут автоматически просуммированы с учетом всех их субсчетов.

Пример обхода на встроенном языке:


ВыборкаСчет = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Счет");
Пока ВыборкаСчет.Следующий() Цикл
    // Здесь мы получаем наши переданные счета-родители и свернутую по ним сумму
    Сообщить("Счет: " + ВыборкаСчет.Счет + " - Сумма: " + ВыборкаСчет.СуммаОстаток);
    
    // Подчиненные элементы (детальные субсчета) мы просто не обходим
КонецЦикла;

Преимущества данного подхода:

  1. Простой и лаконичный текст запроса без сложных соединений и условий выбора.
  2. Платформа 1С берет на себя всю математику расчета иерархических связей.

Способ 4. Настройка в Системе компоновки данных (СКД)

Если вы разрабатываете отчет на СКД, то писать сложные конструкции во встроенном языке или использовать виртуальные таблицы соединений вообще не потребуется. СКД умеет работать с бухгалтерской иерархией «из коробки».

Разберем по шагам, как настроить СКД для решения нашей задачи:

  1. В наборе данных запроса пишем самый простой выбор остатков: ВЫБРАТЬ Счет, СуммаОстаток ИЗ РегистрБухгалтерии.Хозрасчетный.Остатки с параметром фильтрации Счет В ИЕРАРХИИ (&МассивСчетов).
  2. На вкладке "Настройки" в структуре отчета добавляем группировку по полю Счет.
  3. Нажимаем правой кнопкой мыши на созданную группировку, заходим в ее свойства и в поле "Тип дополнения" или в настройках отображения выбираем тип группировки "Иерархия" (или "Только иерархия").
  4. При необходимости накладываем системный отбор в настройках СКД, чтобы скрыть из итогового отчета детальные записи (субсчета), оставив видимыми только корневые элементы. СКД сама построит дерево и свернет все ресурсы на верхний уровень.

Преимущества данного подхода:

  1. Идеально подходит для любых пользовательских отчетов.
  2. Минимум ручного кодинга и высокая гибкость кастомизации под требования пользователей.

Каждый из рассмотренных методов имеет свои преимущества. Для динамических списков и простых экранных форм лучше всего подойдет Способ 1 с временной таблицей соответствия. В высоконагруженных системах, где важна каждая миллисекунда работы СУБД, рекомендуется использовать динамический сбор запроса из Способа 2. Для построения сложных интерактивных отчетов незаменимым инструментом остается СКД (Способ 4).

← На главную