JAVA根据模板生成WORD文件并导出 您所在的位置:网站首页 怎么把简历模板导入word JAVA根据模板生成WORD文件并导出

JAVA根据模板生成WORD文件并导出

2024-07-17 20:47| 来源: 网络整理| 查看: 265

JAVA根据模板生成WORD并导出 实现功能一 : WORD导出效果二 : 编写WORD模板三 : 引入所需maven依赖四 : JAVA代码工具类五 : 配置信息说明六 : 在固定位置插入表格6.1 : 情况说明6.2 : 编码实现6.3 : 导出效果 七 : 可能出现的问题八 : 相关链接

实现功能 根据模板生成WORD文件,模板文件参数可配. 一 : WORD导出效果

先看一下导出的demo文件,具体参数可手动修改 下图为word_demo.docx导出的WORD文件 在这里插入图片描述 下图为word_list.docx导出的WORD文件 在这里插入图片描述

二 : 编写WORD模板 WORD文件模板,新建WORD文件,将所需参数用特殊符号 ${} 配置,如下图.

demo模板(数据替换模板中的配置参数) : word_demo.docx 在这里插入图片描述 demo模板(导出数据列表,数据表格在文件下方自动拼接) : word_list.docx 在这里插入图片描述

三 : 引入所需maven依赖

项目采用springboot框架

org.apache.poi poi-ooxml 3.8 org.apache.poi poi-scratchpad 3.8 四 : JAVA代码工具类

WORD导出接口类 WordController.java

