当前位置:   article > 正文

java POI导出多张图片到表格(占位符方式)_java pdf 导出 多张图片使用同一个占位符

java pdf 导出 多张图片使用同一个占位符

        最近做的项目,需要将一些信息导出到word中。在网上找了好多解决方案,现在将这几天的总结分享一下。

        目前来看,java导出word大致有6种解决方案:

1:Jacob是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁。使用Jacob自带的DLL动态链接库,并通过JNI的方式实现了在Java平台上对COM程序的调用。DLL动态链接库的生成需要windows平台的支持。该方案只能在windows平台实现,是其局限性。

2:Apache POI包括一系列的API,它们可以操作基于MicroSoft OLE 2 Compound Document Format的各种格式文件,可以通过这些API在Java中读写Excel、Word等文件。他的excel处理很强大,对于word还局限于读取,目前只能实现一些简单文件的操作,不能设置样式。

3:Java2word是一个在java程序中调用 MS Office Word 文档的组件(类库)。该组件提供了一组简单的接口,以便java程序调用他的服务操作Word 文档。 这些服务包括: 打开文档、新建文档、查找文字、替换文字,插入文字、插入图片、插入表格,在书签处插入文字、插入图片、插入表格等。填充数据到表格中读取表格数据 ,1.1版增强的功能: 指定文本样式,指定表格样式。如此,则可动态排版word文档。是一种不错的解决方案。

4:iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。功能强大。

5:JSP输出样式,该方案实现简单,但是处理样式有点缺陷,简单的导出可以使用。

6:用XML做。Word从2003开始支持XML格式,大致的思路是先用office2003或者2007编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。经测试这样方式生成的word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。

综合以上资料的参考,和网上的一些意见,最后我选择了,第2种用POI做导出方案。

     

     使用POI导出到word,首先你要设置导出的word模板,在要填充的模板中填入表达式,如下图所示。

占位符尽量用英文,并且保证在同一个模板里不重复。

POI的思路就是取到模板文件,然后将数据替换占位符填充模板,生成一个新的word文档。

数据放到一个map里,key就是占位符名字,value如果是文字,就是字符串,如果是图片,还得特殊处理(见下文)

 

  1. /**
  2. * * 读取word模板并替换变量字段
  3. *
  4. * @param fileName 模板名
  5. * @param contentMap 要替换的内容
  6. * @return word的Document
  7. * @throws IOException
  8. */
  9. public XWPFDocument replaceDocForDispatch(String fileName, Map<String, Object> contentMap) throws IOException {
  10. try {
  11. Map<String, Object> newContentMap = new HashMap<String, Object>();
  12. Resource filePath = resourceLoader
  13. .getResource("classpath:config" + System.getProperty("file.separator") + fileName);
  14. File file = filePath.getFile();
  15. String path = file.getPath();
  16. // 读取模板
  17. CustomXWPFDocument doc = null;
  18. try {
  19. OPCPackage pack = POIXMLDocument.openPackage(path);
  20. doc = new CustomXWPFDocument(pack);
  1. //处理会签,会签里有多个审批意见,领导签名,审批时间
  2. if(contentMap.containsKey("hq")) {
  3. List list = (List)contentMap.get("hq");
  4. List leaderList = getLeaderList();
  5. for(int i=0;i<list.size();i++) {
  6. String operator = list.get(i).toString();
  7. if(leaderList.contains(operator)) {
  8. Object o = this.getSignImageByAccount(operator);
  9. list.remove(i);
  10. list.add(i, o);
  11. }
  12. }
  13. }
  14. // 处理段落
  15. List<XWPFParagraph> paragraphList = doc.getParagraphs();
  16. processParagraphs2(paragraphList, contentMap, doc);
  17. // 处理表格
  18. Iterator<XWPFTable> it = doc.getTablesIterator();
  19. while (it.hasNext()) {
  20. XWPFTable table = it.next();
  21. List<XWPFTableRow> rows = table.getRows();
  22. for (XWPFTableRow row : rows) {
  23. List<XWPFTableCell> cells = row.getTableCells();
  24. for (XWPFTableCell cell : cells) {
  25. List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
  26. processParagraphs2(paragraphListTable, contentMap, doc);
  27. }
  28. }
  29. }
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. return doc;
  34. } catch (Exception e) {
  35. return null;
  36. }
  37. }
  1. /**
  2. * * 通过人员名字获取对应的签名图片
  3. *
  4. * @param fileName 模板名
  5. * @param contentMap 要替换的内容
  6. * @return word的Document
  7. * @throws IOException
  8. */
  9. private Object getSignImageByAccount(String name) {
  10. String account = dao.selectacountBylastname(name);
  11. String url = dao.selectpicurlByacount(account);
  12. // 获取电子签名url异常处理
  13. try {
  14. if (url == null) {
  15. return name;
  16. }
  17. else {
  18. Map<String, Object> imageMap = this.getImageMap(url, 70, 25);
  19. return imageMap;
  20. }
  21. } catch (Exception e) {
  22. return name;
  23. }
  24. }
  25. /**
  26. * 获取图片参数
  27. *
  28. * @param url
  29. * @param width
  30. * @param height
  31. * @return
  32. * @throws IOException
  33. */
  34. private Map<String, Object> getImageMap(String url, int width, int height) throws IOException {
  35. Map<String, Object> imageMap = new HashMap<String, Object>();
  36. imageMap.put("width", width);
  37. imageMap.put("height", height);
  38. imageMap.put("type", "jpg");
  39. imageMap.put("content", CustomXWPFDocument.inputStream2ByteArray(new FileInputStream(url), true));
  40. return imageMap;
  41. }
  1. /**
  2. * 处理段落
  3. *
  4. * @param paragraphList
  5. */
  6. public static void processParagraphs2(List<XWPFParagraph> paragraphList, Map<String, Object> param,
  7. CustomXWPFDocument doc) {
  8. List leaderList = getLeaderList();
  9. if (paragraphList != null && paragraphList.size() > 0) {
  10. for (XWPFParagraph paragraph : paragraphList) {
  11. List<XWPFRun> runs = paragraph.getRuns();
  12. for (int i = 0; i < runs.size(); i++) {
  13. XWPFRun run = runs.get(i);
  14. String text = run.getText(0);
  15. if (text != null&¶m.containsKey(text)) {
  16. Object value = param.get(text);
  17. if (value instanceof String) {// 文本替换
  18. text = value.toString();
  19. run.setText(text,0);
  20. } else if (value instanceof List) {
  21. run.setText("",0);
  22. List list = (List)value;
  23. for(int j=0;j<list.size();j++) {
  24. Object o = list.get(j);
  25. if(o instanceof String) {
  26. XWPFRun run1 = paragraph.createRun();
  27. run1.setText(o.toString());
  28. run1.setFontSize(run.getFontSize());
  29. run1.setFontFamily(run.getFontFamily());
  30. run1.setBold(run.isBold());
  31. run1.addTab();
  32. }
  33. else if (o instanceof Map) {// 图片替换
  34. creactPic(doc,paragraph,(Map)o);
  35. }
  36. if(j%3==0&&j!=0) {
  37. XWPFRun run1 = paragraph.createRun();
  38. run1.addBreak();
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }
  46. }
  1. /**
  2. * 添加图片
  3. * @param map
  4. */
  5. private static void creactPic(CustomXWPFDocument doc,XWPFParagraph paragraph,Map picParam) {
  6. Map pic = (Map) picParam;
  7. int width = Integer.parseInt(pic.get("width").toString());
  8. int height = Integer.parseInt(pic.get("height").toString());
  9. byte[] byteArray = (byte[]) pic.get("content");
  10. ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
  11. try {
  12. String ind = doc.addPictureData(byteInputStream, 5);
  13. int id = doc.getAllPictures().size() - 1;
  14. doc.createPicture(id, width, height, paragraph, ind);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. }

在表格里写图片的关键方法是createPicture

 

 

  1. /**
  2. * @param id
  3. * @param width 宽
  4. * @param height 高
  5. * @param paragraph 段落
  6. * @param blipId
  7. */
  8. public void createPicture(int id,int width, int height, XWPFParagraph paragraph,String blipId) {
  9. final int EMU = 9525;
  10. width *= EMU;
  11. height *= EMU;
  12. CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();
  13. String picXml = "" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
  14. + " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
  15. + " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
  16. + " <pic:nvPicPr>" + " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>"
  17. + " <pic:cNvPicPr/>" + " </pic:nvPicPr>" + " <pic:blipFill>"
  18. + " <a:blip r:embed=\"" + blipId
  19. + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
  20. + " <a:stretch>" + " <a:fillRect/>" + " </a:stretch>"
  21. + " </pic:blipFill>" + " <pic:spPr>" + " <a:xfrm>"
  22. + " <a:off x=\"0\" y=\"0\"/>" + " <a:ext cx=\"" + width + "\" cy=\""
  23. + height + "\"/>" + " </a:xfrm>" + " <a:prstGeom prst=\"rect\">"
  24. + " <a:avLst/>" + " </a:prstGeom>" + " </pic:spPr>"
  25. + " </pic:pic>" + " </a:graphicData>" + "</a:graphic>";
  26. inline.addNewGraphic().addNewGraphicData();
  27. XmlToken xmlToken = null;
  28. try {
  29. xmlToken = XmlToken.Factory.parse(picXml);
  30. } catch (XmlException xe) {
  31. xe.printStackTrace();
  32. }
  33. inline.set(xmlToken);
  34. inline.setDistT(0);
  35. inline.setDistB(0);
  36. inline.setDistL(0);
  37. inline.setDistR(0);
  38. CTPositiveSize2D extent = inline.addNewExtent();
  39. extent.setCx(width);
  40. extent.setCy(height);
  41. CTNonVisualDrawingProps docPr = inline.addNewDocPr();
  42. docPr.setId(id);
  43. docPr.setName("图片" + id);
  44. }

图片被替换后效果如下:

 



 word的模型是
整个是一个document
然后里面有多很多个paragraph,
段落
段落和段落之间按照回车换行分割

每一段内,又可以有多个range,如果是文字,就放入XWPFRun里,然后run1.setText(o.toString());

还可以设置字体,大小,对齐方式,空格,换行

 

  1. run1.setFontSize(run.getFontSize());
  2. run1.setFontFamily(run.getFontFamily());
  3. run1.setBold(run.isBold());
  4. run1.addTab();
  5. run1.addBreak(); //换行
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/273023
推荐阅读
相关标签
  

闽ICP备14008679号