Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Export QTableView to PDF
Forum Updated to NodeBB v4.3 + New Features

Export QTableView to PDF

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 4 Posters 12.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #1

    I have a QTableView associated with some QStandardItemModel. I want to export it to PDF. I know of two ways:

    1. I could write code to export the data to HTML a la https://stackoverflow.com/questions/3147030/qtableview-printing. I already have code to use that in a QWebEngineView and from there to save to PDF. I would be happy doing it this way if recommended.

    2. I read, say, https://forum.qt.io/topic/30728/how-to-turn-a-qtableview-to-a-pdf

    You write code to paint the data from the model underlying the table view to a QPrinter set to output PDF. How you access the data and format it is entirely up to you.

    but I don't really know how to do that, haven't looked at painting. I don't think I then now how to do the row/column layout that I see in the QTableView if I'm supposed to do the desired layout myself(?). And I certainly don't want to know anything about PDF!

    Is there some very simple way of doing #2, like somehow asking the QTableView to just output to PDF (printer?).

    Or, if I am happy to export my data to an HTML table which I can then throw at QWebEngineView to do the PDF export, is that best for me?

    P.S.
    In case anyone suggests: I came across, say, https://github.com/T0ny0/Qt-Table-Printer

    can print any QAbstractItemModel to pdf or postscript with QPrinter

    I don't know, this might be what approach #2 is all about. I am Python, and not prepared to use/write any C++ library. I don't fancy translating it into Python. Plus, this is my idea of "way too much code", if it isn't real short & sweet I think I'd prefer doing it via HTML myself...

    1 Reply Last reply
    0
    • Gojir4G Offline
      Gojir4G Offline
      Gojir4
      wrote on last edited by
      #2

      Hello,

      You could use the QTextDocument API to reproduce the model content in a table, and then print it as a PDF using QPrinter. I think this code should also work if translated to Python.

       QTextDocument *doc = new QTextDocument;
      doc->setDocumentMargin(10);
      QTextCursor cursor(doc);
      
      cursor.movePosition(QTextCursor::Start);
      
      QTextTable *table = cursor.insertTable(properties.size() + 1, 2, tableFormat);
      QTextTableCell headerCell = table->cellAt(0, 0);
      QTextCursor headerCellCursor = headerCell.firstCursorPosition();
      headerCellCursor.insertText(QObject::tr("Name"), boldFormat);
      headerCell = table->cellAt(0, 1);
      headerCellCursor = headerCell.firstCursorPosition();
      headerCellCursor.insertText(QObject::tr("Value"), boldFormat);
      
      for(int i = 0; i < properties.size(); i++){
          QTextCharFormat cellFormat = i % 2 == 0 ? textFormat : alternateCellFormat;
          QTextTableCell cell = table->cellAt(i + 1, 0);
          cell.setFormat(cellFormat);
          QTextCursor cellCursor = cell.firstCursorPosition();
          cellCursor.insertText(properties.at(i)->name());
      
          cell = table->cellAt(i + 1, 1);
          cell.setFormat(cellFormat);
          cellCursor = cell.firstCursorPosition();
          cellCursor.insertText(properties.at(i)->value().toString() + " " + properties.at(i)->unit());
      }
      
      cursor.movePosition(QTextCursor::End);
      cursor.insertBlock();
      
      //Print to PDF
      QPrinter printer(QPrinter::HighResolution);
      printer.setOutputFormat(QPrinter::PdfFormat);
      printer.setOutputFileName(filename);
      doc->print(&printer);
      
      
      JonBJ 1 Reply Last reply
      2
      • Gojir4G Gojir4

        Hello,

        You could use the QTextDocument API to reproduce the model content in a table, and then print it as a PDF using QPrinter. I think this code should also work if translated to Python.

         QTextDocument *doc = new QTextDocument;
        doc->setDocumentMargin(10);
        QTextCursor cursor(doc);
        
        cursor.movePosition(QTextCursor::Start);
        
        QTextTable *table = cursor.insertTable(properties.size() + 1, 2, tableFormat);
        QTextTableCell headerCell = table->cellAt(0, 0);
        QTextCursor headerCellCursor = headerCell.firstCursorPosition();
        headerCellCursor.insertText(QObject::tr("Name"), boldFormat);
        headerCell = table->cellAt(0, 1);
        headerCellCursor = headerCell.firstCursorPosition();
        headerCellCursor.insertText(QObject::tr("Value"), boldFormat);
        
        for(int i = 0; i < properties.size(); i++){
            QTextCharFormat cellFormat = i % 2 == 0 ? textFormat : alternateCellFormat;
            QTextTableCell cell = table->cellAt(i + 1, 0);
            cell.setFormat(cellFormat);
            QTextCursor cellCursor = cell.firstCursorPosition();
            cellCursor.insertText(properties.at(i)->name());
        
            cell = table->cellAt(i + 1, 1);
            cell.setFormat(cellFormat);
            cellCursor = cell.firstCursorPosition();
            cellCursor.insertText(properties.at(i)->value().toString() + " " + properties.at(i)->unit());
        }
        
        cursor.movePosition(QTextCursor::End);
        cursor.insertBlock();
        
        //Print to PDF
        QPrinter printer(QPrinter::HighResolution);
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(filename);
        doc->print(&printer);
        
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @Gojir4
        Thank you, this is very interesting. (I'm a Qt noob, so didn't know about QTextDocument.)

        This approach is similar in principle to my #1, or https://stackoverflow.com/questions/3147030/qtableview-printing. However, instead of having to directly generate the HTML for my table myself, this is a "structured" document, which offers objects like QTextTable, QTextTableCell etc. which I can use to construct the desired structure. I can then print from that and (hopefully!) get a layout somewhat similar to the QTableView.

        I also note that there is even a http://doc.qt.io/qt-5/qtextdocument.html#toHtml method to get an HTML equivalent (which I presume will use <TABLE> etc.) Which is nice. If I want to, I could even doubtless poke that at QWebEnginePage to use its printToPdf(), which I already employ elsewhere :)

        So --- unless someone else wants to tell me about approach #2 instead --- I think I'll shortly give this a go and see how it comes out...!

        Gojir4G 1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi
          I made a fast version of raw html output here
          https://forum.qt.io/topic/52652/solved-pdf-print-in-multiple-pages/22
          It fast becomes a bit messy if you want to use lots of formatting for good looks.

          Constructing a Text Document using its api should be much cleaner :)

          JonBJ 1 Reply Last reply
          2
          • mrjjM mrjj

            Hi
            I made a fast version of raw html output here
            https://forum.qt.io/topic/52652/solved-pdf-print-in-multiple-pages/22
            It fast becomes a bit messy if you want to use lots of formatting for good looks.

            Constructing a Text Document using its api should be much cleaner :)

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @mrjj
            Thanks. Yep, that was one of the posts I looked at (the stackoverflow one, I mean).

            Using the QTextDocument looks cleaner, and relieves me of producing the HTML, so I'll give that a go. If you're saying it won't look as good as the hand-crafted HTML, I'll think again when I get there.

            Meanwhile neither of you is suggesting #2:

            I read, say, https://forum.qt.io/topic/30728/how-to-turn-a-qtableview-to-a-pdf

            You write code to paint the data from the model underlying the table view to a QPrinter set to output PDF. How you access the data and format it is entirely up to you.

            the "Paint" approach. Which is fine by me! Though now I'm curious as to how you actually do that, as I said I haven't gone near painting?

            mrjjM 1 Reply Last reply
            0
            • JonBJ JonB

              @mrjj
              Thanks. Yep, that was one of the posts I looked at (the stackoverflow one, I mean).

              Using the QTextDocument looks cleaner, and relieves me of producing the HTML, so I'll give that a go. If you're saying it won't look as good as the hand-crafted HTML, I'll think again when I get there.

              Meanwhile neither of you is suggesting #2:

              I read, say, https://forum.qt.io/topic/30728/how-to-turn-a-qtableview-to-a-pdf

              You write code to paint the data from the model underlying the table view to a QPrinter set to output PDF. How you access the data and format it is entirely up to you.

              the "Paint" approach. Which is fine by me! Though now I'm curious as to how you actually do that, as I said I haven't gone near painting?

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by mrjj
              #6

              @JonB
              Hi, im saying it will be easier to make it look better than handcrafted as
              you can use higher level classes like
              http://doc.qt.io/qt-5/qtexttableformat.html
              and CharFormat etc and its easier to scale/resize
              My main point is that constructing HTML was not super nice in terms of readability and
              reuse of html parts/styling etc. Just my feeling though. If you are master at html you might produce cleaner html than my run at it :)

              The pure paint way would to create a drawTable function and something to draw the cell text/style and
              set properties on QPainter for bold font etc. For a very plain table, its not very complex but
              for varying cell widths and extra formatting, you suddenly have to have a small structure to keep that info and
              it slowly becomes big(ger)
              Also, you would have to keep a YPos for newPage handling and other small details.

              For full blown printing, something like
              https://sourceforge.net/projects/qtrpt/
              is also very useful :)

              JonBJ 1 Reply Last reply
              2
              • mrjjM mrjj

                @JonB
                Hi, im saying it will be easier to make it look better than handcrafted as
                you can use higher level classes like
                http://doc.qt.io/qt-5/qtexttableformat.html
                and CharFormat etc and its easier to scale/resize
                My main point is that constructing HTML was not super nice in terms of readability and
                reuse of html parts/styling etc. Just my feeling though. If you are master at html you might produce cleaner html than my run at it :)

                The pure paint way would to create a drawTable function and something to draw the cell text/style and
                set properties on QPainter for bold font etc. For a very plain table, its not very complex but
                for varying cell widths and extra formatting, you suddenly have to have a small structure to keep that info and
                it slowly becomes big(ger)
                Also, you would have to keep a YPos for newPage handling and other small details.

                For full blown printing, something like
                https://sourceforge.net/projects/qtrpt/
                is also very useful :)

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @mrjj said in Export QTableView to PDF:

                The pure paint way would to create a drawTable function and something to draw the cell text/style and
                [...]

                I certainly would not want to do any styling, bolding, drawing at all! I thought the way the guy said that meant that you could somehow just tell QTableView to output to a QPrinter set to output PDF instead of to the screen, and it just handled all the drawing itself?

                mrjjM 1 Reply Last reply
                0
                • JonBJ JonB

                  @Gojir4
                  Thank you, this is very interesting. (I'm a Qt noob, so didn't know about QTextDocument.)

                  This approach is similar in principle to my #1, or https://stackoverflow.com/questions/3147030/qtableview-printing. However, instead of having to directly generate the HTML for my table myself, this is a "structured" document, which offers objects like QTextTable, QTextTableCell etc. which I can use to construct the desired structure. I can then print from that and (hopefully!) get a layout somewhat similar to the QTableView.

                  I also note that there is even a http://doc.qt.io/qt-5/qtextdocument.html#toHtml method to get an HTML equivalent (which I presume will use <TABLE> etc.) Which is nice. If I want to, I could even doubtless poke that at QWebEnginePage to use its printToPdf(), which I already employ elsewhere :)

                  So --- unless someone else wants to tell me about approach #2 instead --- I think I'll shortly give this a go and see how it comes out...!

                  Gojir4G Offline
                  Gojir4G Offline
                  Gojir4
                  wrote on last edited by
                  #8

                  @JonB They are several advantages, at my opinion, to use QTextDocument:

                  • You can preview/edit in a QTextEdit or QPlainTextEdit
                  • You can export content to Open Document Format (Open Office Writer), HTML, PDF and plaintext of course.
                  • You can customize everything (font, table, cells, etc..).
                  1 Reply Last reply
                  2
                  • JonBJ JonB

                    @mrjj said in Export QTableView to PDF:

                    The pure paint way would to create a drawTable function and something to draw the cell text/style and
                    [...]

                    I certainly would not want to do any styling, bolding, drawing at all! I thought the way the guy said that meant that you could somehow just tell QTableView to output to a QPrinter set to output PDF instead of to the screen, and it just handled all the drawing itself?

                    mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @JonB
                    Well you can use render() to make it draw it self to QPrinter
                    This sample paint to pixmap but idea is the same.
                    However, this is only nice if all rows are visible as it wont paint all of them. only how Widget looks on screen.
                    Since QPrinter have much higher DPI/pixels, you can scale the widget to use all space but any rows
                    not visible are not handled.
                    Im not aware of anything else in terms of directly printing the TableView.

                    void MainWindow::PrintWidget(QWidget* widget) {
                    
                      QPixmap pix(widget->size());
                      QPainter painter(&pix);
                      widget->render(&painter);
                      painter.end();
                      QPrinter printer(QPrinter::HighResolution);
                      printer.setOrientation(QPrinter::Landscape);
                      printer.setOutputFormat(QPrinter::PdfFormat);
                      printer.setPaperSize(QPrinter::A4);
                      printer.setOutputFileName("test.pdf"); // will be in build folder
                    
                      painter.begin(&printer);
                      double xscale = printer.pageRect().width() / double(pix.width());
                      double yscale = printer.pageRect().height() / double(pix.height());
                      double scale = qMin(xscale, yscale);
                      painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                                        printer.paperRect().y() + printer.pageRect().height() / 2);
                      painter.scale(scale, scale);
                      painter.translate(-widget->width() / 2, -widget->height() / 2);
                      painter.drawPixmap(0, 0, pix);
                    
                    QTextDocument doc;
                    
                    doc.setHtml("htmlcontent");
                    doc.drawContents(&painter);
                    
                      painter.end();
                    }
                    
                    
                    JonBJ I 2 Replies Last reply
                    3
                    • mrjjM mrjj

                      @JonB
                      Well you can use render() to make it draw it self to QPrinter
                      This sample paint to pixmap but idea is the same.
                      However, this is only nice if all rows are visible as it wont paint all of them. only how Widget looks on screen.
                      Since QPrinter have much higher DPI/pixels, you can scale the widget to use all space but any rows
                      not visible are not handled.
                      Im not aware of anything else in terms of directly printing the TableView.

                      void MainWindow::PrintWidget(QWidget* widget) {
                      
                        QPixmap pix(widget->size());
                        QPainter painter(&pix);
                        widget->render(&painter);
                        painter.end();
                        QPrinter printer(QPrinter::HighResolution);
                        printer.setOrientation(QPrinter::Landscape);
                        printer.setOutputFormat(QPrinter::PdfFormat);
                        printer.setPaperSize(QPrinter::A4);
                        printer.setOutputFileName("test.pdf"); // will be in build folder
                      
                        painter.begin(&printer);
                        double xscale = printer.pageRect().width() / double(pix.width());
                        double yscale = printer.pageRect().height() / double(pix.height());
                        double scale = qMin(xscale, yscale);
                        painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                                          printer.paperRect().y() + printer.pageRect().height() / 2);
                        painter.scale(scale, scale);
                        painter.translate(-widget->width() / 2, -widget->height() / 2);
                        painter.drawPixmap(0, 0, pix);
                      
                      QTextDocument doc;
                      
                      doc.setHtml("htmlcontent");
                      doc.drawContents(&painter);
                      
                        painter.end();
                      }
                      
                      
                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @mrjj
                      Thanks. I think:

                      Well you can use render() to make it draw it self to QPrinter

                      is what I was trying to find, QTableView::render(&QPrinter). I understand your example too. Understand about "it wont paint all of them", have a look at https://stackoverflow.com/a/9784152/489865 for one guy's solution to that.

                      I understand enough now to prefer to go down the QTextDocument route for my situation. I have a table of values here, I'm not tied to the physical QTableView visuals, and I'm already offering export to CSV file, so export to PDF via a structured document with a table is good. Plus I get text or HTML too if I want them :)

                      mrjjM 1 Reply Last reply
                      2
                      • JonBJ JonB

                        @mrjj
                        Thanks. I think:

                        Well you can use render() to make it draw it self to QPrinter

                        is what I was trying to find, QTableView::render(&QPrinter). I understand your example too. Understand about "it wont paint all of them", have a look at https://stackoverflow.com/a/9784152/489865 for one guy's solution to that.

                        I understand enough now to prefer to go down the QTextDocument route for my situation. I have a table of values here, I'm not tied to the physical QTableView visuals, and I'm already offering export to CSV file, so export to PDF via a structured document with a table is good. Plus I get text or HTML too if I want them :)

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @JonB
                        Going QTextDocument also gives free page overflow handling or at least very easy so
                        im sure you wont regret it.

                        1 Reply Last reply
                        2
                        • mrjjM mrjj

                          @JonB
                          Well you can use render() to make it draw it self to QPrinter
                          This sample paint to pixmap but idea is the same.
                          However, this is only nice if all rows are visible as it wont paint all of them. only how Widget looks on screen.
                          Since QPrinter have much higher DPI/pixels, you can scale the widget to use all space but any rows
                          not visible are not handled.
                          Im not aware of anything else in terms of directly printing the TableView.

                          void MainWindow::PrintWidget(QWidget* widget) {
                          
                            QPixmap pix(widget->size());
                            QPainter painter(&pix);
                            widget->render(&painter);
                            painter.end();
                            QPrinter printer(QPrinter::HighResolution);
                            printer.setOrientation(QPrinter::Landscape);
                            printer.setOutputFormat(QPrinter::PdfFormat);
                            printer.setPaperSize(QPrinter::A4);
                            printer.setOutputFileName("test.pdf"); // will be in build folder
                          
                            painter.begin(&printer);
                            double xscale = printer.pageRect().width() / double(pix.width());
                            double yscale = printer.pageRect().height() / double(pix.height());
                            double scale = qMin(xscale, yscale);
                            painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                                              printer.paperRect().y() + printer.pageRect().height() / 2);
                            painter.scale(scale, scale);
                            painter.translate(-widget->width() / 2, -widget->height() / 2);
                            painter.drawPixmap(0, 0, pix);
                          
                          QTextDocument doc;
                          
                          doc.setHtml("htmlcontent");
                          doc.drawContents(&painter);
                          
                            painter.end();
                          }
                          
                          
                          I Offline
                          I Offline
                          imene
                          wrote on last edited by
                          #12

                          @mrjj said in Export QTableView to PDF:

                          QWidget

                          Why #include <QPrinter> is not recognized in my qt5?

                          mrjjM 1 Reply Last reply
                          0
                          • I imene

                            @mrjj said in Export QTableView to PDF:

                            QWidget

                            Why #include <QPrinter> is not recognized in my qt5?

                            mrjjM Offline
                            mrjjM Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @imene

                            Hi
                            you need
                            QT += printsupport

                            in the .pro file

                            1 Reply Last reply
                            2
                            • I Offline
                              I Offline
                              imene
                              wrote on last edited by
                              #14

                              Solved Thanks @mrjj

                              mrjjM 1 Reply Last reply
                              0
                              • I imene

                                Solved Thanks @mrjj

                                mrjjM Offline
                                mrjjM Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                @imene
                                Hi
                                Good :)
                                Please notice that such info is listed in the top of the docs if you
                                run into such a thing again.

                                alt text

                                1 Reply Last reply
                                3
                                • Z ZNohre referenced this topic on

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved