📜 ⬆️ ⬇️

Qt: Report output by standard means (or we live without report generators)

Tedious intro with qt 4.8


Recently, a colleague asked about the experience of using report building under Qt (we are beginning to slowly introduce SCADA written in Qt) - because of the task, a very necessary thing. Nobody used the generators (on this platform), but we somehow did the reports without using FastReport and dragging unnecessary applications.

Having rummaged in projects, I found application with reports, widgets for preview (QLabel, QTableView ....). Type of the report "preview":

image

The application window below. Under Qt 5.x, the application itself requires processing, but the reports work:
')


Reports were designed only and only before the application was compiled - there was a task to do quickly (with xml, there was almost no work experience).

Reporter Class - Report Generator


Having read about formatting in Qt, the Reporter class was born (it contains QTextDocument, QTextCursor and methods of working with them). All the work inside the Reporter is to form a QTextDocument, and then print it out on the printer, or display it in QWidget.

For document header:


For content:


The work is carried out with QTextBlockFormat, or QTextTableFormat, actors from the private section

private: int m_iCntTbls; int m_iColCnt; QTextDocument *const m_document; QTextCursor m_cursor; 

Need a title - no problem

 void Reporter::setCompanyDoc(QString str){ //     -   m_cursor.movePosition(QTextCursor::End); if(m_iCntTbls>0){ m_cursor.insertBlock(); m_cursor.insertBlock(); m_cursor.movePosition(QTextCursor::End); } //   QTextBlockFormat blockFrm; blockFrm.setTopMargin(5); blockFrm.setBottomMargin(5); blockFrm.setAlignment(Qt::AlignLeft); blockFrm.setBackground(QBrush(QColor("lightGray"))); //       m_cursor.insertBlock(blockFrm); m_cursor.insertText(str); } 

Similarly, we work with the date and title of the table.

To create the table itself, you must first call the setDataHeader method (QStrignList strLst), the number of columns will be equal to the number of rows in the list:

 void Reporter::setDataHeader(QStringList strLst){ //     -   m_cursor.movePosition(QTextCursor::End); if(m_iCntTbls>0){ m_cursor.insertBlock(); m_cursor.insertBlock(); m_cursor.movePosition(QTextCursor::End); } //      QBrush borderBrush(Qt::SolidPattern); //    QTextTableFormat tableFormat; tableFormat.setCellPadding(5); tableFormat.setCellSpacing(0); tableFormat.setHeaderRowCount(1); tableFormat.setBorderBrush(borderBrush); tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Ridge); tableFormat.setBorder(1); tableFormat.setWidth(QTextLength(QTextLength::PercentageLength,100)); //      m_cursor.insertTable(1,strLst.count(),tableFormat); foreach(QString str, strLst){ m_cursor.insertText(str); m_cursor.movePosition(QTextCursor::NextCell); } m_iCntTbls++; m_iColCnt=strLst.count(); } 

Do not forget at the end to say that there is already at least 1 table and fix the number of columns. And then fill the data:

 void Reporter::addData(QStringList strLst){ //   ,    if(strLst.count()<m_iColCnt){ int iAdd=m_iColCnt-strLst.count(); while(iAdd>0){ iAdd--; strLst<<""; } }else //   -   if(strLst.count()>m_iColCnt){ QMessageBox::critical(0, tr("AddData"), tr("Too many elements to paste wait %1 got %2").arg(m_iColCnt).arg(strLst.count()), QMessageBox::Ok,QMessageBox::Ok ); return; } //  QTextTable *tbl=m_cursor.currentTable(); tbl->appendRows(1); m_cursor.movePosition(QTextCursor::PreviousRow); foreach(QString str, strLst){ m_cursor.movePosition(QTextCursor::NextCell); m_cursor.insertText(str); } } 

Example in action:


We take our class, create an object ( m_reporter ) and push data into it.

  m_reporter->setCompanyDoc(QString::fromLocal8Bit(" ")); m_reporter->setCaptionDoc(QString::fromLocal8Bit("  №0")); strLst<<QString::fromLocal8Bit(" ")<<setStr(" ")<<setStr(" ")<<setStr(" ") <<setStr(" .")<<setStr(" .")<<setStr(""); ..... 

We get something like this:

image

(brought to QDialog with)

  QPainter painter(this); QRect rec(0,0,this->width(),this->height()); m_reporter->getTextDoc()->drawContents(&painter,rec); 

To print, call the Reporter :: printDoc (QPrinter) method.

Summary


For a quick solution of a particular problem, standard Qt tools are suitable from which you can build suitable tools, but this method is not applicable to provide a quality product.

The main disadvantage is the need to compile a project containing a report when changing the document format, adding new reports, etc. Thank you all who read.

PS github.com/AlexisVaBel/QtReport.git (everything you need to play around).

Source: https://habr.com/ru/post/308126/


All Articles