POI在Word文档插入表格,表格中插入图片总结


一、引入相关jar

  1.  
    <dependency>
  2.  
    <groupId>org.apache.poi</groupId>
  3.  
    <artifactId>poi-ooxml</artifactId>
  4.  
    <version>3.10-FINAL</version>
  5.  
    </dependency>

二、原始写法

1)、在首页插入一个表格,单元格中带有图片

  1.  
    public static void writeTblWithImageToDocx_1() {
  2.  
    BufferedReader in = null;
  3.  
    XWPFDocument temp = null;
  4.  
    BufferedOutputStream out = null;
  5.  
    File tempDoc = new File("d:\\test\\test11.docx");
  6.  
    try {
  7.  
    //in = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\test\\2.doc"), "ISO8859_1"));
  8.  
    temp = new XWPFDocument(new BufferedInputStream(new FileInputStream(tempDoc)));
  9.  
    out = new BufferedOutputStream(new FileOutputStream("D:\\test\\test_2.docx"));
  10.  
    XWPFParagraph p = temp.getParagraphArray( 0);
  11.  
    p.setAlignment(ParagraphAlignment.LEFT);
  12.  
    XWPFRun run = p.insertNewRun( 0);
  13.  
     
  14.  
    //表格生成 6行5列.
  15.  
    int rows = 6;
  16.  
    int cols = 5;
  17.  
    XmlCursor cursor = p.getCTP().newCursor();
  18.  
    XWPFTable tableOne = temp.insertNewTbl(cursor);
  19.  
     
  20.  
    //样式控制
  21.  
    CTTbl ttbl = tableOne.getCTTbl();
  22.  
    CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr();
  23.  
    CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
  24.  
    CTJc cTJc = tblPr.addNewJc();
  25.  
    cTJc.setVal(STJc.Enum.forString( "center"));//表格居中
  26.  
    tblWidth.setW( new BigInteger("9000"));//每个表格宽度
  27.  
    tblWidth.setType(STTblWidth.AUTO);
  28.  
     
  29.  
    //表格创建
  30.  
    XWPFTableRow tableRowTitle = tableOne.getRow( 0);
  31.  
    tableRowTitle.getCell( 0).setText("标题");
  32.  
    tableRowTitle.addNewTableCell().setText( "内容");
  33.  
    tableRowTitle.addNewTableCell().setText( "姓名");
  34.  
    tableRowTitle.addNewTableCell().setText( "日期");
  35.  
    tableRowTitle.addNewTableCell().setText( "备注");
  36.  
    for (int i = 1; i < rows; i++) {
  37.  
    XWPFTableRow createRow = tableOne.createRow();
  38.  
    for (int j = 0; j < cols; j++) {
  39.  
    createRow.getCell(j).setText( "我是第"+i+"行,第"+(j+1)+"列");
  40.  
    }
  41.  
    }
  42.  
     
  43.  
    //插入图片测试
  44.  
    XWPFTableRow rowTest = tableOne.getRow( 0);
  45.  
     
  46.  
    XWPFTableCell imageCell = rowTest.getCell( 0);
  47.  
    List<XWPFParagraph> paragraphs = imageCell.getParagraphs();
  48.  
    XWPFParagraph newPara = paragraphs.get( 0);
  49.  
    XWPFRun imageCellRunn = newPara.createRun();
  50.  
    imageCellRunn.addPicture( new FileInputStream("d:/test/1.png"), XWPFDocument.PICTURE_TYPE_PNG, "1.png", Units.toEMU(600), Units.toEMU(300));
  51.  
    run.addBreak();
  52.  
    temp.write(out);
  53.  
    } catch (UnsupportedEncodingException e) {
  54.  
    // TODO 自动生成的 catch 块
  55.  
    e.printStackTrace();
  56.  
    } catch (FileNotFoundException e) {
  57.  
    // TODO 自动生成的 catch 块
  58.  
    e.printStackTrace();
  59.  
    } catch (IOException e) {
  60.  
    // TODO 自动生成的 catch 块
  61.  
    e.printStackTrace();
  62.  
    } catch (InvalidFormatException i) {
  63.  
    // TODO 自动生成的 catch 块
  64.  
    i.printStackTrace();
  65.  
    }
  66.  
    finally {
  67.  
    if (in != null) {
  68.  
    try {
  69.  
    in.close();
  70.  
    } catch (IOException e) {
  71.  
    // TODO 自动生成的 catch 块
  72.  
    e.printStackTrace();
  73.  
    }
  74.  
    }
  75.  
    if (out != null) {
  76.  
    try {
  77.  
    out.close();
  78.  
    } catch (IOException e) {
  79.  
    // TODO 自动生成的 catch 块
  80.  
    e.printStackTrace();
  81.  
    }
  82.  
    }
  83.  
    // tempDoc.deleteOnExit();
  84.  
    }
  85.  
     
  86.  
    System.out.println( "写入完成。。。。。。。。。。。。。。");
  87.  
    }

