如何使用jtable标头在pdf上保存jtable [英] How to save a jtable on pdf with a jtable header

查看:97
本文介绍了如何使用jtable标头在pdf上保存jtable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能够在pdf上保存一个jtable,但是表没有标题,请帮助我:

I am able to save a jtable on pdf but table comes without a header please help me :

  Document document = new Document(PageSize.A4, 50.0f, 50.0f, 10.0f, 50.0f);
            PdfWriter writer = PdfWriter.getInstance((Document)document,      (OutputStream)new FileOutputStream(this.file + ".pdf"));
              document.open();
               PdfContentByte cb1 = writer.getDirectContent();
         // modules table
              PdfTemplate template = cb1.createTemplate(2480.0f, 3500.0f);   
                  Graphics2D g1 =        template.createGraphics((float)this.jTable_Modules2.getWidth(),        (float)this.jTable_Modules2.getHeight());
   //                       this.jTable_Modules2.getViewport().setBackground(Color.WHITE);
             this.jTable_Modules2.print(g1);
                g1.dispose();
            com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance((PdfTemplate)template);
            image.scalePercent(60.0f);
            image.setAbsolutePosition(80.0f, 458.0f);

             document.add((Element)image);

   document.close();
            JOptionPane.showMessageDialog(null, "Transcript successfully generated");

推荐答案

As shown in this answer you can create a new JTable and pass it as the component to the getImageFromComponent(...) and it's header appart:

java.awt.Image img = getImageFromComponent(table.getTableHeader());
addImageToDocument(img);
img = getImageFromComponent(table);
addImageToDocument(img);

如果您没有将JTable添加到JScrollPane,那么您可以发送JScrollPane,例如:

That in case you don't add the JTable to a JScrollPane, if you do, then you send the JScrollPane, for example:

java.awt.Image img = getImageFromComponent(scrollPane);
addImageToDocument(img);

由您决定如何添加表格...我更喜欢scrollPane版本:)

It's up to you how you add the table... I prefer the scrollPane version :)

另一种方法是遍历JTable的数据并使用PdfPTable.

Another way would be to iterate through the JTable's data and use PdfPTable.

基于此答案,您可以获得以下内容:

Based on this answer you can get something like this:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class JTableToPdf {

    private JFrame frame;
    private JTable table;
    private JButton button;
    private Document document;
    private PdfWriter writer;
    private JScrollPane scrollPane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JTableToPdf().createAndShowGui();
            }
        });
    }

    public void openPdf() throws FileNotFoundException, DocumentException {
        document = new Document(PageSize.A4, 30, 30, 30, 30);
        writer = PdfWriter.getInstance(document, new FileOutputStream("myFile2.pdf"));
        document.open();
    }

    public void closePdf() {
        document.close();
    }

    public void addData(PdfPTable pdfTable) throws DocumentException {
        pdfTable.setHeaderRows(1);

        PdfPCell cell = new PdfPCell(new Paragraph(table.getColumnName(0)));
        cell.setBackgroundColor(new GrayColor(0.7f));
        pdfTable.addCell(cell);

        cell = new PdfPCell(new Paragraph(table.getColumnName(1)));
        cell.setBackgroundColor(new GrayColor(0.7f));
        pdfTable.addCell(cell);

        cell = new PdfPCell(new Paragraph(table.getColumnName(2)));
        cell.setBackgroundColor(new GrayColor(0.7f));
        pdfTable.addCell(cell);

        for (int i = 0; i < table.getRowCount(); i++) {
            for (int j = 0; j < table.getColumnCount(); j++) {
                pdfTable.addCell(table.getModel().getValueAt(i, j).toString());
            }
        }

        document.add(pdfTable);
    }

    public void createAndShowGui() {
        frame = new JFrame("PDF creator");

        int rows = 100;
        int cols = 3;

        String data [][] = new String[rows][cols];

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                data[i][j] = i + "-" + j;
            }
        }

        table = new JTable(data, new String []{"A", "B", "C"});
        table.setBorder(BorderFactory.createLineBorder(Color.RED));
        button = new JButton("Create PDF");

        scrollPane = new JScrollPane(table);

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    PdfPTable pdfTable = new PdfPTable(table.getColumnCount());
                    openPdf();
                    addData(pdfTable);
                    closePdf();
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                } catch (DocumentException e1) {
                    e1.printStackTrace();
                }
            }
        });

//      frame.add(table.getTableHeader(), BorderLayout.NORTH);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

如果您不想在每个页面上重复标题,只需在addData(...)方法的for循环之前删除行即可.

If you don't want the header to repeat on every page just remove the lines before the for loops on addData(...) method.

第三种方法可能是使用JTableprintable方法,但是我在这里没有打印机,我将在稍后处理此示例,因为目前我没有太多时间而且我不确定如何将其与iText集成在一起,所以我必须进行一些搜索...

A third method could be using the JTable's printable methods, but I don't own a printer here, I'll work on this sample later, since I don't have much time at the moment and I'm not sure how to integrate that with iText so I must search a little...

PHEW!创建此结果花了我一段时间,但我认为它很好用(尽管您需要在创建PDF后恢复JTable).

PHEW! It took me a while to create this result, but I think it works nice (though you need to restore the JTable after creating the PDF).

看看代码注释,告诉我是否有帮助.我将PDFPTable的使用和图像方法结合起来使用了这种新方法:

