栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多种方式动态生成doc文档

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多种方式动态生成doc文档

本来是要在Android端生成doc的(这需求...),最后方法没有好的方法能够在Android上做到完美,最后还是只能搬迁到服务器。不浪费,还是记录下各框架不支持Android的原因以及他们的特点。Java相关的这类框架还是很多的,有几个还不错,可惜要么不支持Android,要么要收费还价格不低。 

经过亲自测试,Android不支持Java的awt很多包不能直接在Android上用,FreeMarker挺不错的,能生成复杂漂亮的doc,可惜不支持Android。用POI在Android上能运行,但是一路因为版本,格式等走了很多坑,用WFS打开还是乱码。Jword、Aspose.word能完美支持,Jword试用期只有30天两者收费都不菲。itext没有测试,不过听说也不支持Android。 

方法一:freemarker 

该方法需要先手动创建一个doc模板(图片记得使用占位符),并保存为xml文件。通过动态替换特定标签${}中的内容生成。example: 

先上效果图:

public class DocUtil {
 public Configuration configure=null;
 
 public DocUtil(){
  configure=new Configuration(Configuration.VERSION_2_3_22);
  configure.setDefaultEncoding("utf-8");
 }
 
 public void createDoc(Map dataMap,String downloadType,String savePath){
  try {
   //加载需要装填的模板
   Template template=null;
   //设置模板装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载。
   //加载模板文件,放在testDoc下
   configure.setClassForTemplateLoading(this.getClass(), "/testDoc");
   //设置对象包装器
//   configure.setObjectWrapper(new DefaultObjectWrapper());
   //设置异常处理器
   configure.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
   //定义Template对象,注意模板类型名字与downloadType要一致
   template=configure.getTemplate(downloadType+".xml");
   File outFile=new File(savePath);
   Writer out=null;
   out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
   template.process(dataMap, out);
   out.close();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (TemplateException e) {
   e.printStackTrace();
  }
 }
 
 public String getImageStr(String imgFile){
  InputStream in=null;
  byte[] data=null;
  try {
   in=new FileInputStream(imgFile);
   data=new byte[in.available()];
   in.read(data);
   in.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  base64Encoder encoder=new base64Encoder();
  return encoder.encode(data);
 }
}

public class TestDoc {
 public static void main(String[] args) {
  DocUtil docUtil=new DocUtil();
  Map dataMap=new HashMap();
  dataMap.put("name", "Joanna");
  dataMap.put("examNum", "111111111111");
  dataMap.put("IDCard", "222222222222222222");
  dataMap.put("carModel", "C1");
  dataMap.put("drivingSchool", "测试驾校");
  dataMap.put("busyType", "初次申领");
  dataMap.put("examDate", "2016-03-10");
  dataMap.put("orderCount", "第1次");
  dataMap.put("userImg1", docUtil.getImageStr("D:\Img\userImg1.png"));
  dataMap.put("userImg2", docUtil.getImageStr("D:\Img\userImg2.png"));
  dataMap.put("firstExamTime", "12:41:17-12:44:38");
  dataMap.put("firstExamScores", "0分,不及格");
  dataMap.put("firstDeductItem", "12:44:15 20102 1号倒车入库,车身出线 扣100分");
  dataMap.put("firstPic1", docUtil.getImageStr("D:\Img\firstPic1.png"));
  dataMap.put("firstPic2", docUtil.getImageStr("D:\Img\firstPic2.png"));
  dataMap.put("firstPic3", docUtil.getImageStr("D:\Img\firstPic3.png"));
  dataMap.put("secondExamTime", "12:46:50-13:05:37");
  dataMap.put("secondExamScores", "90分,通过");
  dataMap.put("secondDeductItem", "");
  dataMap.put("secondPic1", docUtil.getImageStr("D:\Img\secondPic1.png"));
  dataMap.put("secondPic2", docUtil.getImageStr("D:\Img\secondPic2.png"));
  dataMap.put("secondPic3", docUtil.getImageStr("D:\Img\secondPic3.png"));
  docUtil.createDoc(dataMap, "baseDoc", "D:\yanqiong.doc");
 }
}

xml文件太长,就不贴了... 

最后附上Android不能使用的原因:http://stackoverflow.com/questions/25929542/use-freemarker-library-in-android 

补充关于动态显示list以及换行的问题 

需求明确到:在上面的扣分项中,如果我有几条扣分项,我希望每显示一条换行。 

直接在要显示的内容上加换行符,并没有什么效果,起不到换行的作用。 

其中在加ftl标签时,如<#list>,就会出现一些问题,在xml中并不识别,导致项目不能运行。 

解决: 

在需要显示多条扣分项的位置加,并加换行符: 

<#list firstDeductItem as firstItem>
     ${firstItem}

TestDoc.java中改为: 

List Strs=new ArrayList();
Strs.add("1111111111111111111");
Strs.add("222222222222222");
Strs.add("333333333333333");
dataMap.put("firstDeductItem", Strs);

DocUtil.java中改为: 

//定义Template对象,注意模板类型名字与downloadType要一致
template=configure.getTemplate(downloadType+".ftl");此时xml文件会报错,当然也不能编译运行项目,需要将.xml文件改为.ftl文件保存。再编译运行,效果图: 

方法二:POI 

用这个方法遇到了很多版本问题,这里是基于POI3.7+Word2007的,测试能够完美运行。 

你需要用Word2007手动生成文档模板(用其他的生成会报错:无法打开文件),并用${}替换需要动态更新的内容,与上面类似,但是不需要你保存为xml文档格式了。 


public class CustomXWPFdocument extends XWPFdocument{
 public CustomXWPFdocument(InputStream in) throws IOException{
  super(in);
 }
 public CustomXWPFdocument(){
  super();
 }
 public CustomXWPFdocument(OPCPackage pkg) throws IOException{
  super(pkg);
 }
 public void createPicture(int id,int width,int height,XWPFParagraph paragraph){
  final int EMU=9525;
  width *=EMU;
  height *=EMU;
  String blipId=((POIXMLdocumentPart) getAllPictures().get(id)).getPackageRelationship().getId(); 
  CTInline inline=paragraph.createRun().getCTR().addNewDrawing().addNewInline();
  String picXml="" 
    + "" 
    + " " 
    + "  " 
    + "   " + "   " 
    + "   " 
    + "   " 
    + "   " 
    + "   " 
    + "   " 
    + "    " 
    + "   " 
    + "   " 
    + "   " 
    + "   " 
    + "    " 
    + "    " 
    + "   " 
    + "   " 
    + "    " 
    + "   " 
    + "   " 
    + "  " 
    + " " + ""; 
  inline.addNewGraphic().addNewGraphicData();
  XmlToken xmlToken=null;
  try {
   xmlToken=XmlToken.Factory.parse(picXml);
  } catch (XmlException e) {
   e.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("测试");
 }
}


public class WordUtil {
 
 public static CustomXWPFdocument generateWord(Map param,String template){
  CustomXWPFdocument doc=null;
  try {
   OPCPackage pack=POIXMLdocument.openPackage(template);
   doc=new CustomXWPFdocument(pack);
   if(param!=null&¶m.size()>0){
    //处理段落
    List paragraphList = doc.getParagraphs(); 
    processParagraphs(paragraphList, param, doc); 
    //处理表格
    Iterator it = doc.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, doc); 
      }
     }
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
  return doc;
 }
 
 
 public static void processParagraphs(List paragraphList,Map param,CustomXWPFdocument doc){ 
  if(paragraphList!=null&¶graphList.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 (Entry entry : param.entrySet()) {
String key=entry.getKey();
if(text.indexOf(key)!=-1){
 isSetText=true;
 Object value=entry.getValue();
 if(value instanceof String){//文本替换
  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());
  byte[] byteArray = (byte[]) pic.get("content");
  ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray); 
  try {
   int ind = doc.addPicture(byteInputStream,picType);
   doc.createPicture(ind, width , height,paragraph); 
  } catch (InvalidFormatException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } 
 }
}
      }
      if(isSetText){
run.setText(text, 0);
      }
     }
    }
   }
  }
 }
 
 
 public 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;
 }
}

public class TestPoi {

 public static void main(String[] args) throws IOException {
  Map param=new HashMap();
  param.put("${name}", "Joanna.Yan");
  param.put("${examNum}", "000000000001");
  param.put("${IDCard}", "111111111111111111");
  param.put("${carModel}", "C1");
  CustomXWPFdocument doc=WordUtil.generateWord(param, "D:\joanna.docx");
  FileOutputStream fopts = new FileOutputStream("D:\yan.docx"); 
  doc.write(fopts); 
  fopts.close(); 
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/149203.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号