2)、调用该方法

  1.  
    public static void main(String[] args) {
  2.  
    writeTblWithImageToDocx_1();
  3.  
     
  4.  
    }

3)、结果

WPS:图片是空白的图,无法打开,表格宽度样式无效

Office:无法打开

 

 三、修改代码支持可显示图片

Poi代码bug,亲测3.9和3.10都有该问题,其他版本未测,可自行测试。

修改后代码:

1)、首先重写XWPFDocument,定义构造函数,自定义读取图片的方法

  1.  
    public class CustomXWPFDocument extends XWPFDocument {
  2.  
     
  3.  
    public CustomXWPFDocument(InputStream inputStream) throws IOException {
  4.  
    super(inputStream);
  5.  
    }
  6.  
    public void createPic(String blipId, int id, int width, int height, CTInline inline) {
  7.  
    final int EMU = 9525;
  8.  
    width *= EMU;
  9.  
    height *= EMU;
  10.  
    //String blipId = getAllPictures().get(id).getPackageRelationship().getId();
  11.  
     
  12.  
     
  13.  
    //CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();
  14.  
     
  15.  
     
  16.  
    String picXml = "" +
  17.  
    "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
  18.  
    " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
  19.  
    " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
  20.  
    " <pic:nvPicPr>" +
  21.  
    " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
  22.  
    " <pic:cNvPicPr/>" +
  23.  
    " </pic:nvPicPr>" +
  24.  
    " <pic:blipFill>" +
  25.  
    " <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
  26.  
    " <a:stretch>" +
  27.  
    " <a:fillRect/>" +
  28.  
    " </a:stretch>" +
  29.  
    " </pic:blipFill>" +
  30.  
    " <pic:spPr>" +
  31.  
    " <a:xfrm>" +
  32.  
    " <a:off x=\"0\" y=\"0\"/>" +
  33.  
    " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
  34.  
    " </a:xfrm>" +
  35.  
    " <a:prstGeom prst=\"rect\">" +
  36.  
    " <a:avLst/>" +
  37.  
    " </a:prstGeom>" +
  38.  
    " </pic:spPr>" +
  39.  
    " </pic:pic>" +
  40.  
    " </a:graphicData>" +
  41.  
    "</a:graphic>";
  42.  
     
  43.  
     
  44.  
    //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
  45.  
    XmlToken xmlToken = null;
  46.  
    try {
  47.  
    xmlToken = XmlToken.Factory.parse(picXml);
  48.  
    } catch (XmlException xe) {
  49.  
    xe.printStackTrace();
  50.  
    }
  51.  
    inline.set(xmlToken);
  52.  
    //graphicData.set(xmlToken);
  53.  
     
  54.  
     
  55.  
    inline.setDistT( 0);
  56.  
    inline.setDistB( 0);
  57.  
    inline.setDistL( 0);
  58.  
    inline.setDistR( 0);
  59.  
     
  60.  
     
  61.  
    CTPositiveSize2D extent = inline.addNewExtent();
  62.  
    extent.setCx(width);
  63.  
    extent.setCy(height);
  64.  
     
  65.  
     
  66.  
    CTNonVisualDrawingProps docPr = inline.addNewDocPr();
  67.  
    docPr.setId(id);
  68.  
    docPr.setName( "Picture " + id);
  69.  
    docPr.setDescr( "Generated");
  70.  
    }
  71.  
     
  72.  
     
  73.  
    }