Have a look at the code comments and tell me if this helps. I combined the use of the PDFPTable and the image approach to get to this new approach:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class JTable2Pdf {

    private JFrame frame;
    private JTable table;
    private JButton button;
    private JScrollPane scrollPane;
    private DefaultTableModel model;
    private DefaultTableModel restoreModel;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JTable2Pdf().createAndShowGui();
            }
        });
    }

    public void restoreTableView() {
        table.setModel(restoreModel);
        frame.revalidate();
        frame.repaint();
    }

    public void createAndShowGui() {
        frame = new JFrame("PDF creator");
        int rows = 130;
        int cols = 3;

        String data[][] = new String[rows][cols];

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                data[i][j] = i + "-" + j;
            }
        }

        model = new DefaultTableModel(data, new String[] { "A", "B", "C" });

        restoreModel = new DefaultTableModel(data, new String[] { "A", "B", "C" });

        table = new JTable(model);

        //Just some borders for the table and its header
        table.setBorder(BorderFactory.createLineBorder(Color.RED));
        table.getTableHeader().setBorder(BorderFactory.createLineBorder(Color.RED));

        scrollPane = new JScrollPane(table);

        button = new JButton("Create PDF");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    //We create an instance of pdfCreator and pass our JTable as instance
                    PdfCreator pdfCreator = new PdfCreator(table);

                    //We open the pdf and say we want to repeat the header for each page
                    pdfCreator.openPdf(true);
                    //Then we add the header (if we don't add it first, then the 1st row of the table will be the one repeating over the pages
                    pdfCreator.addImageToTable(pdfCreator.getImageFromComponent(table.getTableHeader()));
                    //Then we add the rows to the PDF
                    pdfCreator.getRowsImage();
                    //Finally we close the PDF
                    pdfCreator.closePdf();
                    //And last we restore the table
                    restoreTableView();

                } catch (DocumentException e1) {
                    e1.printStackTrace();
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });

        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class PdfCreator {

    private JTable table;
    private Document document;
    private PdfWriter writer;
    private boolean isNewPage;
    private PdfPTable pdfTable;

    public PdfCreator(JTable table) {
        this.table = table;
    }

    //This method opens the PDF, repeatHeader if true, adds the header to each page, otherwise it only adds it to the 1st one
    public void openPdf(boolean repeatHeader) throws FileNotFoundException, DocumentException {
        document = new Document(PageSize.A4, 30, 30, 30, 30);
        writer = PdfWriter.getInstance(document, new FileOutputStream("myFile.pdf"));
        pdfTable = new PdfPTable(1);
        if (repeatHeader) {
            pdfTable.setHeaderRows(1);
        }
        pdfTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
        pdfTable.getDefaultCell().setPadding(0);
        document.open();
    }

    //This method closes the document
    public void closePdf() {
        document.close();
    }

    //This method gets the image for each row recursively
    //As this method gets the graphics for the table from 0, 0 to the width and length determined, we need to remove the 1st row of the table
    //each time we go through it and that's why we need to restore the table model later in the code
    public void getRowsImage() throws DocumentException, IOException {
        if (table.getRowCount() > 0) {
            int width = table.getCellRect(0, 0, true).width + table.getCellRect(0, 1, true).width + table.getCellRect(0, 2, true).width;
            int height = table.getCellRect(0, 0, true).height;

            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            table.paint(img.getGraphics());
            DefaultTableModel dtm = (DefaultTableModel) table.getModel();
            System.out.println(table.getRowCount() + " - " + isNewPage);

            dtm.removeRow(0);
            addImageToTable(img);
            getRowsImage();
        } else {
            document.add(pdfTable);
        }
    }

    //This gets the image for the table header and / or any other components you need to add to the PDF
    public java.awt.Image getImageFromComponent(JComponent component) throws DocumentException {
        int width = component.getWidth();
        int height = component.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        component.paint(image.getGraphics());
        return image;
    }

    //This method add the image to a PDFPTable which will be added later to the document
    public void addImageToTable(java.awt.Image img) throws IOException, DocumentException {
        Image image = Image.getInstance(writer, img, 1);
        image.scalePercent(100);
        pdfTable.addCell(image);
        System.out.println("printed!");
    }
}

这些是输出:

第一页带有边框和重复页眉 第二页带边框和重复页眉

1st page with borders and repeating header 2nd page with borders and repeating header

第二页带有边框且不重复页眉

2nd page with borders and not repeating header

第一页无边框且不重复页眉 第二页无边框且不重复页眉

1st page with no borders and not repeating header 2nd page with no borders and not repeating header

我能够通过移动而不删除行来更改上面的代码,这会产生相同的结果,并且仍然可以正常工作,但是您不再需要restoreTableView()方法...只需更改getRowsImage()方法如下:

I was able to change the above code by moving and not removing the rows this produces the same result and it's still working the same, but you no longer need the restoreTableView() method... Just change the getRowsImage() method as follows:

public void getRowsImage() throws DocumentException, IOException {
    if (movedRows < table.getRowCount()) {
        int width = table.getCellRect(0, 0, true).width + table.getCellRect(0, 1, true).width + table.getCellRect(0, 2, true).width;
        int height = table.getCellRect(0, 0, true).height;

        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        table.paint(img.getGraphics());
        DefaultTableModel dtm = (DefaultTableModel) table.getModel();
        System.out.println(table.getRowCount() + " - " + isNewPage);

        dtm.moveRow(0, 0, table.getRowCount() - 1);
        movedRows++;
        addImageToTable(img);
        getRowsImage();
    } else {
        document.add(pdfTable);
    }
}

并声明变量movedRows = 0作为PdfCreator类的类成员:)

And declare a variable movedRows = 0 as a class member for the PdfCreator class :)

这篇关于如何使用jtable标头在pdf上保存jtable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