本来是要在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: 

Java多种方式动态生成doc文档_第1张图片

先上效果图:

Java多种方式动态生成doc文档_第2张图片

public class DocUtil { public Configuration configure=null;  public DocUtil(){  configure=new Configuration(Configuration.VERSION_2_3_22);  configure.setDefaultEncoding("utf-8"); } /**  * 根据Doc模板生成word文件  * @param dataMap 需要填入模板的数据  * @param downloadType 文件名称  * @param savePath 保存路径  */ 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文件保存。再编译运行,效果图: 

Java多种方式动态生成doc文档_第3张图片

方法二:POI 

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

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

/** * 自定义XWPFDocument,并重写createPicture()方法 * @author Joanna.Yan * */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("测试"); }}
/** * 适用于word 2007 * poi版本 3.7 * @author Joanna.Yan * */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; }  /**  * 处理段落  * @param paragraphList  * @param param  * @param 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);      }     }    }   }  } }  /**  * 根据图片类型获取对应的图片类型代码  * @param picType  * @return  */ 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();  }}

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

更多相关文章

  1. [Android Studio系列(五)] Android Studio手动配置Gradle的方法
  2. 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrol
  3. Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
  4. Android系统build/core下.mk文件分析
  5. android使用webview上传文件(支持相册和拍照)
  6. Android ImageView使用网络资源文件
  7. Android的文件存储(写入和读取)
  8. Android 照相机打开方法
  9. 文件对应

随机推荐

  1. Android下数据库的解析
  2. android 打包 生成apk 出现的问题 javasc
  3. android选择视频文件上传到后台服务器
  4. Android(安卓)开发 设置banner圆角,滑动时
  5. Android(安卓)ListView 实现 GridView 用
  6. Android(安卓)中文API(86)――ResourceCurs
  7. Android,一个函数实现支付宝...
  8. Android(安卓)Screen Monitor
  9. 面试 | Android(安卓)View、布局、动画、
  10. Android(安卓)Studio教程-创建第一个项目