2)、修改首页插入一个表格,单元格中带有图片的相关代码

  1.  
    public static void writeTblWithImageToDocx_2() {
  2.  
    BufferedReader in = null;
  3.  
    CustomXWPFDocument temp = null;
  4.  
    BufferedOutputStream out = null;
  5.  
    File tempDoc = new File("d:\\test\\test11.docx");
  6.  
    try {
  7.  
    //in = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\test\\2.doc"), "ISO8859_1"));
  8.  
    temp = new CustomXWPFDocument(new BufferedInputStream(new FileInputStream(tempDoc)));
  9.  
     
  10.  
    out = new BufferedOutputStream(new FileOutputStream("D:\\test\\test_2.docx"));
  11.  
    XWPFParagraph p = temp.getParagraphArray( 0);
  12.  
    p.setAlignment(ParagraphAlignment.LEFT);
  13.  
    XWPFRun run = p.insertNewRun( 0);
  14.  
     
  15.  
    //表格生成 6行5列.
  16.  
    int rows = 6;
  17.  
    int cols = 5;
  18.  
    XmlCursor cursor = p.getCTP().newCursor();
  19.  
    XWPFTable tableOne = temp.insertNewTbl(cursor);
  20.  
     
  21.  
    //样式控制
  22.  
    CTTbl ttbl = tableOne.getCTTbl();
  23.  
    CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr();
  24.  
    CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
  25.  
    CTJc cTJc = tblPr.addNewJc();
  26.  
    cTJc.setVal(STJc.Enum.forString( "center"));//表格居中
  27.  
    tblWidth.setW( new BigInteger("8000"));//每个表格宽度
  28.  
    tblWidth.setType(STTblWidth.DXA);
  29.  
     
  30.  
    //表格创建
  31.  
    XWPFTableRow tableRowTitle = tableOne.getRow( 0);
  32.  
    tableRowTitle.setHeight( 380);
  33.  
     
  34.  
    tableRowTitle.getCell( 0).setText("标题");
  35.  
    tableRowTitle.addNewTableCell().setText( "内容");
  36.  
    tableRowTitle.addNewTableCell().setText( "姓名");
  37.  
    tableRowTitle.addNewTableCell().setText( "日期");
  38.  
    tableRowTitle.addNewTableCell().setText( "备注");
  39.  
    for (int i = 1; i < rows; i++) {
  40.  
    XWPFTableRow createRow = tableOne.createRow();
  41.  
    for (int j = 0; j < cols; j++) {
  42.  
    createRow.getCell(j).setText( "我是第"+i+"行,第"+(j+1)+"列");
  43.  
    }
  44.  
    }
  45.  
     
  46.  
    //插入图片测试
  47.  
    XWPFTableRow rowTest = tableOne.getRow( 0);
  48.  
     
  49.  
    XWPFTableCell imageCell = rowTest.getCell( 0);
  50.  
    List<XWPFParagraph> paragraphs = imageCell.getParagraphs();
  51.  
    XWPFParagraph newPara = paragraphs.get( 0);
  52.  
    XWPFRun imageCellRunn = newPara.createRun();
  53.  
    String id = temp.addPictureData( new FileInputStream("d:/test/1.png"), XWPFDocument.PICTURE_TYPE_PNG);//添加图片数据
  54.  
     
  55.  
    int id2=temp.getAllPackagePictures().size()+1;
  56.  
     
  57.  
    CTInline ctinline=imageCellRunn.getCTR().addNewDrawing().addNewInline(); //设置段落行
  58.  
    temp.createPic(id,id2, 259, 259,ctinline);//添加图片
  59.  
     
  60.  
    mergeCellsHorizontal(tableOne, 0,0,1);//WPS不支持跨列
  61.  
    mergeCellsVertically(tableOne, 1,1,2);
  62.  
    run.addBreak();
  63.  
    temp.write(out);
  64.  
    } catch (UnsupportedEncodingException e) {
  65.  
    // TODO 自动生成的 catch 块
  66.  
    e.printStackTrace();
  67.  
    } catch (FileNotFoundException e) {
  68.  
    // TODO 自动生成的 catch 块
  69.  
    e.printStackTrace();
  70.  
    } catch (IOException e) {
  71.  
    // TODO 自动生成的 catch 块
  72.  
    e.printStackTrace();
  73.  
    } catch (InvalidFormatException i) {
  74.  
    // TODO 自动生成的 catch 块
  75.  
    i.printStackTrace();
  76.  
    }
  77.  
    finally {
  78.  
    if (in != null) {
  79.  
    try {
  80.  
    in.close();
  81.  
    } catch (IOException e) {
  82.  
    // TODO 自动生成的 catch 块
  83.  
    e.printStackTrace();
  84.  
    }
  85.  
    }
  86.  
    if (out != null) {
  87.  
    try {
  88.  
    out.close();
  89.  
    } catch (IOException e) {
  90.  
    // TODO 自动生成的 catch 块
  91.  
    e.printStackTrace();
  92.  
    }
  93.  
    }
  94.  
    // tempDoc.deleteOnExit();
  95.  
    }
  96.  
     
  97.  
    System.out.println( "写入完成。。。。。。。。。。。。。。");
  98.  
    }

3)、新增合并单元格相关代码

  1.  
    // word跨列合并单元格
  2.  
    public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
  3.  
    for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
  4.  
    XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
  5.  
    if ( cellIndex == fromCell ) {
  6.  
    // The first merged cell is set with RESTART merge value
  7.  
    cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
  8.  
    } else {
  9.  
    // Cells which join (merge) the first one, are set with CONTINUE
  10.  
    cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
  11.  
    }
  12.  
    }
  13.  
    }
  14.  
    // word跨行并单元格
  15.  
    public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
  16.  
    for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
  17.  
    XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
  18.  
    if ( rowIndex == fromRow ) {
  19.  
    // The first merged cell is set with RESTART merge value
  20.  
    cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
  21.  
    } else {
  22.  
    // Cells which join (merge) the first one, are set with CONTINUE
  23.  
    cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
  24.  
    }
  25.  
    }
  26.  
    }

3)、测试结果

WPS:图片已经正常显示,样式依旧无效,合并列也无效,合并行有效

Office:可以正常显示


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM