Как получить конечное сальдо по счету, контрагенту и договору в 1С 7.7?

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

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

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

Постановка задачи и анализ структуры данных

Представим ситуацию: у нас есть отчёт «Реестр договоров». В каждой строке этого отчета фигурирует контрагент и документ договора. Нам необходимо добавить колонку «Остаток» (конечное сальдо). Учет взаиморасчетов ведется, например, на активно-пассивных субсчетах счета 76 (например, 76.К.1 «Личные сбережения» или 76.К.4 «Займы»).

Для решения этой задачи в платформе 1С 7.7 используется специализированный объект БухгалтерскиеИтоги. Однако здесь разработчики часто сталкиваются с неочевидной проблемой сопоставления типов данных аналитики (субконто) и производительности базы данных при расчете остатков в цикле.

Способ 1. Получение остатка напрямую по конкретному контрагенту и договору

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


Функция ПолучитьОстатокПоДоговору(ТекущийДоговор, КонДата)
    
    // Определяем счет в зависимости от свойств договора
    Счет = ?(ТекущийДоговор.Вид = Перечисление.ПС_ВидыДоговоров.ДоговорВзноса, СчетПоКоду("76.К.1"), СчетПоКоду("76.К.4"));
    
    // Определяем контрагента (первое субконто)
    Субконто1 = ТекущийДоговор.Контрагент.ТекущийЭлемент();
    Субконто2 = ТекущийДоговор; 
    
    БухИт = СоздатьОбъект("БухгалтерскиеИтоги");
    БухИт.Актуальность(1);
    БухИт.ПериодМ(КонДата);
    
    // Получаем сальдо конечное дебетовое и кредитовое
    ОстатокДт = БухИт.СКД(Счет, , , Субконто1, Субконто2);
    ОстатокКт = БухИт.СКК(Счет, , , Субконто1, Субконто2);
    
    // Возвращаем разницу (или конкретное сальдо в зависимости от логики счета)
    Возврат ОстатокКт - ОстатокДт;
КонецФункции

В данном коде мы используем методы СКД() (Сальдо Конечное Дебетовое) и СКК() (Сальдо Конечное Кредитовое) объекта БухгалтерскиеИтоги. В качестве параметров мы передаем счет учета, тип суммы, валюту (если учет валютный) и конкретные значения субконто.

Важная проблема: Несовпадение типов данных в субконто

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

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

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

Неэффективный способ (полный перебор в цикле):


// Такой код будет сильно замедлять работу отчета при большом количестве договоров!
Спр = СоздатьОбъект("Справочник.Договоры");
Спр.ИспользоватьВладельца(Договор.Контрагент);
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
    Если Спр.ТекущийЭлемент().ПС_Документ = Договор Тогда
        Субконто2 = Спр.ТекущийЭлемент();
        Прервать;
    КонецЕсли;
КонецЦикла;

Эффективный способ (поиск по реквизиту):

Для того чтобы избежать медленного перебора справочника вручную, воспользуемся методом НайтиПоРеквизиту(). Предварительно убедитесь, что в конфигураторе у реквизита ПС_Документ справочника «Договоры» установлено свойство «Сортировка».


Спр = СоздатьОбъект("Справочник.Договоры");
Спр.ИспользоватьВладельца(Договор.Контрагент);
// Третий параметр "0" означает поиск в пределах подчинения владельцу
Если Спр.НайтиПоРеквизиту("ПС_Документ", Договор, 0) = 1 Тогда
    Субконто2 = Спр.ТекущийЭлемент();
Иначе
    Субконто2 = ПолучитьПустоеЗначение("Справочник.Договоры");
КонецЕсли;

Использование метода НайтиПоРеквизиту() работает мгновенно за счет индексации таблиц базы данных СУБД, что кардинально повышает скорость открытия отчета.

Способ 2. Оптимальное решение для больших отчетов (один запрос к итогам)

Несмотря на то, что точечное обращение к итогам в функции (Способ 1) работает просто, у него есть огромный минус. Если в вашем отчете будет 500 строк, система выполнит 500 отдельных обращений к таблицам бухгалтерских итогов на диске. В файловом варианте базы данных (DBF) это вызовет заметные задержки, а на крупных базах отчет может просто «зависнуть».

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

Разберем по шагам реализацию этого механизма:

Шаг 1. Инициализация и выполнение запроса перед циклом вывода отчета:


// Создаем список счетов, по которым нам нужны остатки
СписокСчетов = СоздатьОбъект("СписокЗначений");
СписокСчетов.ДобавитьЗначение(СчетПоКоду("76.К.1"));
СписокСчетов.ДобавитьЗначение(СчетПоКоду("76.К.4"));

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

// Выполняем один запрос на конечную дату
БухИт.ВыполнитьЗапрос( , КонДата, СписокСчетов);

Шаг 2. Выборка остатков внутри цикла вывода строк отчета:

В процессе обхода строк нашего отчета (например, при чтении строк справочника или документа) мы не создаем новые объекты бухгалтерских итогов. Вместо этого мы используем позиционирование по результатам уже выполненного запроса БухИт с помощью третьего параметра методов ПолучитьСчет() и ПолучитьСубконто():


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

Использование третьего параметра в методе ПолучитьСубконто(НомерСубконто, , Значение) позволяет мгновенно переместить указатель выборки на нужного контрагента и договор. Это увеличивает скорость работы отчета в десятки и сотни раз по сравнению с индивидуальными запросами в цикле.

Способ 3. Выгрузка бухгалтерских итогов в Таблицу Значений

Еще один удобный и гибкий метод, который часто используют разработчики 1С 7.7, — это выгрузка результатов запроса бухгалтерских итогов во временную таблицу значений (ТЗ) с последующим поиском в ней.

Рассмотрим, как это реализовать:

  1. Выполняем один общий запрос к бухгалтерским итогам на конечную дату.
  2. Используем метод ВыгрузитьИтоги() для создания таблицы значений с готовыми остатками.
  3. При формировании строк отчета выполняем поиск по колонкам таблицы значений.

Посмотрим на пример кода:


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

// Выгружаем итоги в Таблицу Значений
ТЗ_Остатки = СоздатьОбъект("ТаблицаЗначений");
// Второй параметр "1" означает выгрузку детальных строк по субконто
БухИт.ВыгрузитьИтоги(ТЗ_Остатки, 1, 1);

// Для ускорения поиска можно проиндексировать или свернуть таблицу значений
// ТЗ_Остатки будет содержать колонки: Субконто1, Субконто2, Счет, СКД, СКК и др.

Теперь в цикле вывода отчета нам достаточно выполнить быстрый поиск по нашей таблице значений ТЗ_Остатки:


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

Метод с выгрузкой в ТЗ особенно удобен тем, что вы можете производить с полученными данными любые математические и сортировочные операции стандартными средствами таблиц значений 1С 7.7.

Резюме и рекомендации

Подводя итог, выделим ключевые правила работы с остатками по счетам и аналитике в 1С 7.7:

Применение этих простых правил гарантирует, что ваши отчеты будут работать быстро и безошибочно даже на больших объемах данных в крупных информационных базах 1С 7.7.

← На главную