# Формирование отчёта

Отчёт

## Подготовка

Функция Report::prepare() вызвывает соответствующую функцию для всех страниц отчёта (в текушей реализации, страница может быть только одна). В качестве одного из параметров передаётся источник данных RpDataStorage *dataStorage, который содержит набор всех данных используемые отчётом (данные из баз данных, параметры отчёта - страница, кол-во страниц, константы и т.д.).

RpPage::prepare(RpDataStorage *dataStorage, QString *lastError) - подготовка страницы, вызывает фунции подготовки бендов входящих в страницу. В текущей реализации сначала вызывается подготовка заголовка страницы (m_header), затем - подготовка одного или нескольких бендов основных данных (m_mainData).

RpBand::prepare(RpDataStorage *dataStorage, QString *lastError) - подготовка бенда, вызывает подготовку полей данных (m_memo) входящих в бенд.

bool RpMemo::prepare(RpDataStorage *dataStorage, QString *lastError) - подготовка поля данных. RpMemo содержит объект m_part, который при генерации отчёта должен "вычислять" выражение заданное в m_data.
В текущей реализации, на данном этапе, происходит преобразование выражения m_data в список объектов класса RpDataAbstract, представляющие из себя текст и/или вычисляемые выражения. Каждый из таких объектов возвращает строку текса, которые складываются в строку для отображения в отчёте.

## Подготовка отчёта за один или два прохода

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

За первый проход мы определяем значения всех функций и внешних данных (из базы данных и т.п.). А во время второго прохода формируем текст поля данных.

Соответсвенно в случае двухпроходного отчета, нам необходимо "кешировать данные" для каждого memoFix.

Не оформлено...

1. На этапе подготовки (prepare), объекты для расчёта выражений (Calc...), при необходимости (зависит от класса) сохраняют ссылку на источник данных (RpDataStorage) у себя.
2. Данные объекты не должны знать о том какой сейчас проход, они просто запрашивают данные.
3. Для второго прохода данные кеширует источник данных. Из этого следует что он должен знать номер текущего прохода построения отчёта.

## Первый проход

Объект класса Report хранит сформированный отчёт в виде сформированных страниц m_pageFix(RpPageFixList). Report::generate() - процедура формирования отчёта, делает следующее:

1. Если необходимо, уничтожает ранее сформированные страницы.
2. Подготавливает источник данных к формированию отчёта, передавая определённые пользователем параметры - m_dataStorage->init(&m_parameter).
3. Подготавливает к началу формирования отчёта страницу - m_page->init(m_dataStorage).
4. Циклически, пока не превышено максимальное количество страниц, вызывается функция формирования очередной страницы - m_page->generate(m_dataStorage, m_lastError).

Формирование страницы осуществляет объект класса RpPage - RpPage::generate(RpDataStorage *dataStorage, QString &errorStr).

Порядок формирования:

1. Формируем заголовок страницы, если он есть.
2. Проверяем есть ещё данные в источнике данных связанных с текущим бендом. Если данных нет, то переходим к следующиему бенду с данными. При завершении обработки всех бендов, заканчиваем формирование страницы.
3. Аналогично проверяем оставшееся место для формирования очередной строки. Если места недостаточно, то заканчиваем формирования страницы.
4. Для текущего бенда с информацией, формируем строки md->generate(rect, dataStorage, pg, errorStr).
   Где rect - оставшаяся область для рисования на текущей странице, после формирования очередной строки она уменьшаестя.

Формирование бендов разных типов отличаются только определением места расположения, основная работа производится функцией RpBand::generate(drawRect, dataStorage, pageFix, errorStr). Для всех RpMemo принадлежащих бенду создаётся memoFix (зафиксированное поле данных) определяестя местоположение на странице, и генерируется тест с текущими данными запроса.

Формирование текста поля данных.

m_text = m_memo->part()->text(errorStr)

m_text - сформированный текст. m_memo->part() - объект отвечающий за формирование готового результата.