Welcome, Guest. Please login or register.
Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - LCoetzer

Pages: [1]
2
Hi

I ran into another issue whereby in the report footer for the last group I could not access the group variable value.
The reason was that I had reached eof and the m_eof variable was not being updated in the prior method.

I implemented the following simple fix in the CallbackDatasource header file to update the m_eof value:

    bool prior(){ if (m_currentRow !=-1) { m_currentRow--; if (m_rowCount != -1) m_eof = false; return true; } else return false; }
    void undoPrior() { m_currentRow++; if (m_rowCount != -1) m_eof = !(m_rowCount>0 && m_currentRow<m_rowCount); }

This fix will however only work when using the rowCount method and not the older changePos signal slot method.
For it to work with the signal slot method there would have to be a new "Prior" ChangePosType added.

Regards
   Louis Coetzer

3
Hi

Thank you for updating with all my changes.

I attached my report and two report pdfs, one with the line commented out and one NOT.
I cannot post a data sample because I get the data from my objects in code.
This is my code: This is prototype code to test the reporting library, so it's not necessarily the best way to do it.

void ReportManager::limeReceiver(LimeReport::CallbackInfo info, QVariant &data)
{
    switch (info.dataType)
    {
        /*//For Traversal method
        case LimeReport::CallbackInfo::DataType::IsEmpty:
        {
            data = m_dataAttributes.isEmpty();
            m_curRowIndex = 0;
            break;
        }
        case LimeReport::CallbackInfo::DataType::HasNext:
        {
            data = m_curRowIndex < (m_dataAttributes.size() - 1);
            break;
        }*/
        case LimeReport::CallbackInfo::DataType::ColumnHeaderData:
        {
            data = m_headers.at(info.index);
            break;
        }
        case LimeReport::CallbackInfo::DataType::ColumnData:
        {
            int columnIndex = m_headers.indexOf(info.columnName);

            /*//For Traversal method
            if (m_curRowIndex < m_dataAttributes.size())
            {
                //Attribute * attribute = m_dataAttributes.at(m_curRowIndex).at(columnIndex); //Traversal method
                QVariant attribute = m_dataAttributes.at(m_curRowIndex).at(columnIndex); //Traversal method
                //if (attribute != nullptr)
                    data = attribute->getValueString();
            }*/

            //Specify row count method
            if ((columnIndex >= 0) && (info.index >= 0) && (info.index < m_dataAttributes.size()))
                data = m_dataAttributes.at(info.index).at(columnIndex);
            break;
        }
        case LimeReport::CallbackInfo::DataType::ColumnCount:
        {
            data = m_headers.size();
            break;
        }
        //For row count method
        case LimeReport::CallbackInfo::DataType::RowCount:
        {
            data = m_dataAttributes.size();
            break;
        }
        default: break;
    }
}

//For Traversal method
void ReportManager::limeTransversal(const LimeReport::CallbackInfo::ChangePosType &type, bool &result)
{
    switch (type)
    {
        case LimeReport::CallbackInfo::ChangePosType::First:
        {
            m_curRowIndex = 0;
            if (m_dataAttributes.size() > 0)
            {
                result = true;
            }
            else
                result = false;

            break;
        }
        case LimeReport::CallbackInfo::ChangePosType::Next:
        {
            m_curRowIndex++;
            if (m_curRowIndex < (m_dataAttributes.size()))
            {
                result = true;
            }
            else
            {
                //m_curRowIndex--;
                result = false;
            }

            break;
        }
    }
}

bool ReportManager::printTestReport_LimeReport(bool pdf)
{
    bool success = false;
    LimeReport::ReportEngine *limeReport = new LimeReport::ReportEngine(this);

//Load Template
    QString fileName = ":/Reports/VehicleRefueling_LimeReport.lrxml";

    //Connect signals
    LimeReport::ICallbackDatasource *limeDataCallback = limeReport->dataManager()->createCallbackDatasource(QString("limeData"));
    connect(limeDataCallback, SIGNAL(getCallbackData(LimeReport::CallbackInfo,QVariant&)), this, SLOT(limeReceiver(LimeReport::CallbackInfo,QVariant&)));
    //connect(limeDataCallback, SIGNAL(changePos(LimeReport::CallbackInfo::ChangePosType,bool&)), this, SLOT(limeTransversal(LimeReport::CallbackInfo::ChangePosType,bool&)));

    //Get Data
    loadData();
    limeReport->loadFromFile(fileName);

    //Print
    QString pdfFileName = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).first() + QString("/LimeReport_Report.pdf");
    if (pdf)
    {
        success = limeReport->printToPDF(pdfFileName);
        QDesktopServices::openUrl(QUrl(pdfFileName));
    }
    else
        success = limeReport->printReport();


    //Disconnect Signals
    disconnect(limeDataCallback, SIGNAL(getCallbackData(LimeReport::CallbackInfo,QVariant&)), this, SLOT(limeReceiver(LimeReport::CallbackInfo,QVariant&)));
    //disconnect(limeDataCallback, SIGNAL(changePos(LimeReport::CallbackInfo::ChangePosType,bool&)), this, SLOT(limeTransversal(LimeReport::CallbackInfo::ChangePosType,bool&)));
    //delete limeDataCallback; Don't delete it here. The library allready deletes it in it's destructor

