本来是要在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"); } /**  * 根据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文件保存。再编译运行,效果图: 

方法二: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. 浅谈Java中Collections.sort对List排序的两种方法
  2. NPM 和webpack 的基础使用
  3. Python list sort方法的具体使用
  4. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  5. python list.sort()根据多个关键字排序的方法实现
  6. android Manifest.xml全局配置文件中根标签中package属性及标签
  7. Android高手进阶教程(四)之----Android(安卓)中自定义属性(attr.
  8. Android(安卓)add prebuilt lib(*.so) to Android.mk
  9. Android(安卓)SystemProperties.get()和System.getProperty()的

随机推荐

  1. Android中Context详解——你所不知道的Co
  2. S5PV310 Android(安卓)电容屏驱动调试
  3. 【android】各镜像文件img介绍
  4. ReactNative学习----20ReactNative中调用
  5. Android(安卓)各类优秀依赖库 等各位砖友
  6. Android(安卓)OkHttp3使用http2问题记录
  7. android 音量调整
  8. Android(安卓)Studio 3.5.2版本中Kotlin
  9. 2015最火十大Android开源项目,是个程序员
  10. Android签名过程