1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > java poi实现word导出(包括word模板的使用 复制表格 复制行 插入图片的使用)

java poi实现word导出(包括word模板的使用 复制表格 复制行 插入图片的使用)

时间:2020-12-07 14:11:31

相关推荐

java poi实现word导出(包括word模板的使用 复制表格 复制行 插入图片的使用)

java poi实现数据的word导出(包括word模板的使用、复制表格、复制行、插入图片的使用)

1.实现的效果

实现病人基本信息、多条病历数据、多项检查项图片的动态插入(网络图片)

2.模板

把word中的占位符替换为实际的值,注意WPFRun表示有相同属性的一段文本,所以模板里变量内容需要从左到右的顺序写,${name},如果先写${},再添加内容,会拆分成几部分,不能正常使用,因此若出现替换失败的情况,可以尝试手动修改占位符,不要偷懒直接复制

3.pom.xml中相关依赖

包括poi和模板

<!-- poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.15-beta2</version></dependency><!-- 模板 --><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.1</version></dependency>

4.导出的工具类

/*** 功能描述:word工具类** @author jynn* @created 8月15日* @version 1.0.0*/public class WordUtil {/*** 功能描述:word下载** @param response* @param patientMap* @param list* @param itemList* @param file* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static final void DownloadWord(HttpServletResponse response, Map<String, Object> patientMap,List<Map<String, Object>> list, List<List<String>> itemList, String file) {CustomXWPFDocument document = null;ServletOutputStream servletOS = null;ByteArrayOutputStream ostream = null;// 添加表格try {servletOS = response.getOutputStream();ostream = new ByteArrayOutputStream();// 生成word文档并读取模板document = new CustomXWPFDocument(POIXMLDocument.openPackage(file));// 病人信息XWPFTable patientTable = document.getTables().get(0);eachTable(document, patientTable.getRows(), patientMap);// 病历信息// 根据病历数量复制表格for (int i = 0; i < list.size(); i++) {// 标题XWPFParagraph paragraph = document.createParagraph();XWPFRun paragraphRun = paragraph.createRun();paragraphRun.setText(list.get(i).get("${title}").toString());paragraph.setAlignment(ParagraphAlignment.CENTER);// 创建新的 CTTbl , tableCTTbl ctTbl = CTTbl.Factory.newInstance(); // 复制原来的CTTblctTbl.set(document.getTables().get(1).getCTTbl()); IBody iBody = document.getTables().get(1).getBody();BeanUtils.copyProperties(document.getTables().get(1).getBody(), iBody);XWPFTable newTable = new XWPFTable(ctTbl, iBody); // 新增一个table,使用复制好的CttblList<String> iList = itemList.get(i);Integer itemIndex = 0;// 新建西医检查信息for (String item : iList) {// 复制行,主要用于复制样式和重设图片文本// 直接新增行还需要手动改样式,比较繁琐XWPFTableRow titleRow = newTable.createRow();// 注意setText方式是在原来文本的后面添加,若不需要原先的文本在需要删除原先的run,新增一个runcopyTableRow(titleRow, newTable.getRows().get(7), null);titleRow.getTableCells().get(0).setText(item);XWPFTableRow imageRow = newTable.createRow();// 带入序号重设文本copyTableRow(imageRow, newTable.getRows().get(8), itemIndex);itemIndex++;}// 删除作为模板的检查项标题和图片行newTable.removeRow(7);newTable.removeRow(7);// 遍历表格,并替换模板eachTable(document, newTable.getRows(), list.get(i));document.createTable(); // 创建一个空的Table// 设置table值document.setTable(i + 2, newTable); // 将table设置到word中}List<XWPFTable> tables = document.getTables();// 删除作为模板的第一个表格for (int i = tables.get(1).getRows().size(); i >= 0; i--) {tables.get(1).removeRow(i);}// 输出word内容文件流,提供下载response.setContentType("application/x-msdownload");String name = .URLEncoder.encode("病历.docx", "UTF8");name = new String((name).getBytes("UTF-8"), "ISO-8859-1");response.addHeader("Content-Disposition", "attachment; filename*=utf-8'zh_cn'" + name);document.write(ostream);servletOS.write(ostream.toByteArray());} catch (Exception e) {System.out.print(e.getMessage());} finally {try {if (ostream != null) {ostream.close();}if (servletOS != null) {servletOS.close();}} catch (IOException e) {}}}/*** 功能描述:复制单元格,从source到target** @param target* @param source* @param index* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void copyTableCell(XWPFTableCell target, XWPFTableCell source, Integer index) {// 列属性if (source.getCTTc() != null) {target.getCTTc().setTcPr(source.getCTTc().getTcPr());}// 删除段落for (int pos = 0; pos < target.getParagraphs().size(); pos++) {target.removeParagraph(pos);}// 添加段落for (XWPFParagraph sp : source.getParagraphs()) {XWPFParagraph targetP = target.addParagraph();copyParagraph(targetP, sp, index);}}/*** 功能描述:复制段落,从source到target** @param target* @param source* @param index* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void copyParagraph(XWPFParagraph target, XWPFParagraph source, Integer index) {// 设置段落样式target.getCTP().setPPr(source.getCTP().getPPr());// 移除所有的runfor (int pos = target.getRuns().size() - 1; pos >= 0; pos--) {target.removeRun(pos);}// copy 新的runfor (XWPFRun s : source.getRuns()) {XWPFRun targetrun = target.createRun();copyRun(targetrun, s, index);}}/*** 功能描述:复制RUN,从source到target** @param target* @param source* @param index* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void copyRun(XWPFRun target, XWPFRun source, Integer index) {// 设置run属性target.getCTR().setRPr(source.getCTR().getRPr());// 设置文本String tail = "";if (index != null) {tail = index.toString();}target.setText(source.text().replace("}", "") + tail + "}");}/*** 功能描述:复制行,从source到target** @param target* @param source* @param index* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void copyTableRow(XWPFTableRow target, XWPFTableRow source, Integer index) {// 复制样式if (source.getCtRow() != null) {target.getCtRow().setTrPr(source.getCtRow().getTrPr());}// 复制单元格for (int i = 0; i < source.getTableCells().size(); i++) {XWPFTableCell cell1 = target.getCell(i);XWPFTableCell cell2 = source.getCell(i);if (cell1 == null) {cell1 = target.addNewTableCell();}copyTableCell(cell1, cell2, index);}}/*** 功能描述:遍历表格,替换信息** @param document* @param rows* @param textMap* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void eachTable(CustomXWPFDocument document, List<XWPFTableRow> rows, Map<String, Object> textMap) {for (XWPFTableRow row : rows) {List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {// 判断单元格是否需要替换if (checkText(cell.getText())) {List<XWPFParagraph> paragraphs = cell.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {Object ob = changeValue(run.toString(), textMap);if (ob instanceof String) {run.setText((String) ob, 0);} else if (ob instanceof Map) {run.setText("", 0);<u>Map</u> pic = (<u>Map</u>) ob;int width = Integer.parseInt(pic.get("width").toString());int height = Integer.parseInt(pic.get("height").toString());int picType = getPictureType(pic.get("type").toString());String urls = pic.get("content").toString();String[] urlList = urls.split(";");for (String url : urlList) {ByteArrayInputStream byteInputStream;try {//网络图片取文件数据byteInputStream = new ByteArrayInputStream(getImageData(url));document.addPictureData(byteInputStream, picType);int id2 = document.getAllPackagePictures().size() - 1;document.createPicture(id2, width, height, paragraph);} catch (Exception e) {e.printStackTrace();}}}break;}}}}}}/*** 功能描述:读取线上图片文件流** @param strUrl* @return* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static byte[] getImageData(String strUrl) {InputStream inStream = null;try {// new一个URL对象URL url = new URL(strUrl);// 打开链接HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 设置请求方式为"GET"conn.setRequestMethod("GET");// 超时响应时间为5秒conn.setConnectTimeout(10 * 1000);// 通过输入流获取图片数据inStream = conn.getInputStream();byte[] data = readInputStream(inStream);return data;} catch (Exception e) {return null;} finally {if (inStream != null) {try {inStream.close();} catch (Exception e2) {System.out.println("关闭流失败");}}}}/*** 功能描述:读取文件流** @param inStream* @return* @throws Exception* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static byte[] readInputStream(InputStream inStream) throws Exception {ByteArrayOutputStream outStream = new ByteArrayOutputStream();// 创建一个Buffer字符串byte[] buffer = new byte[1024];// 每次读取的字符串长度,如果为-1,代表全部读取完毕int len = 0;// 使用一个输入流从buffer里把数据读取出来while ((len = inStream.read(buffer)) != -1) {// 用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度outStream.write(buffer, 0, len);}// 关闭输入流inStream.close();// 把outStream里的数据写入内存return outStream.toByteArray();}/*** 功能描述:为表格插入数据,行数不够添加新行** @param table* @param tableList* @param daList* @param type* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static void insertTable(XWPFTable table, List<String> tableList, List<String[]> daList, Integer type) {if (2 == type) {// 创建行和创建需要的列for (int i = 1; i < daList.size(); i++) {// 添加一个新行XWPFTableRow row = table.insertNewTableRow(1);for (int k = 0; k < daList.get(0).length; k++) {// 根据String数组第一条数据的长度动态创建列row.createCell();}}// 创建行,根据需要插入的数据添加新行,不处理表头for (int i = 0; i < daList.size(); i++) {List<XWPFTableCell> cells = table.getRow(i + 1).getTableCells();for (int j = 0; j < cells.size(); j++) {XWPFTableCell cell02 = cells.get(j);cell02.setText(daList.get(i)[j]);}}} else if (4 == type) {// 插入表头下面第一行的数据for (int i = 0; i < tableList.size(); i++) {XWPFTableRow row = table.createRow();List<XWPFTableCell> cells = row.getTableCells();cells.get(0).setText(tableList.get(i));}}}/*** 功能描述:判断文本中时候包含$** @param text* @return* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static boolean checkText(String text) {boolean check = false;if (text.indexOf("$") != -1) {check = true;}return check;}/*** 功能描述:匹配传入信息集合与模板** @param value* @param textMap* @return* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public static Object changeValue(String value, Map<String, Object> textMap) {Set<Map.Entry<String, Object>> textSets = textMap.entrySet();Object valu = "";for (Map.Entry<String, Object> textSet : textSets) {// 匹配模板与替换值 格式${key}String key = textSet.getKey();if (value.indexOf(key) != -1) {valu = textSet.getValue();}}return valu;}/*** 功能描述:根据图片类型,取得对应的图片类型代码** @param picType* @return* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/private static int getPictureType(String picType) {int res = CustomXWPFDocument.PICTURE_TYPE_PICT;if (picType != null) {if (picType.equalsIgnoreCase("png")) {res = CustomXWPFDocument.PICTURE_TYPE_PNG;} else if (picType.equalsIgnoreCase("dib")) {res = CustomXWPFDocument.PICTURE_TYPE_DIB;} else if (picType.equalsIgnoreCase("emf")) {res = CustomXWPFDocument.PICTURE_TYPE_EMF;} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {res = CustomXWPFDocument.PICTURE_TYPE_JPEG;} else if (picType.equalsIgnoreCase("wmf")) {res = CustomXWPFDocument.PICTURE_TYPE_WMF;}}return res;}}

5.自定义的ducument

主要需要重写document的创建图片方法

/*** 功能描述:自定义XWPFDocument,并重写 createPicture()方法** @author jynn* @created 8月18日* @version 1.0.0*/public class CustomXWPFDocument extends XWPFDocument {public CustomXWPFDocument() {super();}public CustomXWPFDocument(OPCPackage opcPackage) throws IOException {super(opcPackage);}public CustomXWPFDocument(InputStream in) throws IOException {super(in);}/*** 功能描述:创建图片** @param id* @param width* @param height* @param paragraph* @return* @see [相关类/方法](可选)* @since [产品/模块版本](可选)*/public void createPicture(int id, int width, int height, XWPFParagraph paragraph) {final int EMU = 9525;width *= EMU;height *= EMU;String blipId = getAllPictures().get(id).<u>getPackageRelationship</u><u>()</u>.getId();CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();System.out.println(blipId + ":" + inline);String picXml = "" + "<a:graphic xmlns:a=\"/drawingml//main\">"+ " <a:graphicData uri=\"/drawingml//picture\">"+ "<pic:pic xmlns:pic=\"/drawingml//picture\">"+ " <pic:nvPicPr>" + " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>"+ " <pic:cNvPicPr/>" + " </pic:nvPicPr>" + " <pic:blipFill>"+ " <a:blip r:embed=\"" + blipId+ "\" xmlns:r=\"/officeDocument//relationships\"/>"+ " <a:stretch>" + "<a:fillRect/>" + " </a:stretch>"+ " </pic:blipFill>" + " <pic:spPr>" + " <a:xfrm>"+ "<a:off x=\"0\" y=\"0\"/>" + "<a:ext cx=\"" + width + "\" cy=\""+ height + "\"/>" + " </a:xfrm>" + " <a:prstGeom prst=\"rect\">"+ "<a:avLst/>" + " </a:prstGeom>" + " </pic:spPr>"+ "</pic:pic>" + " </a:graphicData>" + "</a:graphic>";inline.addNewGraphic().addNewGraphicData();XmlToken xmlToken = null;try {xmlToken = XmlToken.Factory.parse(picXml);} catch (XmlException xe) {xe.printStackTrace();}inline.set(xmlToken);inline.setDistT(0);inline.setDistB(0);inline.setDistL(0);inline.setDistR(0);CTPositiveSize2D extent = inline.addNewExtent();extent.setCx(width);extent.setCy(height);CTNonVisualDrawingProps docPr = inline.addNewDocPr();docPr.setId(id);docPr.setName("图片" + id);docPr.setDescr("测试");}}

6.源代码

运行接口:http://localhost:9400/word/export

/JynnFun/word

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。