//Clean up and return
    delete limeReport;
    return success;
}

void ReportManager::loadData()
{
    Kind *fuelLogKind = KindManager::getSingleton()->get(QString("Fuel Log"));
    QList<Thing*> *fuelLogs = fuelLogKind->getThings();

    //Sort it
    struct {
        bool operator()(Thing* a, Thing* b) const
        {
            Thing *vehicleA = a->getAttribute("Vehicle")->getValueThing();
            Thing *vehicleB = b->getAttribute("Vehicle")->getValueThing();
            int comparisonResult = vehicleA->getValueDisplayString("Name").compare(vehicleB->getValueDisplayString("Name"));
            if (comparisonResult < 0)
                return true;
            else if (comparisonResult > 0)
                return false;
            else
            {
                QDateTime dateTimeA = a->getAttribute("Date Time")->getValueTimestamp();
                QDateTime dateTimeB = b->getAttribute("Date Time")->getValueTimestamp();
                return dateTimeA < dateTimeB;
            }
        }
    } customLess;
    std::sort(fuelLogs->begin(), fuelLogs->end(), customLess);

    m_curRowIndex = -1;
    m_headers.clear();
    m_headers << "vehicleName" << "Month" << "Amount" << "Cost" << "Economy" << "vehicleEconomy";

    m_dataAttributes.clear();
    int count = 0;
    int index = 0;
    QDecNumber prevOdometer;
    int vehicleLogCount = 0;
    QDecNumber vehicleEconomy = 0;
    int vehicleLogStart = 0;
    foreach (Thing* aThing, (*fuelLogs))
    {
        count++;
        QList<QVariant> record;

        Thing *vehicle = aThing->getAttribute("Vehicle")->getValueThing();
        record.append(vehicle->getValueDisplayString("Name"));
        if ((count > 1) && (m_dataAttributes.at(index - 1).at(0).toString().compare((record.at(0).toString())) != 0))
            count = 1;

        record.append(aThing->getValueDisplayString("Date Time"));
        record.append(aThing->getValueDisplayString("Quantity"));
        record.append(aThing->getValueDisplayString("Amount"));

        //Append economy
        QDecNumber distanceTravelled;
        if (count == 1)
        {
            record.append(QVariant());//aThing->getAttribute("Economy"));
            if (index > 0) //If just finished a vehicle
            {
                //Set the vehicle average economy for the previous vehicle
                if (vehicleLogCount > 0)
                {
                    QVariant newValue = QVariant(QString((vehicleEconomy / vehicleLogCount).toString()));
                    for (int i = vehicleLogStart; i < index; i++)
                    {
                        QList<QVariant> prevRecord = m_dataAttributes.at(i);
                        prevRecord.replace(5, newValue);
                        m_dataAttributes.replace(i, prevRecord);
                    }
                }
            }
            vehicleLogCount = 0;
            vehicleEconomy = 0;
            vehicleLogStart = index;
        }
        else
        {
            distanceTravelled = aThing->getAttribute("Odometer")->getValueDecimal() - prevOdometer;
            QString refuelType = aThing->getValueDisplayString("Refuel Type");
            if (refuelType.compare("Full") == 0)
            {
                QDecNumber economy = distanceTravelled / aThing->getAttribute("Quantity")->getValueDecimal();
                if (economy != QDecNumber(0))
                {
                    vehicleLogCount++;
                    vehicleEconomy += economy;
                }

                record.append(QVariant(QString(economy.toString()))); //QVariant::fromValue(getValueDecimal());
            }
            else if (refuelType.compare("Partial with Fuel Level"))
            {
                record.append(QVariant());//aThing->getAttribute("Economy"));
            }
            else
            {
                record.append(QVariant());//aThing->getAttribute("Economy"));
            }
        }
        record.append(QVariant());//vehicleEconomy;

        m_dataAttributes.append(record);

        prevOdometer = aThing->getAttribute("Odometer")->getValueDecimal();
        index++;
    }

    //Set the vehicle average economy for the last vehicle
    if (vehicleLogCount > 0)
    {
        QVariant newValue = QVariant(QString((vehicleEconomy / vehicleLogCount).toString()));
        for (int i = vehicleLogStart; i < index; i++)
        {
            QList<QVariant> prevRecord = m_dataAttributes.at(i);
            prevRecord.replace(5, newValue);
            m_dataAttributes.replace(i, prevRecord);
        }
    }
}



Thanks and Regards
    Louis Coetzer

4
Hi

Since the last build v 1.4.14 I am unable to build the library if I exclude Zint by commenting out
CONFIG += zint
inside common.pri

Regards
    Louis

5
Hi

The last Group footer seems to get displayed twice, but with empty values the second time.
I'm using v 1.4.14

In void ReportRender::renderDataBand(BandDesignIntf *dataBand)

The first time it gets rendered from within renderGroupHeader on line 553
The second time it gets rendered by renderGroupFooter(dataBand) on line 560

...
            renderGroupHeader(dataBand, bandDatasource, false);
            if (dataBand->tryToKeepTogether()) closeDataGroup(dataBand);
            firstTime = false;
        }

        m_reprintableBands.removeOne(dataBand->bandHeader());

        renderGroupFooter(dataBand);
...

Commenting out renderGroupFooter(dataBand); on line 560, worked for me, but I don't know if it will cause issues for other scenarios.

Regards
    Louis


6
Discussion | Обсуждение / Horizontal layout breaks scripts
« on: June 13, 2017, 11:43:06 AM »
Hi

I have some text boxes that uses SUM and AVG functions in my group and data footers.
As soon as I put them in a "Horizontal Layout" then they stop working and I get the invalid formula error displayed in my report.

Is this the correct forum for reporting issues such as this??

Regards
    Louis


8
Apologies. The undoPrior() function should return void.

9
Hi

Thank you for a great library.

I am using a callback data source and could not get the groups to display correctly.
Only the first group displayed correctly.
For the incorrect groups: (In my test data I actually only had two)
Depending what I did in my code it either didn't display the last line or it used the second line's data for the first line as well or it added the group heading a second time after the group.
I experienced problems using both the changePos slot mechanism as well as using the recordCount method.

In the end, unless I'm doing things wrong, I found some bugs in the library. When I made some small changes in the library, everything worked correctly. (Both methods)

May I please recommend the following changes on v 1.4.12:

void ReportRender::renderGroupHeader(BandDesignIntf *parentBand, IDataSource* dataSource, bool firstTime)
{
    foreach(BandDesignIntf* band,parentBand->childrenByType(BandDesignIntf::GroupHeader)){
        IGroupBand* gb = dynamic_cast<IGroupBand*>(band);
        if (gb&&gb->isNeedToClose(m_datasources)){
            if (band->childBands().count()>0){
//I changed this line
                bool didGoBack = dataSource->prior();
                foreach (BandDesignIntf* subBand, band->childrenByType(BandDesignIntf::GroupHeader)) {
                    foreach(BandDesignIntf* footer, subBand->childrenByType(BandDesignIntf::GroupFooter)){
                        renderBand(footer, 0);
                        closeDataGroup(subBand);
                    }
                }

                foreach (BandDesignIntf* footer, band->childrenByType(BandDesignIntf::GroupFooter)) {
                    renderBand(footer, 0, StartNewPageAsNeeded);
                }

//I changed this part
                if (didGoBack)
                {
                    //New Method to undo prior... Alternatively pass in bool isUndoPrior into next()
                    dataSource->undoPrior();
                    //dataSource->next(); //Also emit changePos, which it should not at this point
                }
            }
.....


In IDataSource I added this method:
    virtual bool undoPrior() = 0;

In ModelToDataSource I added this method:
    bool undoPrior() {m_curRow++;}

In CallbackDatasource I added this method:
    bool undoPrior() {m_currentRow++;}


and to prevent my datasource to be read beyond it's limits, I made this change:

QVariant CallbackDatasource::data(const QString& columnName)
{
    QVariant result;
    if (!eof())
    {
        CallbackInfo info;
        info.dataType = CallbackInfo::ColumnData;
        info.columnName = columnName;
        info.index = m_currentRow;
        emit getCallbackData(info,result);
    }
    return result;
}


I also noticed that in the implementation of "bool ModelToDataSource::prior()" the variable m_curRow would be decremented twice if eof. That seems wrong but I didn't change it because I'm not using a ModelToDataSource and would not be able to test it properly.

I also attached the source files for diffing.

Thanks and Regards
    Louis Coetzer





Pages: [1]