Как подсчитать количество документов в печатной форме 1С 7.7 и рассчитать средний чек

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Приветствуем вас, уважаемые разработчики! В процессе создания внешних отчетов и печатных форм на платформе 1С:Предприятие 7.7 часто возникает необходимость не просто вывести список документов (например, расходных накладных) за определенный период, но и рассчитать сводные аналитические показатели. Одним из таких важных показателей является средний чек, который рассчитывается как отношение общей суммы продаж к физическому количеству совершенных сделок (накладных).

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

Метод 1. Простой подсчет с помощью счетчика в цикле вывода секций

Давайте начнем с самого простого и очевидного решения, которое отлично подходит, если средний чек и общее количество накладных должны выводиться в самом конце отчета — в секции «Подвал».

Суть метода заключается в создании специальной переменной-счетчика, которая будет увеличивать свое значение на единицу при каждой итерации цикла вывода документов. Рассмотрим, как это выглядит на практике в модуле формы отчета.

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

Разберем алгоритм по шагам:

  1. Перед началом цикла инициализируем переменную СчетчикНакладных и переменную для накопления общей суммы ОбщаяСумма, присвоив им начальное значение 0.
  2. Внутри цикла, перед или сразу после вывода очередной секции документа, увеличиваем наш счетчик на единицу. Также аккумулируем сумму документов.
  3. После завершения цикла рассчитываем средний чек, разделив общую накопленную сумму на значение счетчика документов.
  4. Выводим секцию «Подвал», передавая туда уже рассчитанные итоговые показатели.

Посмотрим на пример программного кода, реализующего данный подход:


// Создаем объект Таблица для формирования печатной формы
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Накладные");

// Инициализируем переменные-счетчики
СчетчикНакладных = 0;
ОбщаяСумма = 0;

// Выводим шапку печатной формы
Таб.ВывестиСекцию("Шапка");

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

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

// Защищаем код от деления на ноль и рассчитываем средний чек
Если СчетчикНакладных > 0 Тогда
    СреднийЧек = Окр(ОбщаяСумма / СчетчикНакладных, 2);
Иначе
    СреднийЧек = 0;
КонецЕсли;

// Выводим подвал печатной формы с итогами
Таб.ВывестиСекцию("Подвал");
Таб.Показать("Реестр накладных");

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

Метод 2. Расчет показателей до начала печати с помощью Таблицы Значений

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

Наиболее гибким и профессиональным инструментом для этого в 1С 7.7 является объект ТаблицаЗначений. Мы можем сначала быстро собрать все нужные документы во временную таблицу, узнать их общее количество и сумму, рассчитать средний чек, вывести «Шапку» с готовыми цифрами, а затем запустить цикл печати по строкам таблицы значений.

Рассмотрим подробнее этот алгоритм на примере:


// 1. Создаем и заполняем Таблицу Значений (ТЗ)
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Документ");
ТЗ.НоваяКолонка("Сумма");

ВыборкаДок = СоздатьОбъект("Документ.РасходнаяНакладная");
ВыборкаДок.ВыбратьДокументы(ДатаНачала, ДатаКонца);

Пока ВыборкаДок.ПолучитьДокумент() = 1 Цикл
    Если ВыборкаДок.Проведен() = 1 Тогда
        ТЗ.НоваяСтрока();
        ТЗ.Документ = ВыборкаДок.ТекущийДокумент();
        ТЗ.Сумма = ВыборкаДок.Итог("Сумма");
    КонецЕсли;
КонецЦикла;

// 2. Получаем общее количество накладных и их общую сумму
ВсегоНакладных = ТЗ.КоличествоСтрок();
ОбщаяСуммаПродаж = ТЗ.Итог("Сумма");

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

// 4. Начинаем вывод на печать
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("МакетСШапкой");

// Теперь переменные ВсегоНакладных и СреднийЧек заполнены
// и будут успешно выведены внутри секции "Шапка"!
Таб.ВывестиСекцию("Шапка");

// Выводим строки из подготовленной Таблицы Значений
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    ТекущийДокумент = ТЗ.Документ;
    СуммаДокумента = ТЗ.Сумма;
    Таб.ВывестиСекцию("Строка");
КонецЦикла;

Таб.ВывестиСекцию("Подвал");
Таб.Показать("Реестр");

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

Метод 3. Получение количества документов через встроенный язык запросов 1С 7.7

Если выборка документов в вашем отчете строится с использованием механизма запросов 1С 7.7, то подсчет количества документов можно переложить на плечи самого SQL-движка или внутреннего оптимизатора базы данных. Для этого применяется встроенная агрегатная функция Счётчик().

Проанализируем пример построения такого запроса:


Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = 
"//{{ЗАПРОС(РеестрНакладных)
|Период с ДатаНачала по ДатаКонца;
|Док = Документ.РасходнаяНакладная.ТекущийДокумент;
|СуммаДок = Документ.РасходнаяНакладная.ИтогСумма;
|Группировка Док;
|Функция ВсегоНакладных = Счётчик(Док);
|Функция ОбщаяСумма = Сумма(СуммаДок);
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
КонецЕсли;

// Извлекаем общие итоги из запроса до начала обхода группировок
КоличествоДокументов = Запрос.ВсегоНакладных;
СуммарныйОборот = Запрос.ОбщаяСумма;

Если КоличествоДокументов > 0 Тогда
    СреднийЧек = Окр(СуммарныйОборот / КоличествоДокументов, 2);
Иначе
    СреднийЧек = 0;
КонецЕсли;

// Теперь мы можем смело выводить секцию "Шапка" со средним чеком!
Таб = СоздатьОбъект("Таблица");
Таб.ВывестиСекцию("Шапка");

Пока Запрос.Группировка("Док") = 1 Цикл
    // Выводим строки отчета
    Таб.ВывестиСекцию("Строка");
КонецЦикла;

Таб.ВывестиСекцию("Подвал");
Таб.Показать();

Этот способ является наиболее производительным при работе с большими объемами данных, так как платформа оптимизирует подсчет на уровне базы данных.

Важный подводный камень: Строки товаров против заголовков документов

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

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

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


СчетчикНакладных = 0;
ПредыдущийДокумент = "";

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

Пока ВыборкаСтрок.Группировка("СтрокаТовара") = 1 Цикл
    ТекущийДок = ВыборкаСтрок.ДокументСсылка;
    
    // Проверяем, изменился ли документ по сравнению с предыдущей строкой
    Если ТекущийДок <> ПредыдущийДокумент Тогда
        СчетчикНакладных = СчетчикНакладных + 1;
        ПредыдущийДокумент = ТекущийДок; // Запоминаем новый документ
    КонецЕсли;
    
    // Выводим строку товара на печать
    Таб.ВывестиСекцию("СтрокаТовара");
КонецЦикла;

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

Определение физического количества строк на листе печатной формы

В завершение рассмотрим еще одну смежную задачу, которую часто путают с подсчетом документов. Иногда под «количеством строк в секции» подразумевают физическую высоту получившейся таблицы на листе бумаги (например, чтобы динамически рассчитать разбиение по страницам или настроить высоту колонтитулов).

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


// Получаем текущую высоту таблицы (количество физических строк в макете)
ТекущаяВысота = Таб.ВысотаТаблицы();

// Мы можем использовать это для добавления принудительного разрыва страницы
Если ТекущаяВысота > 50 Тогда
    Таб.НоваяСтраница();
КонецЕсли;

Метод ВысотаТаблицы() возвращает актуальное число строк сформированного табличного документа на текущий момент исполнения кода, что позволяет гибко управлять компоновкой печатного листа.

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

← На главную