package com.chang.word; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; /** * WORD导出 * @author message丶小和尚 * @create 2020/01/10 */ @Controller public class WordController { @Resource private WordExportService wordExportService;//Word导出工具 @RequestMapping("exportWordDemo") @ResponseBody public void exportWordDemo(HttpServletResponse response, @RequestParam("param")String param) throws Exception{ WordResult wordResult = new WordResult(); wordResult.setData(param); wordExportService.toWordDemo(response, wordResult); } @RequestMapping("exportWordList") @ResponseBody public void exportWordList(HttpServletResponse response, @RequestParam("param")String param) throws Exception{ List wordResultList = new ArrayList(); WordResult wordResult = new WordResult(); wordResult.setData(param); wordResultList.add(wordResult); wordExportService.toWordList(response, wordResult, wordResultList); } }

WORD导出工具类 WordExportService.java

package com.chang.word; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.List; /** * 模板文档下载 * @author message丶小和尚 * @create 2020/01/10 */ @Service public class WordExportService { //文件名 private final static String DEMO_WORD_FILE="模板demo文件"; private final static String DEMO_WORD_LIST="模板list文件"; public void toWordDemo(HttpServletResponse response, WordResult wordResult)throws Exception{ byte[] bytes = WordBaseService.toWordDemo(wordResult); if(bytes != null){ uploadWord(response,bytes,DEMO_WORD_FILE); } } public void toWordList(HttpServletResponse response, WordResult wordResult, List publicResultList)throws Exception{ byte[] bytes = WordBaseService.toWordList(wordResult,publicResultList); if(bytes != null){ uploadWord(response,bytes,DEMO_WORD_LIST); } } /** * 下载模板 * @param response 响应 * @param bytes 字节 * @param fileName 文件名 * @throws Exception */ private void uploadWord(HttpServletResponse response, byte[] bytes, String fileName) throws Exception{ try { if(bytes != null){ // OutputStream outputStream = new FileOutputStream("E:ceshi.docx"); OutputStream outputStream = response.getOutputStream(); response.setCharacterEncoding("utf-8"); response.setContentType("application/x-download"); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String userAgent = request.getHeader("User-Agent"); byte[] byteName = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8");//name.getBytes("UTF-8")处理safari的乱码问题 fileName = new String(byteName, "ISO-8859-1"); // 各浏览器基本都支持ISO编码 response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName+".docx"));//文件名外的双引号处理firefox的空格截断问题 InputStream is = new ByteArrayInputStream(bytes); byte[] buff = new byte[1024]; int len = 0; while ((len = is.read(buff)) != -1) { outputStream.write(buff, 0, len); } is.close(); outputStream.close(); } } catch (Exception e) { throw(e); } } }

WORD导出工具类 WordBaseService.java

package com.chang.word; import lombok.extern.slf4j.Slf4j; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.math.BigInteger; import java.util.List; import java.util.Map; /** * @author message丶小和尚 * @create 2020/01/10 * 模板下载 */ @Slf4j @Component public class WordBaseService { private static String templateBasePath = "/app/static/template/"; private final static String WORD_DEMO = "word_demo.docx"; private final static String WORD_LIST = "word_list.docx"; //Word导出,参数配置 public static byte[] toWordDemo(WordResult wordResult) throws Exception { return toWordObjectMap(wordResult,WORD_DEMO); } private static byte[] toWordObjectMap(Object obj,String filePath) throws Exception{ byte[] bytes = null; if(obj != null ){ bytes = toWordAllModelAnalysis(WordUtil.setMapObject(obj),templateBasePath + filePath); } return bytes; } private static byte[] toWordAllModelAnalysis(Map mapObject, String modelPath) throws Exception { byte[] bytes = null; if(mapObject != null && !StringUtils.isEmpty(modelPath)){ File file = new File(modelPath); if(!file.exists()&&!file.isFile()){ log.error("模板文件不存在"); return null; } try { XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath); ByteArrayOutputStream baos=new ByteArrayOutputStream(); doc.write(baos); bytes = baos.toByteArray(); baos.close(); } catch (Exception e) { log.error("文件处理异常",e); } } return bytes; } //Word导出,列表设置 public static byte[] toWordList(WordResult wordResult, List publicResultList) throws Exception { return toWordObjectMapPublic(wordResult,publicResultList,WORD_LIST); } private static byte[] toWordObjectMapPublic(Object obj, List list, String filePath) throws Exception{ byte[] bytes = null; if(obj != null ){ bytes = toWordAllModelAnalysisPublic(WordUtil.setMapObject(obj),list,templateBasePath+filePath); } return bytes; } private static byte[] toWordAllModelAnalysisPublic(Map mapObject,List list, String modelPath) throws Exception { byte[] bytes = null; if(mapObject != null && !StringUtils.isEmpty(modelPath)){ File file = new File(modelPath); if(!file.exists()&&!file.isFile()){ log.error("模板文件不存在"); return null; } try { XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //插入表格 XWPFTable table = doc.createTable(); table.getCTTbl().addNewTblPr().addNewJc().setVal(STJc.CENTER);//设置表格居中 //设置表头 XWPFTableRow tableRowOne = table.getRow(0); XWPFParagraph paragraph0 = getStyle(doc.createParagraph(),"序号"); tableRowOne.getCell(0).setParagraph(paragraph0); paragraph0.removeRun(0); tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1000));//设置宽度 tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中 // tableRowOne.getCell(0).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER); XWPFParagraph paragraph1 = getStyle(doc.createParagraph(),"数据"); tableRowOne.addNewTableCell().setParagraph(paragraph1); paragraph1.removeRun(0); tableRowOne.getCell(1).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1500));//设置宽度 tableRowOne.getCell(1).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中 // tableRowOne.getCell(1).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER); //循环设置Word表格内容 for (int i = 0; i log.error("文件处理异常",e); } } return bytes; } //设置段落格式 private static XWPFParagraph getStyle(XWPFParagraph paragraphX, String name){ paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式 XWPFRun runXOne = paragraphX.createRun();//创建文本对象 runXOne.setText(name); runXOne.setFontSize(15);//字体大小 runXOne.setFontFamily("黑体");//字体 runXOne.setBold(true);//加粗 runXOne.setTextPosition(10);//设置行间距 return paragraphX; } //设置段落格式 private static XWPFParagraph getStyleNotBold(XWPFParagraph paragraphX, String name){ paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式 XWPFRun runXOne = paragraphX.createRun();//创建文本对象 runXOne.setText(name); runXOne.setFontSize(14);//字体大小 runXOne.setBold(false);//加粗 runXOne.setTextPosition(10);//设置行间距 return paragraphX; } }

WORD导出工具类 WordUtil.java

package com.chang.word; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.poi.POIXMLDocument; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlToken; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author message丶小和尚 * @create 2020/01/10 * 模板的装载过程 */ public class WordUtil { private static Log log = LogFactory.getLog(WordUtil.class); /** * 装载模板所对应的对象 * @param object * @return map */ public static Map setMapObject(Object object){ Map mapObject = new HashMap(); if(object != null){ Field[] fields = object.getClass().getDeclaredFields(); log.info("fields" + fields.length); for(Field field : fields){ try { field.setAccessible(true); String str = "${" + field.getName() + "}"; Object objValue = field.get(object); if(objValue != null){ log.info(str + "----" + objValue.toString()); mapObject.put(str, objValue); }else{ mapObject.put(str, ""); } } catch(Exception e) { log.error("模板对象出现错误", e); } } } else { log.error("模板对象不是对应的一个类对象"); } return mapObject; } /** * 根据指定的参数值、模板,生成 word 文档 * @param param 需要替换的变量 * @param template 模板 * @return XWPFDocument * @throws IOException * @throws InvalidFormatException */ public static XWPFDocument generateWord(Map param, String template) throws IOException, InvalidFormatException { if(param == null || template == null){ return null ; } XWPFDocument xwpfDocument = null; log.info("解析的模版为:" + template); try { OPCPackage pack = POIXMLDocument.openPackage(template); xwpfDocument = new XWPFDocument(pack); if (param.size() > 0) { //处理段落 List paragraphList = xwpfDocument.getParagraphs(); processParagraphs(paragraphList, param, xwpfDocument); //处理表格 Iterator it = xwpfDocument.getTablesIterator(); while (it.hasNext()) { XWPFTable table = it.next(); List rows = table.getRows(); for (XWPFTableRow row : rows) { List cells = row.getTableCells(); for (XWPFTableCell cell : cells) { List paragraphListTable = cell.getParagraphs(); processParagraphs(paragraphListTable, param, xwpfDocument); } } } } } catch (IOException e) { log.error("文件处理异常", e); throw(e); }catch (InvalidFormatException e) { log.error("文档中内容处理异常", e); throw(e); } return xwpfDocument; } /** * 处理段落 * @param paragraphList * @param param * @param doc * @throws InvalidFormatException * @throws FileNotFoundException */ public static void processParagraphs(List paragraphList, Map param, XWPFDocument doc) throws InvalidFormatException, FileNotFoundException{ if(paragraphList != null && paragraphList.size() > 0){ for(XWPFParagraph paragraph : paragraphList){ List runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); if(text != null){ boolean isSetText = false; for (Map.Entry entry : param.entrySet()) { String key = entry.getKey(); if(text.indexOf(key) != -1){ isSetText = true; Object value = entry.getValue(); if (value instanceof String) {//文本替换 log.info(key + "模板中模要转化属性对应的值:" + value); text = text.replace(key, value.toString()); } else if (value instanceof Map) {//图片替换 text = text.replace(key, ""); Map pic = (Map)value; int width = Integer.parseInt(pic.get("width").toString()); int height = Integer.parseInt(pic.get("height").toString()); int picType = getPictureType(pic.get("type").toString()); String byteArray = (String) pic.get("imgPath"); log.info("模板中模要转化的图片" + byteArray); CTInline inline = run.getCTR().addNewDrawing().addNewInline(); insertPicture(doc,byteArray,inline, width, height); } } } if(isSetText){ run.setText(text,0); } } } } } } /** * 根据图片类型,取得对应的图片类型代码 * @param picType * @return int */ private static int getPictureType(String picType){ int res = XWPFDocument.PICTURE_TYPE_PICT; if(picType != null){ if(picType.equalsIgnoreCase("png")){ res = XWPFDocument.PICTURE_TYPE_PNG; }else if(picType.equalsIgnoreCase("dib")){ res = XWPFDocument.PICTURE_TYPE_DIB; }else if(picType.equalsIgnoreCase("emf")){ res = XWPFDocument.PICTURE_TYPE_EMF; }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){ res = XWPFDocument.PICTURE_TYPE_JPEG; }else if(picType.equalsIgnoreCase("wmf")){ res = XWPFDocument.PICTURE_TYPE_WMF; } } return res; } /** * 将输入流中的数据写入字节数组 * @param inputStream * @param isClose * @return */ public static byte[] inputStream2ByteArray(InputStream inputStream,boolean isClose){ byte[] byteArray = null; try { int total = inputStream.available(); byteArray = new byte[total]; inputStream.read(byteArray); } catch (IOException e) { log.error("IO异常",e); } finally { if(isClose){ try { inputStream.close(); } catch (Exception e2) { log.debug("关闭流失败"); } } } return byteArray; } /** * * @param document * @param filePath * @param inline * @param width * @param height * @throws InvalidFormatException * @throws FileNotFoundException */ private static void insertPicture(XWPFDocument document, String filePath, CTInline inline, int width, int height) throws InvalidFormatException, FileNotFoundException { document.addPictureData(new FileInputStream(filePath), XWPFDocument.PICTURE_TYPE_PNG); int id = document.getAllPictures().size() - 1; final int EMU = 9525; width *= EMU; height *= EMU; // String blipId = document.getAllPictures().get(id).getPackageRelationship().getId(); Integer blipIdString = document.getAllPictures().get(id).getPictureType(); String blipId = blipIdString.toString(); String picXml = getPicXml(blipId, width, height); XmlToken xmlToken = null; try { xmlToken = XmlToken.Factory.parse(picXml); } catch (XmlException xe) { log.error("XmlException",xe); } 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("IMG_" + id); docPr.setDescr("IMG_" + id); } /** * get the xml of the picture * @param blipId * @param width * @param height * @return */ private static String getPicXml(String blipId, int width, int height) { String picXml = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; return picXml; } }

WORD导出实体类(模板所需参数) WordResult.java

package com.chang.word; import java.io.Serializable; /** * WORD导出参数类 * @author message丶小和尚 * @create 2020/01/10 */ public class WordResult implements Serializable { private static final long serialVersionUID = 1L; public String data; public String getData() { return data; } public void setData(String data) { this.data = data; } } 五 : 配置信息说明

在WordExportService中,可设置导出的Word文件名. 在这里插入图片描述 在WordBaseService中,可设置Word模板配置的地址,以及配置模板名称 在这里插入图片描述

六 : 在固定位置插入表格 6.1 : 情况说明

在真实的业务场景中,可能会涉及Word中表格的导出。表格并不是拼接在文档末尾,而是设置在文档中,即某个段落与段落之间,类似下图这种情况。 在这里插入图片描述 对于这种在固定位置插入表格的情况,我们可采用同样的占位符的方式来实现。 如图所示,定义一个占位符 ${make_newTable},当然里面的内容可以自己定义,需注意不能与文档中其他占位符同名即可。 在这里插入图片描述

6.2 : 编码实现

前提是前面的架子已经搭好。 这里的实现结果为标准表格导出,如果需要特殊表格,即合并单元格等,可改造该方法,对cell做特殊处理即可。 在WordTempleCommonService.java文件中增加方法如下:

//通用导出WORD 包含list public static byte[] toWordCommonIndexList(Object obj,List head,List list,String filePath) throws Exception{ byte[] bytes = null; if(obj != null ){ bytes = toWordAllModelAnalysisCommonIndexList(WordUtil.setMapObject(obj),head,list,WordConstant.TEMPLATE_BASE_PATH + filePath); } return bytes; } private static byte[] toWordAllModelAnalysisCommonIndexList(Map mapObject,List head,List stringList, String modelPath) throws Exception { byte[] bytes = null; if(mapObject != null && !StringUtils.isEmpty(modelPath)){ File file = new File(modelPath); if(!file.exists() && !file.isFile()){ return null; } try { XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); List xwpfParagraphList = doc.getParagraphs(); for(int s = 0; s XmlCursor cursor = xwpfParagraphIndex.getCTP().newCursor(); XWPFTable table = doc.insertNewTbl(cursor); //插入表格 table.getCTTbl().addNewTblPr().addNewJc().setVal(STJc.CENTER);//设置表格居中 //定义map Map map = new HashMap(); //设置表头 XWPFTableRow tableRowOne = table.getRow(0); for(String string:head){ Integer index = head.indexOf(string);//当前所处序号 Integer width = string.length() * 350 + 200; if(0 == index && "序号".equals(string)){ width = 800; } map.put(index,width); XWPFParagraph paragraph = getCommonIndexStyle(doc.createParagraph(), string, true); if(0 == index){ tableRowOne.getCell(0).setParagraph(paragraph); paragraph.removeRun(0); tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(width));//设置宽度 tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中 tableRowOne.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(600)); } else { tableRowOne.addNewTableCell().setParagraph(paragraph); paragraph.removeRun(0); tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(width));//设置宽度 tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中 tableRowOne.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(600)); } doc.removeBodyElement(doc.getPosOfParagraph(paragraph)); } //循环设置Word表格内容 for(List list : stringList){ XWPFTableRow tableRow = table.createRow(); for(int i = 0; i log.error("文件处理异常,Exception:", e); } } return bytes; } //设置通用段落格式 private static XWPFParagraph getCommonIndexStyle(XWPFParagraph paragraphX, String name, boolean flag){ paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式 paragraphX.setVerticalAlignment(TextAlignment.CENTER);//对齐方式 XWPFRun runXOne = paragraphX.createRun();//创建文本对象 runXOne.setText(name); if(null == name){ runXOne.setText(""); } runXOne.setFontSize(12);//字体大小 runXOne.setFontFamily("Calibri (正文)");//字体 if(flag){ runXOne.setBold(true);//加粗 } runXOne.setTextPosition(10);//设置行间距 return paragraphX; }

上述代码中需要注意的是:doc.removeBodyElement(doc.getPosOfParagraph(xwpfParagraphIndex)); 这是由于我们在生成表格的时候,会去调用 doc.createParagraph(),创建段落,如果不去remove的话,会导致文档产生非常多的空白页。 方法getCommonIndexStyle,其主要作用即设置样式,如果想设置不同样式,可以自行设置即可。

然后在WordTempleService.java文件中增加方法如下:

//指定位置插入表格 ${make_newTable} public void toWordCommonIndexList(HttpServletResponse response, Object object,List head,List list,String wordTemplate,String fileName)throws Exception{ byte[] bytes = WordTempleCommonService.toWordCommonIndexList(object,head,list,wordTemplate); if(bytes != null){ uploadWord(response,bytes,fileName); } }

上述代码的 uploadWord方法,可在文中找到。

至此方法已经搭建完成,下面是模拟调用。

wordTempleService.toWordCommonIndexList(response, templateDate, tableHead, tableData, wordTemplate, fileName);

参数说明: response:响应头。 templateDate:Word模板导出的其他匹配数据。 tableHead:表格的表头。可使用Arrays.asList(“序号”, “姓名”) tableData:表格的内容。 wordTemplate:模板的名称,需要注意路径问题。 fileName:导出的文件对应的文件名。

6.3 : 导出效果

在这里插入图片描述

七 : 可能出现的问题

在模板中配置参数 ${data} 时,可能会出现配置了参数,但是导出的时候赋值不了的情况,生成的Word中仍是 ${data} . 这种情况需要在代码中debug,找到对应的map,从代码中把对应的key复制到Word模板上. 如图所示复制一下,问题就可以解决了 在这里插入图片描述

附上材料下载地址 链接:https://pan.baidu.com/s/1jL1UpQatLVIjx0iBXIOMeg 提取码: ga1a CSDN资源,0积分下载:https://download.csdn.net/download/qq_38254635/12099599

八 : 相关链接

JAVA生成Zip文件并导出: https://blog.csdn.net/qq_38254635/article/details/127364398

JAVA导出Excel文件: https://blog.csdn.net/qq_38254635/article/details/126691175

JAVA根据PDF文件生成图片: https://blog.csdn.net/qq_38254635/article/details/112029941

JAVA根据模板生成PDF文件并导出: https://blog.csdn.net/qq_38254635/article/details/103919024



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有