...

Создание отчета при помощи таблиц контекста конструктора форм

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем pushkarev, 11 фев 2022.

  1. pushkarev

    pushkarev Эксперт

    Всем привет!
    В этом посте я расскажу про один прием создания отчетов с помощью elma365.
    В elma365 есть готовый виджет Таблица в разделе отчеты, но он позволяет только делать выборку по одному приложению, но этого не всегда достаточно и иногда требуется выборка данных из нескольких приложений или же сгруппированные результаты. Для создания таких выборок я предлагаю использовать контекст конструктора форм и поле с типом данных Таблица.
    Идея решения достаточно простая, но может быть не очевидна. Для этого мы будем использовать конструктор форм страницы. Контекст используемый в конструкторе форм не сохраняется в базе данных и его можно использовать для вычисления промежуточных данных, которые нужны только на странице и которые после закрытия страницы нигде не будут сохраняться. Алгоритм построения такого решения следующий:
    1. Создаем в контексте страницы свойство типа таблица. И добавляем в таблицу все необходимые для отображения поля. И размещаем поле типа таблица на форме и делаем его только для чтения.
    2. Добавляем в контекст поля, которые будут служить параметрами для формирования отчета. И размещаем их над нашим табличным полем.
    3. Добавляем кнопку сформировать отчет. В ней указываем серверный сценарий, который будет осуществлять выборку и обработку данных, а после добавлять в контекст в табличное поле строки с получившимися данными.
    Покажу данное решение на примере. У меня есть приложение для работы по задачами и учета трудозатрат (системные задачи мне не подошли, т.к. нужна была работа с задачами на канбан доске и учет трудозатрат, а в стандартных задачах этого сейчас нет). Замечу, что у одной задачи много записей о фактических трудозатратах. Вот скриншот, как выглядит такая задача:
    [​IMG]
    Для отчета я создал отдельную страницу. В конструкторе форм создал таблицу и добавил туда столбцы: Контрагент, Задача, плановые трудозатраты и фактические трудозатраты. И добавил отображение порядкового номера. Так же добавил 2 поля для фильтрации: "период с" и "период по". Разместил это все на форме и добавил кнопку формирования отчета. Логика хранения данных следующая: у задачи есть поле контрагент, а так же плановые трудозатраты, а вот фактические трудозатраты нужно считать на основе другого приложения: Трудозатраты (оно ссылается на задачу), в котором помимо факта трудозатрат так же хранится дата, когда они возникли. Логика отчета получается следующей: необходимо отобрать все фактические трудозатраты за указанный период и сгруппировать их по задачам, отобразив сумму фактических трудозатрат в соответствующем поле. То есть мы в отчете увидим задачи, у которых были фактические трудозатраты за указанный период, и увидим сумму трудозатрат по ним за указанный период. В результате отчет имеет следующий вид:
    [​IMG]
    Наполнение таблицы отчета происходит программно. Сначала создаю новый объект таблицы, чтобы при формировании отчета несколько раз, не оставались результаты прошлых расчетов. Затем делаю выборку всех трудозатрат за указанный период с помощью метода search. А далее уже в цикле перебираем все трудозатраты и добавляем их в таблицу. Если ранее по данной задаче уже добавили запись в таблицу, то мы находим такую запись и прибавляем к имеющимся фактическим трудозатратам текущие, таким образом получая агрегацию по ним. Код выглядит следующим образом:
    Спойлер: Код формирования отчета
    Код:
    
    async function filter_labor_costs(): Promise<void> {
        
    Context.data.test_report Context.fields.test_report.create();
        var 
    labor_costs await Namespace.app.test_labor_costs.search()
            .
    where((f,g) => g.and(f.date.gte(Context.data.start_period!), f.date.lte(Context.data.end_period!))).all();
        for (
    let row of labor_costs)
        {
            const 
    work_task_item await row.data.work_task!.fetch();
            const 
    exist_row Context.data.test_report.find(tr => tr.work_task!.id == work_task_item!.id);
            if (
    exist_row == undefined)
            {
                const 
    new_row Context.data.test_report!.insert();
                
    new_row.contractor work_task_item.data.contractor!;
                
    new_row.labor_costs_plan work_task_item.data.plan_labor_costs_count!;
                
    new_row.labor_costs_fact row.data.labor_hours!;
                
    new_row.work_task work_task_item;
            } else {
                if (
    exist_row!.labor_costs_fact != undefined)
                {
                    
    exist_row!.labor_costs_fact exist_row!.labor_costs_fact row.data.labor_hours!;
                } else {
                    
    exist_row!.labor_costs_fact row.data.labor_hours!;
                }
            }
        }
    }

    Благодарю за внимание! Надеюсь кому-то данный прием оказался полезен. Если кто-то знает способ формирования подобных отчетов получше, прошу поделиться в комментариях, буду очень признателен.
    Последнее редактирование: 25 окт 2022
  2. v.sabirov

    v.sabirov Участник

    Здравствуйте. Очень интересная статься. Пытаюсь сделать подобное. Но не отображается часть картинок в вашем посте.
  3. pushkarev

    pushkarev Эксперт

    Обновил картинки, видимо был какой-то сбой, который удалил ранее прикрепленные картинки.
  4. denis.khveshchenik

    denis.khveshchenik Активный участник

    @pushkarev Здравствуйте, интересный подход, спасибо! А существует ли возможность затем выгрузить сформированную таблицу в Excel?
  5. pushkarev

    pushkarev Эксперт

    Есть простой способ, выделить табличку и ctrl+c ctrl+v, в эксель, я таким сейчас пользуюсь. Но если делать полноценную реализацию, то пока вижу только способ делать отдельный процесс, там заполнять тот же блок с данными, и потом делать генерацию документа по шаблону в excel. Но минус в том что в базе будут все отчеты оставаться.
  6. e.duchinskaya

    e.duchinskaya Новичок

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

    lexam Активный участник

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

    Вложения: