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

网友投稿 386 2023-07-06


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");

}

/**

* 根据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}

#list>

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=""

+ ""

+ " "

+ " "

+ " " + "

+ id

+ "\" name=\"Generated\"/>"

+ " "

+ "

"

+ id

+ "\" name=\"Generated\"/>"

+ " "

+ "

+ " "

+ "

+ blipId

+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ "

+ width

+ "\" cy=\""

+ height

+ "\"/>"

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ " " + "";

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&&param.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) {http://

e.printStackTrace();

}

return doc;

}

/**

* 处理段落

* @param paragraphList

* @param param

* @param doc

*/

public static void processParagraphs(List paragraphList,Map param,CustomXWPFDocument doc){

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 (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();

}

}

+ blipId

+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ "

+ width

+ "\" cy=\""

+ height

+ "\"/>"

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ " " + "";

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&&param.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) {http://

e.printStackTrace();

}

return doc;

}

/**

* 处理段落

* @param paragraphList

* @param param

* @param doc

*/

public static void processParagraphs(List paragraphList,Map param,CustomXWPFDocument doc){

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 (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();

}

}

+ width

+ "\" cy=\""

+ height

+ "\"/>"

+ " "

+ " "

+ " "

+ " "

+ " "

+ " "

+ " " + "";

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&&param.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) {http://

e.printStackTrace();

}

return doc;

}

/**

* 处理段落

* @param paragraphList

* @param param

* @param doc

*/

public static void processParagraphs(List paragraphList,Map param,CustomXWPFDocument doc){

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 (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();

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java interface的两个经典用法
下一篇:Java 高并发六:JDK并发包2详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~