使用poi操作模板文件重新生成新的word表单文件
2017-06-01 14:11
716 查看
问题:本人在项目中使用poi生成word表单文件,发现格式排版非常麻烦不说,还有个比较严重的问题是,wps跟office格式不兼容,用了2种方法都没有让这个两种打开的样式一致。不是office格式排版有问题就是wps格式排版有问题,研究了一天,最后决定用模板文件去生成新的文档比较容易,也不会有兼容性问题,并且也不用麻烦的去写很多样式做,而且可以简化代码变成工具类。解决了一个样式就要写一个生成类的问题,下面就来介绍一个下。
三、操作类
四 、controller类调用方法
一、先来看一下模板文件
首先先创建一个格式符合要求的表单文档,所有需要动态值的地方用${}括起来自定义名称 例如${name}等等。二、准备一个工具类。
package org.uz.dxt.common; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; 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; public class Xwp { /** * 此类为poi操作word模板的工具类 * @Author qixin at 2017-6-01 * */ /*String filePath = "/sta.docx"; InputStream is; XWPFDocument doc; Map<String, Object> params = new HashMap<String, Object>(); { params.put("${name}", "xxx"); params.put("${sex}", "男"); params.put("${political}", "共青团员"); params.put("${place}", "sssss"); params.put("${classes}", "3102"); params.put("${id}", "213123123"); params.put("${qq}", "213123"); params.put("${tel}", "312313213"); params.put("${oldJob}", "sadasd"); params.put("${swap}", "是"); params.put("${first}", "asdasd"); params.put("${second}", "综合事务部"); params.put("${award}", "asda"); params.put("${achievement}", "完成科协网站的开发"); params.put("${advice}", "没有建议"); params.put("${attach}", "无"); try { is = new FileInputStream(filePath); doc = new XWPFDocument(is); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }*/ /** * 用一个docx文档作为模板,然后替换其中的内容,再写入目标文档中。 * * @throws Exception */ /*@Test public void testTemplateWrite() throws Exception { //替换段落里面的变量 this.replaceInPara(doc, params); //替换表格里面的变量 this.replaceInTable(doc, params); OutputStream os = new FileOutputStream("D:\\sta1.docx"); doc.write(os); this.close(os); this.close(is); }*/ /*@Test public void myTest1() throws Exception { *//*Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); List<XWPFRun> runs = para.getRuns(); para.removeRun(0); para.insertNewRun(0).setText("hello"); } OutputStream os = new FileOutputStream("D:\\sta1.docx"); doc.write(os); this.close(os); this.close(is);*//* System.out.println(this.matcher("报告日期:${reportDate}").find()); }*/ /*@Test public void myReplaceInPara() { // Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); // XWPFParagraph para; // while (iterator.hasNext()) { // para = iterator.next(); // List<XWPFRun> runs = para.getRuns(); // // // } System.out.println('{'=='{'); }*/ /** * 替换段落里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ public void replaceInPara(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); this.replaceInPara(para, params); } } /** * 替换段落里面的变量 * * 10bfd @param para 要替换的段落 * @param params 参数 */ public void replaceInPara(XWPFParagraph para, Map<String, Object> params) { List<XWPFRun> runs; Matcher matcher; runs = para.getRuns(); int start = -1; int end = -1; String str = ""; for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); System.out.println("------>>>>>>>>>" + runText); if ('$' == runText.charAt(0)) { start = i; } if ((start != -1)) { str += runText; } if ('}' == runText.charAt(runText.length() - 1)) { if (start != -1) { end = i; break; } } } System.out.println("start--->"+start); System.out.println("end--->"+end); System.out.println("str---->>>" + str); for (int i = start; i <= end; i++) { para.removeRun(i); i--; end--; System.out.println("remove i="+i); } for (String key : params.keySet()) { if (str.equals(key)) { para.createRun().setText((String) params.get(key)); break; } } } /** * 替换表格里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ public void replaceInTable(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFTable> iterator = doc.getTablesIterator(); XWPFTable table; List<XWPFTableRow> rows; List<XWPFTableCell> cells; List<XWPFParagraph> paras; while (iterator.hasNext()) { table = iterator.next(); rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); for (XWPFParagraph para : paras) { this.replaceInPara(para, params); } } } } } /** * 关闭输入流 * * @param is */ public void close(InputStream is) { if (is != null) { try { is.close(); } catch ( Exception e) { e.printStackTrace(); } } } /** * 关闭输出流 * * @param os */ public void close(OutputStream os) { if (os != null) { try { os.close(); } catch ( Exception e) { e.printStackTrace(); } } } }
package org.uz.dxt.common; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; 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; public class Xwp { /** * 此类为poi操作word模板的工具类 * @Author qixin at 2017-6-01 * */ /*String filePath = "/sta.docx"; InputStream is; XWPFDocument doc; Map params = new HashMap(); { params.put("${name}", "xxx"); params.put("${sex}", "男"); params.put("${political}", "共青团员"); params.put("${place}", "sssss"); params.put("${classes}", "3102"); params.put("${id}", "213123123"); params.put("${qq}", "213123"); params.put("${tel}", "312313213"); params.put("${oldJob}", "sadasd"); params.put("${swap}", "是"); params.put("${first}", "asdasd"); params.put("${second}", "综合事务部"); params.put("${award}", "asda"); params.put("${achievement}", "完成科协网站的开发"); params.put("${advice}", "没有建议"); params.put("${attach}", "无"); try { is = new FileInputStream(filePath); doc = new XWPFDocument(is); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }*/ /** * 用一个docx文档作为模板,然后替换其中的内容,再写入目标文档中。 * * @throws Exception */ /*@Test public void testTemplateWrite() throws Exception { //替换段落里面的变量 this.replaceInPara(doc, params); //替换表格里面的变量 this.replaceInTable(doc, params); OutputStream os = new FileOutputStream("D:\\sta1.docx"); doc.write(os); this.close(os); this.close(is); }*/ /*@Test public void myTest1() throws Exception { *//*Iterator iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); List runs = para.getRuns(); para.removeRun(0); para.insertNewRun(0).setText("hello"); } OutputStream os = new FileOutputStream("D:\\sta1.docx"); doc.write(os); this.close(os); this.close(is);*//* System.out.println(this.matcher("报告日期:${reportDate}").find()); }*/ /*@Test public void myReplaceInPara() { // Iterator iterator = doc.getParagraphsIterator(); // XWPFParagraph para; // while (iterator.hasNext()) { // para = iterator.next(); // List runs = para.getRuns(); // // // } System.out.println('{'=='{'); }*/ /** * 替换段落里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ public void replaceInPara(XWPFDocument doc, Map params) { Iterator iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); this.replaceInPara(para, params); } } /** * 替换段落里面的变量 * * @param para 要替换的段落 * @param params 参数 */ public void replaceInPara(XWPFParagraph para, Map params) { List runs; Matcher matcher; runs = para.getRuns(); int start = -1; int end = -1; String str = ""; for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); System.out.println("------>>>>>>>>>" + runText); if ('$' == runText.charAt(0)) { start = i; } if ((start != -1)) { str += runText; } if ('}' == runText.charAt(runText.length() - 1)) { if (start != -1) { end = i; break; } } } System.out.println("start--->"+start); System.out.println("end--->"+end); System.out.println("str---->>>" + str); for (int i = start; i <= end; i++) { para.removeRun(i); i--; end--; System.out.println("remove i="+i); } for (String key : params.keySet()) { if (str.equals(key)) { para.createRun().setText((String) params.get(key)); break; } } } /** * 替换表格里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ public void replaceInTable(XWPFDocument doc, Map params) { Iterator iterator = doc.getTablesIterator(); XWPFTable table; List rows; List cells; List paras; while (iterator.hasNext()) { table = iterator.next(); rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); for (XWPFParagraph para : paras) { this.replaceInPara(para, params); } } } } } /** * 关闭输入流 * * @param is */ public void close(InputStream is) { if (is != null) { try { is.close(); } catch ( Exception e) { e.printStackTrace(); } } } /** * 关闭输出流 * * @param os */ public void close(OutputStream os) { if (os != null) { try { os.close(); } catch ( Exception e) { e.printStackTrace(); } } } }
三、操作类
package org.uz.dxt.service.bankbase.impl; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.zip.Adler32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.uz.dxt.common.Xwp; import org.uz.dxt.model.bankbase.PeopleVisit; import org.uz.dxt.util.DateUtil; /** * * @Description:Task下载生成流 */ public class DownLoadTable { private Logger log = LoggerFactory.getLogger(DownLoadTemplet.class); // Word生成的格式 private final String FONT_FAMILY = "宋体"; private final int TITLE_FONT_SIZE = 20; private final int BODY_FONT_SIZE = 12; private final String TITLE_FONT_COLOR = "000000"; private final String BOFY_FONT_COLOR = "555555"; // 下载文件的地址 private final String HOST_URL = "http://wiscc6911.qnoddns.org.cn:8400/file/web/download/"; private PeopleVisit task; private Map<String, byte[]> fileMap=new HashMap<String, byte[]>(); public DownLoadTable() { } public DownLoadTable(Map<String, Object> params,String templatePath,String wordFileName) { CreateWord(params,templatePath,wordFileName); } /** * * @Description:生成word 并把word 流 和录音流放入 fileMap中 * @Date:2015-12-17 * @return */ private void CreateWord( Map<String, Object> params,String templatePath,String wordFileName) { XWPFDocument doc = new XWPFDocument(); ByteArrayOutputStream bt = new ByteArrayOutputStream(); Xwp xwpfTUtil = new Xwp(); try { /*String templatePath = "e:/word/model.docx"; */ InputStream is = new FileInputStream(templatePath); doc = new XWPFDocument(is); //替换段落里面的变量 xwpfTUtil.replaceInPara(doc, params); //替换表格里面的变量 xwpfTUtil.replaceInTable(doc, params); doc.write(bt); xwpfTUtil.close(bt); bt.flush(); bt.close(); //word文件名拼装 /*String wordFileName="外访报告信息填写模板";*/ wordFileName+="-"+DateUtil.formatDate(new Date())+".docx"; //word 放入fileMap中 fileMap.put(wordFileName, bt.toByteArray()); // bt.close(); } catch (Exception e) { e.printStackTrace(); log.error("create word {}" + e.getMessage()); } } /** * * @Description:zip 打包 * @Date:2015-12-17 * @return */ public byte[] createZip(){ ByteArrayOutputStream zipByte = new ByteArrayOutputStream(); //输出流校验,采用Adler32 更快 CheckedOutputStream csum = new CheckedOutputStream(zipByte, new Adler32()); ZipOutputStream zos=new ZipOutputStream(csum); try{ Iterator<String> fileNames=fileMap.keySet().iterator(); while(fileNames.hasNext()){ String fileName=fileNames.next(); byte[] fileByte=fileMap.get(fileName); ZipEntry entry = new ZipEntry(fileName); entry.setSize(fileByte.length); zos.putNextEntry(entry); zos.write(fileByte); } zos.closeEntry(); zos.close(); return zipByte.toByteArray(); }catch (Exception e) { e.printStackTrace(); try { zipByte.close(); } catch (IOException e1) { e1.printStackTrace(); } } return null; } /** * * @Description:从文件服务器获取文件流 * @Date:2015-12-16 * @param fileDownUrl * @param fileId * @return * @throws Exception */ private InputStream getImage(String fileDownUrl) throws Exception{ log.debug(fileDownUrl); URL url; InputStream in=null; url = new URL(fileDownUrl); HttpURLConnection request=(HttpURLConnection) url.openConnection(); request.setRequestMethod("GET"); request.setConnectTimeout(5*1000); request.setDoInput(true); log.debug(""+request.getResponseCode()); if(request.getResponseCode()==200) { log.debug(""+request.getResponseCode()); in=request.getInputStream(); return in; } log.debug("return null"); return null; } /** * * @Description: input转byte[] * @Date:2015-12-17 * @param in * @return * @throws IOException */ private byte[] inputStreamToByte(InputStream in) throws IOException{ ByteArrayOutputStream out=new ByteArrayOutputStream(); int len=0; byte[] buffer=new byte[1024]; while((len=in.read(buffer))!=-1){ out.write(buffer, 0, len); } return out.toByteArray(); } }
四 、controller类调用方法
/** * 下载外访报告的模板 * * @param * @author qixin * @return */ @RequestMapping("/out/downloadTemplet") public ResponseEntity<byte[]> downloadTemplet(Model model,HttpServletRequest request,HttpSession session,String visitId){ String userId=null; Object sessions = session.getAttribute("user"); if (sessions == null) { return null; } if (User.class.equals(sessions.getClass())) { User user = (User) sessions; userId=Integer.toString(user.getId()); } VisitApply visitApply=new VisitApply(); visitApply.setVisitId(visitId); //获取外访申请信息 VisitApply info=outVisitServiceimpl.selectVisitApplyData(visitApply); //获取案件信息 CaseHead t = new CaseHead(); t.setCaseid(info.getCaseid()); t.setCompanycode(info.getCompanyCode()); CaseBo caseBo=caseHeadService.getCaseHeadDetailByExample(t); //获取案件联系方式信息 CaseContact caseContact=new CaseContact(); caseContact.setCaseid(info.getCaseid()); List<CaseContact> contacts=caseContactService.selectCaseConcatList(caseContact); //生成文件名称 String fileName="外访报告填写模板"+DateUtil.formatDate(new Date())+".zip"; //生成下载文件word /*DownLoadTemplet download=new DownLoadTemplet(info,caseBo,contacts);*/ //生成下载文件word表单 /*DownLoadTableTemplet download=new DownLoadTableTemplet(info,caseBo,contacts);*/ //生成下载文件word模板替换生成表单 Map<String, Object> params=dowloadWordService.dowloadModelWord(info, caseBo, contacts); //模板地址 String templatePath = this.getClass().getClassLoader().getResource("/model.docx").getPath(); System.out.println(templatePath); String wordFileName="外访报告信息填写模板";//生成文件名 DownLoadTable download=new DownLoadTable(params,templatePath,wordFileName); byte[] taskFile=download.createZip(); HttpHeaders headers = new HttpHeaders(); //下载 if(taskFile!=null){ headers.setContentLength(taskFile.length); } headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); setFileName(request, headers, fileName); //下载文件 return new ResponseEntity<byte[]>(taskFile, headers, HttpStatus.OK); }
五,params参数的sercive实现类
package org.uz.dxt.service.bankbase.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import org.uz.dxt.model.bankbase.CaseBo; import org.uz.dxt.model.bankbase.VisitApply; import org.uz.dxt.model.common.CaseContact; import org.uz.dxt.service.bankbase.DowloadWordService; @Service public class DowloadWordServiceImpl implements DowloadWordService { @Override public Map<String, Object> dowloadModelWord(VisitApply info, CaseBo caseBo, List<CaseContact> contacts) { Map<String, Object> params = new HashMap<String, Object>(); params.put("${caseid}", info.getCaseid()); params.put("${applyName}", info.getApplyName()); params.put("${applyTime}", info.getApplyTime()); params.put("${visitPurpose}", info.getVisitPurpose()); params.put("${addressType}", info.getAddressType()); params.put("${appointName}", info.getAppointName()); params.put("${bankName}", info.getBankName()); params.put("${name}", info.getName()); params.put("${doccode}", info.getDoccode()); params.put("${cardcode}", info.getCardcode()); params.put("${overmoney}", info.getOvermoney()); String deputecapital=""; if(caseBo.getDeputecapital() != null){ deputecapital=caseBo.getDeputecapital().toString(); }else{ deputecapital="无"; } String moneybalance=""; if(caseBo.getMoneybalance() != null){ moneybalance=caseBo.getMoneybalance().toString(); }else{ moneybalance="无"; } params.put("${deputecapital}", deputecapital); params.put("${moneybalance}", moneybalance); String contactInfo=""; if (contacts != null) { for(int i=0;i<contacts.size();i++){ String type=""; String address=""; String name=""; if (contacts.get(i).getValid() != 0) { if (contacts.get(i).getContacttype() == "0") { type="电话"; }else if (contacts.get(i).getContacttype() == "1") { type="邮件"; }else if (contacts.get(i).getContacttype() == "2") { type="QQ"; }else if (contacts.get(i).getContacttype() == "3") { type="微信"; }else if (contacts.get(i).getContacttype() == "4") { type="地址"; }else { type="无"; } if (contacts.get(i).getCoofficeaddr() != null) { address=contacts.get(i).getCoofficeaddr(); }else{ address="无"; } if (contacts.get(i).getContactname() != null) { name=contacts.get(i).getContactname(); }else{ name="不详"; } contactInfo=contactInfo+"联系人:"+name+" 类型:"+type+" 关系:"+contacts.get(i).getRelation()+" 联系方式:"+contacts.get(i).getInfo()+" 单位地址:"+address; } } }else{ contactInfo="无联系方式"; } params.put("${visitAddress}", info.getVisitAddress()); params.put("${contactInfo}", contactInfo); return params; } }
六、生成后的表单效果
七、如果觉得麻烦看的不太明白我建议一点一点尝试,这里放一个简单的测试main方法,当你使用这个明白以后再琢磨一下怎么适合自己的需求去写代码。
还是要用到xwp工具类,模板用本地路径即可,运行mian方法查看结果package org.uz.dxt.service; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.apache.poi.xwpf.usermodel.XWPFDocument; public class TestModel { public static void main(String[] args) throws Exception { Map<String, Object> params = new HashMap<String, Object>(); params.put("${applyName}", "aaa"); params.put("${applyTime}", "bbb"); params.put("${visitPurpose}", "ccc"); Xwp xwpfTUtil = new Xwp(); XWPFDocument doc; String templatePath = "e:/word/model.docx"; //模板路径 InputStream is = new FileInputStream(templatePath); doc = new XWPFDocument(is); //替换表格里面的变量 xwpfTUtil.replaceInTable(doc, params); FileOutputStream fos = new FileOutputStream("e:/word/ddd.docx");//生成文档的路径 doc.write(fos); xwpfTUtil.close(fos); fos.flush(); fos.close(); } }
相关文章推荐
- 使用 poi 根据 word 模板生成 word 文件
- 使用 poi 根据 word 模板生成 word 文件
- java poi操作word模版文件生成表单和修改
- 使用POI分段落生成纯Word动态模板并导入数据
- POI 使用替换字符方式进行模板生成word
- Java:使用POI实现word的docx文件的模板功能
- java通过poi-tl使用word模版生成word文件
- 记录使用freemarker生成word的模板ftl文件以及word的遍历数据
- java poi 基于模板文件替换字符生成word文档
- 使用freemaker模板生成word文档
- fatal error C1047 对象或库文件“....Win32Release xxx.obj”是使用比创建其他对象所用编译器旧的编译器创建的;请重新生成旧的对象和库
- 【Java】使用模板生成word文档到服务器,并下载
- java 生成excel利器!基于jxls2写的jxls增强版jxlss。使用excel模板生成excel文件
- poi操作excel导出是否修改模板文件内容的问题
- 使用POI读写word docx文件
- Java使用iText生成word文件的完美解决方案(亲测可行)
- itext使用模板生成pdf文件
- 使用C# 怎么生成.db后缀的文件,并且能够使用sql语言进行读取等 操作
- poi使用模板导出word带图片
- 使用POI生成Excel文件,可以自动调整excel列宽 .