Как настроить сквозную нумерацию записей в отчете СКД с обнулением при смене верхнего уровня группировки?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Представим ситуацию: у нас есть отчет с двумя уровнями группировки, например, «Производство» и «ОКОФ». Нам необходимо, чтобы детальные записи, относящиеся к определенному «Производству», нумеровались по порядку, но при переходе к следующему «Производству» нумерация начиналась снова с 1.

Стандартное поведение СистемныеПоля.НомерПоПорядкуВГруппировке заключается в нумерации строк внутри той группировки, в которую оно непосредственно добавлено. Если мы добавим его к детальным записям, оно будет нумеровать их сквозным образом, либо внутри самой последней, самой детальной группировки. Это не всегда удовлетворяет нашим требованиям, когда нам нужен контекст нумерации по более высокому уровню иерархии.

Выясним, как мы можем добиться желаемого результата, используя возможности СКД и, при необходимости, программные корректировки.

Решение 1: Использование функций Уровень() и ВычислитьВыражение() в вычисляемых полях СКД

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

  1. Создание вычисляемого поля: Перейдите в настройки СКД на вкладку «Вычисляемые поля» и создайте новое поле. Назовем его, например, «НомерСтрокиПоГруппировке».
  2. Определение выражения: В выражении для этого поля мы можем прописать логику, которая будет проверять текущий уровень группировки и в зависимости от этого рассчитывать номер.

Рассмотрим, как это работает:

Давайте посмотрим на гипотетический пример выражения для двух уровней группировки ("Производство" и "ОКОФ"):

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

ВычислитьВыражение("НомерПоПорядку", "Производство")

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

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

Если бы нам понадобилась более сложная иерархическая нумерация, например, "1.1", "1.2", "2.1", "2.2", мы могли бы комбинировать эти функции:


Выбор
    Когда Уровень() = 0 Тогда Строка(НомерПоПорядкуВГруппировке())
    Когда Уровень() = 1 Тогда 
        Строка(ВычислитьВыражение("НомерПоПорядкуВГруппировке()", "Производство")) 
        + "." 
        + Строка(НомерПоПорядкуВГруппировке())
    Иначе ""
Конец

Однако в нашем конкретном случае, когда требуется просто сброс нумерации при смене верхнего уровня, достаточно использовать ВычислитьВыражение("НомерПоПорядку", "ИмяВышестоящейГруппировки") для детальных записей.

Решение 2: Решение через вычисляемое поле с явным указанием контекста группировки

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

  1. Создайте вычисляемое поле: Как и в предыдущем случае, добавьте новое вычисляемое поле, например, «НомерПППоПроизводству».
  2. Задайте выражение: В качестве выражения укажите следующее: ВычислитьВыражение("НомерПоПорядку", "Производство") Где "Производство" — это имя поля, по которому вы осуществляете верхний уровень группировки в настройках СКД.
  3. Добавьте поле в выбранные поля: Убедитесь, что это новое вычисляемое поле добавлено в выбранные поля отчета или в соответствующую группировку, если вы хотите его вывести.

Как это работает? Функция ВычислитьВыражение фактически говорит СКД: «Вычисли сквозной номер по порядку ("НомерПоПорядку") для каждой строки, но каждый раз, когда значение поля "Производство" меняется, начни отсчет заново с 1». Таким образом, вы получаете нумерацию детальных записей, которая сбрасывается при смене верхнего уровня группировки «Производство».

Важный аспект: Для корректной работы этого механизма, поле, указанное в качестве контекста (в нашем случае «Производство»), должно присутствовать в настройках группировок СКД, даже если сама эта группировка не выводится визуально в отчете.

Решение 3: Использование пользовательских полей и их доступность в макетах

Если вы используете пользовательские макеты для оформления отчета, стандартные системные поля типа НомерПоПорядкуВГруппировке могут быть недоступны напрямую или вести себя непредсказуемо. Однако, если вы создали вычисляемое поле в СКД с нужной логикой (как описано в Решении 1 или Решении 2), это пользовательское поле будет доступно для вывода в вашем макете.

  1. Создайте вычисляемое поле в СКД: Выполните шаги из Решения 1 или Решения 2, создав поле типа «Поле-выражение» с вашей логикой нумерации.
  2. Используйте это поле в макете: Откройте ваш пользовательский макет СКД. Ваше новое вычисляемое поле (например, «НомерПППоПроизводству») появится в списке доступных полей, и вы сможете вставить его в нужную ячейку макета для вывода.

Это позволяет сохранить гибкость настройки логики нумерации средствами СКД и одновременно использовать преимущества пользовательских макетов для сложного оформления.

Решение 4: Программная постобработка отчета (более сложный путь)

В самых сложных случаях, когда требуется очень специфическая иерархическая нумерация или логика, которую трудно реализовать средствами выражений СКД, можно прибегнуть к программной постобработке отчета. Этот подход требует большего объема кода и понимания структуры объекта «РезультатКомпоновкиДанных».

  1. Добавьте вычисляемое выражение: В СКД создайте простое вычисляемое поле, например, «Счетчик», без сложной логики. Его значение по умолчанию может быть 0 или пустым.
  2. В макете укажите новое поле: В вашем пользовательском макете для детальных записей или нужной группировки добавьте ячейку для вывода этого поля «Счетчик».
  3. Программное заполнение номеров: После того как отчет будет сформирован (обычно в модуле формы отчета или в модуле менеджера, если это типовая подсистема), мы получаем программный доступ к табличному документу отчета.

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

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

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

Заключение

Задача нумерации записей в отчете СКД с обнулением при смене верхнего уровня группировки является достаточно распространенной. Мы видим, что стандартное поле НомерПоПорядкуВГруппировке не всегда дает желаемый результат. Наиболее эффективными и гибкими методами являются использование вычисляемых полей в СКД в сочетании с функцией ВычислитьВыражение("НомерПоПорядку", "ИмяВышестоящейГруппировки"). Этот подход позволяет добиться требуемой логики, минимизируя необходимость в программном коде и максимально используя возможности самой СКД. При этом, если используются пользовательские макеты, вычисляемые поля будут легко доступны для вывода. Программная постобработка остается вариантом для очень специфичных и сложных сценариев.

← На главную