Java结合docx4j生成docx文件

平时项目中经常碰到报表的生成,在此简单描述下使用java结合docx4j技术,生成docx文件的一些基本方法,仅供参考,代码如下:

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.imageio.ImageIO;
import javax.xml.bind.JAXBException;

import org.docx4j.XmlUtils;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.model.table.TblFactory;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.BooleanDefaultTrue;
import org.docx4j.wml.CTBorder;
import org.docx4j.wml.CTDocProtect;
import org.docx4j.wml.CTSettings;
import org.docx4j.wml.CTTblLayoutType;
import org.docx4j.wml.CTVerticalJc;
import org.docx4j.wml.FooterReference;
import org.docx4j.wml.Ftr;
import org.docx4j.wml.HdrFtrRef;
import org.docx4j.wml.Jc;
import org.docx4j.wml.JcEnumeration;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.RPr;
import org.docx4j.wml.STAlgClass;
import org.docx4j.wml.STAlgType;
import org.docx4j.wml.STBorder;
import org.docx4j.wml.STCryptProv;
import org.docx4j.wml.STDocProtect;
import org.docx4j.wml.STHint;
import org.docx4j.wml.STTblLayoutType;
import org.docx4j.wml.STVerticalJc;
import org.docx4j.wml.SectPr;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.TblGrid;
import org.docx4j.wml.TblGridCol;
import org.docx4j.wml.TblPr;
import org.docx4j.wml.TblWidth;
import org.docx4j.wml.Tc;
import org.docx4j.wml.TcPr;
import org.docx4j.wml.Tr;
import org.docx4j.wml.TrPr;
import org.docx4j.wml.SectPr.PgMar;
import org.docx4j.wml.TcPrInner.HMerge;
import org.docx4j.wml.TcPrInner.TcBorders;
import org.docx4j.wml.TcPrInner.VMerge;
import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;

/**
 * 功能描述:报表的工具类
 * @author myclover
 *
 */
@SuppressWarnings("all")
public class Docx4jUtils {
	
	/**
	 * 功能描述:创建文档处理包对象
	 * @return  返回值:返回文档处理包对象
	 * @throws Exception
	 * @author myclover
	 */
	public static WordprocessingMLPackage createWordprocessingMLPackage() throws Exception{
		return WordprocessingMLPackage.createPackage();
	}
	
	/**
	 * 功能描述:获取文档的可用宽度
	 * @param wordPackage 文档处理包对象
	 * @return            返回值:返回值文档的可用宽度
	 * @throws Exception
	 * @author myclover
	 */
	private static int getWritableWidth(WordprocessingMLPackage wordPackage)throws Exception{
		return wordPackage.getDocumentModel().getSections().get(0).getPageDimensions().getWritableWidthTwips();
	}
	
	/**
	 * 功能描述:创建文档表格,上下双边框,左右不封口
	 * @param rows    行数
	 * @param cols    列数
	 * @param widths  每列的宽度
	 * @return   返回值:返回表格对象
	 * @author myclover
	 */
	public static Tbl createTable(int rows, int cols, int[] widths) {
		ObjectFactory factory = Context.getWmlObjectFactory();
		Tbl tbl = factory.createTbl();
		// w:tblPr
		StringBuffer tblSb = new StringBuffer();
		tblSb.append("<w:tblPr ").append(Namespaces.W_NAMESPACE_DECLARATION).append(">");
		tblSb.append("<w:tblStyle w:val=\"TableGrid\"/>");
		tblSb.append("<w:tblW w:w=\"0\" w:type=\"auto\"/>");
		//上边框双线
		tblSb.append("<w:tblBorders><w:top w:val=\"double\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>");
		//左边无边框
		tblSb.append("<w:left w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
		//下边框双线
		tblSb.append("<w:bottom w:val=\"double\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>");
		//右边无边框
		tblSb.append("<w:right w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
		tblSb.append("</w:tblBorders>");
		tblSb.append("<w:tblLook w:val=\"04A0\"/>");
		tblSb.append("</w:tblPr>");
		TblPr tblPr = null;
		try {
			tblPr = (TblPr) XmlUtils.unmarshalString(tblSb.toString());
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		tbl.setTblPr(tblPr);
		if (tblPr != null) {
			Jc jc = factory.createJc();
			//单元格居中对齐
			jc.setVal(JcEnumeration.CENTER);
			tblPr.setJc(jc);
			CTTblLayoutType tbll = factory.createCTTblLayoutType();
			// 固定列宽
			tbll.setType(STTblLayoutType.FIXED);
			tblPr.setTblLayout(tbll);
		}
		// <w:tblGrid><w:gridCol w:w="4788"/>
		TblGrid tblGrid = factory.createTblGrid();
		tbl.setTblGrid(tblGrid);
		// Add required <w:gridCol w:w="4788"/>
		for (int i = 1; i <= cols; i++) {
			TblGridCol gridCol = factory.createTblGridCol();
			gridCol.setW(BigInteger.valueOf(widths[i - 1]));
			tblGrid.getGridCol().add(gridCol);
		}
		// Now the rows
		for (int j = 1; j <= rows; j++) {
			Tr tr = factory.createTr();
			tbl.getContent().add(tr);
			// The cells
			for (int i = 1; i <= cols; i++) {
				Tc tc = factory.createTc();
				tr.getContent().add(tc);
				TcPr tcPr = factory.createTcPr();
				tc.setTcPr(tcPr);
				// <w:tcW w:w="4788" w:type="dxa"/>
				TblWidth cellWidth = factory.createTblWidth();
				tcPr.setTcW(cellWidth);
				cellWidth.setType("dxa");
				cellWidth.setW(BigInteger.valueOf(widths[i - 1]));
				tc.getContent().add(factory.createP());
			}

		}
		return tbl;
	}
	
	/**
	 * 功能描述:创建文档表格,全部表格边框都为1
	 * @param rows    行数
	 * @param cols    列数
	 * @param widths  每列的宽度
	 * @return   返回值:返回表格对象
	 * @author myclover
	 */
	public static Tbl createBorderTable(int rows, int cols, int[] widths) {
		ObjectFactory factory = Context.getWmlObjectFactory();
		Tbl tbl = factory.createTbl();
		// w:tblPr
		StringBuffer tblSb = new StringBuffer();
		tblSb.append("<w:tblPr ").append(Namespaces.W_NAMESPACE_DECLARATION).append(">");
		tblSb.append("<w:tblStyle w:val=\"TableGrid\"/>");
		tblSb.append("<w:tblW w:w=\"0\" w:type=\"auto\"/>");
		tblSb.append("<w:tblBorders><w:top w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>");
		tblSb.append("<w:left w:val=\"single\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
		tblSb.append("<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>");
		tblSb.append("<w:right w:val=\"single\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
		tblSb.append("</w:tblBorders>");
		tblSb.append("<w:tblLook w:val=\"04A0\"/>");
		tblSb.append("</w:tblPr>");
		TblPr tblPr = null;
		try {
			tblPr = (TblPr) XmlUtils.unmarshalString(tblSb.toString());
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		tbl.setTblPr(tblPr);
		if (tblPr != null) {
			Jc jc = factory.createJc();
			//单元格居中对齐
			jc.setVal(JcEnumeration.CENTER);
			tblPr.setJc(jc);
			CTTblLayoutType tbll = factory.createCTTblLayoutType();
			// 固定列宽
			tbll.setType(STTblLayoutType.FIXED);
			tblPr.setTblLayout(tbll);
		}
		// <w:tblGrid><w:gridCol w:w="4788"/>
		TblGrid tblGrid = factory.createTblGrid();
		tbl.setTblGrid(tblGrid);
		// Add required <w:gridCol w:w="4788"/>
		for (int i = 1; i <= cols; i++) {
			TblGridCol gridCol = factory.createTblGridCol();
			gridCol.setW(BigInteger.valueOf(widths[i - 1]));
			tblGrid.getGridCol().add(gridCol);
		}
		// Now the rows
		for (int j = 1; j <= rows; j++) {
			Tr tr = factory.createTr();
			tbl.getContent().add(tr);
			// The cells
			for (int i = 1; i <= cols; i++) {
				Tc tc = factory.createTc();
				tr.getContent().add(tc);
				TcPr tcPr = factory.createTcPr();
				tc.setTcPr(tcPr);
				// <w:tcW w:w="4788" w:type="dxa"/>
				TblWidth cellWidth = factory.createTblWidth();
				tcPr.setTcW(cellWidth);
				cellWidth.setType("dxa");
				cellWidth.setW(BigInteger.valueOf(widths[i - 1]));
				tc.getContent().add(factory.createP());
			}
			
		}
		return tbl;
	}
	
	/**
	 * 功能描述:创建文档表格,上下双边框,左右不封口
	 * @param wordPackage  文档处理包对象
	 * @param rows         表格行数
	 * @param cols         表格列数
	 * @param tableWidth   表格的宽度
	 * @param style        表格的样式
	 * @param jcEnumerationVal 表格的对齐方式
	 * @return             返回值:返回表格对象
	 * @throws Exception
	 * @author myclover
	 */
	private static Tbl createTable(WordprocessingMLPackage wordPackage , int rows , int cols , String tableWidth , String style , JcEnumeration jcEnumerationVal)throws Exception{
		int writableWidthTwips = getWritableWidth(wordPackage);
		if(cols == 0){
			cols = 1;
		}
		int cellWidth = new Double(Math.floor( (writableWidthTwips/cols ))).intValue();
		int[] widths = new int[cols];
		for(int i = 0 ; i < cols ; i++){
			widths[i] = cellWidth;
		}
		return createTable(rows, cols, widths);
	}
	
	/**
	 * 功能描述:创建文档表格,表格的默认宽度为:表格样式:dxa,对齐方式:居中
	 * @param wordPackage 文档处理包对象
	 * @param rows        表格行数
	 * @param cols        表格列数
	 * @param tableWidth  表格宽度
	 * @return            返回值:返回表格对象
	 * @throws Exception
	 * @author myclover
	 */
	public static Tbl createTable(WordprocessingMLPackage wordPackage , int rows , int cols , String tableWidth) throws Exception{
		return createTable(wordPackage, rows, cols, tableWidth , "dxa", JcEnumeration.CENTER);
	}
	
	/**
	 * 功能描述:创建文档表格,表格的默认宽度为:9328,表格样式:dxa,对齐方式:居中
	 * @param wordPackage 文档处理包对象
	 * @param rows        表格行数
	 * @param cols        表格列数
	 * @return            返回值:返回表格对象
	 * @throws Exception
	 * @author myclover
	 */
	public static Tbl createTable(WordprocessingMLPackage wordPackage , int rows , int cols) throws Exception{
		return createTable(wordPackage, rows, cols, "9328", "dxa", JcEnumeration.CENTER);
	}
	
	/**
	 * 功能描述:往文档对象中添加相应的内容
	 * @param wordPackage  文档处理包对象
	 * @param info         需要添加的信息
	 * @param unmarshal    是否有样式,表格对象默认不用
	 * @throws Exception
	 * @author myclover
	 */
	private static void addObject(WordprocessingMLPackage wordPackage , Object info , boolean unmarshal)throws Exception{
		if(unmarshal){
			wordPackage.getMainDocumentPart().addObject(org.docx4j.XmlUtils.unmarshalString(String.valueOf(info)));
		}else{
			wordPackage.getMainDocumentPart().addObject(info);
		}
	}
	
	/**
	 * 功能描述:往文档中添加内容
	 * @param wordPackage  文档处理包对象
	 * @param info         文档内容
	 * @throws Exception
	 * @author myclover
	 */
	public static void addObject(WordprocessingMLPackage wordPackage , Object info)throws Exception{
		addObject(wordPackage, info, true);
	}
	
	/**
	 * 功能描述:往文档中添加表格
	 * @param wordPackage  文档处理包对象
	 * @param tbl          表格
	 * @throws Exception
	 * @author myclover
	 */
	public static void addObjectForTbl(WordprocessingMLPackage wordPackage , Tbl tbl)throws Exception{
		addObject(wordPackage, tbl, false);
	}
	
	/**
	 * 功能描述:保存文档信息
	 * @param wordPackage  文档处理包对象
	 * @param fileName     完整的输出文件名称,包括路径
	 * @throws Exception
	 * @author myclover
	 */
	public static void saveWordPackage(WordprocessingMLPackage wordPackage , String fileName)throws Exception{
		saveWordPackage(wordPackage, new File(fileName));
	}
	
	/**
	 * 功能描述:保存文档信息
	 * @param wordPackage  文档处理包对象
	 * @param file         文件
	 * @throws Exception
	 * @author myclover
	 */
	public static void saveWordPackage(WordprocessingMLPackage wordPackage , File file)throws Exception{
		wordPackage.save(file);
	}
	
	/**
	 * 功能描述:设置页边距
	 * @param wordPackage 文档处理包对象
	 * @param top    上边距
	 * @param bottom 下边距
	 * @param left   左边距
	 * @param right  右边距
	 * @author myclover
	 */
	public static void setMarginSpace(WordprocessingMLPackage wordPackage , String top , String bottom , String left , String right ){
		ObjectFactory factory = Context.getWmlObjectFactory();
		PgMar pg = factory.createSectPrPgMar();
		pg.setTop(new BigInteger(top));
		pg.setBottom(new BigInteger(bottom));
		pg.setLeft(new BigInteger(left));
		pg.setRight(new BigInteger(right));
		wordPackage.getDocumentModel().getSections().get(0).getSectPr().setPgMar(pg);
	}
	
	/**
	 * 功能描述:设置页边距,上下边距都为1440,2.54厘米
	 * @param wordPackage 文档处理包对象
	 * @param left   左边距
	 * @param right  右边距
	 * @author myclover
	 */
	public static void setMarginSpace(WordprocessingMLPackage wordPackage , String left , String right ){
		setMarginSpace(wordPackage, "1440", "1440", left, right);
	}
	
	/**
	 * 功能描述:设置页边距,上下边距都为1440,2.54厘米,左右边距都为1797,3.17厘米
	 * @param wordPackage 文档处理包对象
	 * @author myclover
	 */
	public static void setMarginSpace(WordprocessingMLPackage wordPackage){
		setMarginSpace(wordPackage, "1440", "1440", "1797", "1797");
	}
	
	/**
	 * 功能描述:设置字体的样式
	 * @param fontFamily      字体类型
	 * @param colorVal        字体颜色
	 * @param hpsMeasureSize  字号大小
	 * @param sTHint          字体格式
	 * @param isBlod          是否加粗
	 * @return                返回值:返回字体样式对象
	 * @throws Exception
	 * @author myclover
	 */
	private static RPr getRPr(String fontFamily , String colorVal , String hpsMeasureSize , STHint sTHint , boolean isBlod){
		ObjectFactory factory = Context.getWmlObjectFactory();
		RPr rPr = factory.createRPr();
		
		org.docx4j.wml.RFonts rf = new org.docx4j.wml.RFonts();
		rf.setHint(sTHint);
		rf.setAscii(fontFamily);
		rf.setHAnsi(fontFamily);
		rPr.setRFonts(rf);
		
		BooleanDefaultTrue bdt = Context.getWmlObjectFactory().createBooleanDefaultTrue();
		rPr.setBCs(bdt);
		if(isBlod){
			rPr.setB(bdt);
		}
		org.docx4j.wml.Color color = new org.docx4j.wml.Color();
		color.setVal(colorVal);
		rPr.setColor(color);

		org.docx4j.wml.HpsMeasure sz = new org.docx4j.wml.HpsMeasure();
		sz.setVal(new BigInteger(hpsMeasureSize));
		rPr.setSz(sz);
		rPr.setSzCs(sz);
		
		return rPr;
	}
	
	/**
	 * 功能描述:设置字体的样式,宋体,黑色,18号
	 * @param isBlod          是否加粗
	 * @return                返回值:返回字体样式对象
	 * @throws Exception
	 * @author myclover
	 */
	private static RPr getRPr(boolean isBlod){
		return getRPr("宋体", "000000", "18", STHint.EAST_ASIA, isBlod);
	}
	
	/**
	 * 功能描述:设置字体的样式,黑色,18号
	 * @param fontFamily      字体
	 * @param isBlod          是否加粗
	 * @return                返回值:返回字体样式对象
	 * @throws Exception
	 * @author myclover
	 */
	private static RPr getRPr(String fontFamily , boolean isBlod){
		return getRPr(fontFamily, "000000", "18", STHint.EAST_ASIA, isBlod);
	}
	
	/**
	 * 功能描述:设置字体的样式,黑色
	 * @param fontFamily      字体
	 * @param hpsMeasureSize  字号的大小
	 * @param isBlod          是否加粗
	 * @return                返回值:返回字体样式对象
	 * @throws Exception
	 * @author myclover
	 */
	private static RPr getRPr(String fontFamily , String hpsMeasureSize , boolean isBlod){
		return getRPr(fontFamily, "000000", hpsMeasureSize, STHint.EAST_ASIA, isBlod);
	}
	
	/**
	 * 功能描述:获取单元格边框样式
	 * @param type    单元格类型,0表示无边框,2表示双线边框,其他表示单线边框
	 * @param color   边框颜色
	 * @param border  边框大小
	 * @param space   间距
	 * @return        返回值:返回边框对象
	 * @author myclover
	 */
	private static CTBorder getCTBorder(int type , String color , String border , String space){
		CTBorder ctb = new CTBorder();
		if(type == 0){
			ctb.setVal(STBorder.NIL);
		}else{
			ctb.setColor(color);
			ctb.setSz(new BigInteger(border));
			ctb.setSpace(new BigInteger(space));
			if(type == 2){
				ctb.setVal(STBorder.DOUBLE);
			}else{
				ctb.setVal(STBorder.SINGLE);
			}
		}
		return ctb;
	}
	
	/**
	 * 功能描述:设置单元格内容对齐方式
	 * @param p  内容
	 * @param jcEnumeration  对齐方式
	 * @author myclover
	 */
	public static void setCellContentStyle(P p , JcEnumeration jcEnumeration){
		PPr pPr = p.getPPr();
		if(pPr == null){
			ObjectFactory factory = Context.getWmlObjectFactory();
			pPr = factory.createPPr();
		}
		org.docx4j.wml.Jc jc = pPr.getJc();
		if(jc == null){
			jc = new org.docx4j.wml.Jc();
		}
		jc.setVal(jcEnumeration);
		pPr.setJc(jc);
		p.setPPr(pPr);
	}
	
	/**
	 * 功能描述:设置单元格内容对齐方式,居中对齐
	 * @param p  内容
	 * @author myclover
	 */
	public static void setCellContentStyle(P p){
		setCellContentStyle(p, JcEnumeration.CENTER);
	}
	
	
	/**
	 * 功能描述:填充表格内容
	 * @param wordPackage  文档处理包对象
	 * @param tbl          表格对象
	 * @param dataList     表格数据
	 * @param titleList    表头数据
	 * @param isFixedTitle 是否固定表头
	 * @param tFontFamily  表头字体
	 * @param tFontSize    表头字体大小
	 * @param tIsBlod      表头是否加粗
	 * @param tJcEnumeration 表头对齐方式
	 * @param fontFamily   表格字体
	 * @param fontSize     表格字号
	 * @param isBlod       表格内容是否加粗
	 * @param jcEnumeration 表格对齐方式
	 * @author myclover
	 */
	private static void fillTableData(WordprocessingMLPackage wordPackage , Tbl tbl , List dataList , List titleList , boolean isFixedTitle,String tFontFamily , String tFontSize , boolean tIsBlod , JcEnumeration tJcEnumeration,String fontFamily , String fontSize , boolean isBlod , JcEnumeration jcEnumeration){
		List rowList = tbl.getContent();
		//整个表格的行数
		int rows = rowList.size();
		int tSize = 0;
		//表头
		if(titleList != null && titleList.size() > 0){
			tSize = titleList.size();
			for(int t = 0 ; t < tSize ; t++){
				Object[] tobj = (Object[]) titleList.get(t);
				Tr tr0 = (Tr) XmlUtils.unwrap(rowList.get(t));
				List colList = tr0.getContent();
				for(int c = 0 ; c < colList.size() ; c++){
					Tc tc0 = (Tc) XmlUtils.unwrap(colList.get(c));
					//填充表头数据
					fillCellData(tc0, converObjToStr(tobj[c], ""), tFontFamily, tFontSize, tIsBlod, tJcEnumeration);
				}
				if(isFixedTitle){
					//设置固定表头
					fixedTitle(tr0);
				}
			}
		}
		int colsSize = 1;
		//表格数据,去掉表头之后的表格数据
		for(int r = tSize ; r < rows ; r++){
			Tr tr = (Tr) XmlUtils.unwrap(rowList.get(r));
			Object[] objs = null;
			//如果表格内容不为空,则取出相应的数据进行填充
			if(dataList != null && (dataList.size() >= (rows - tSize))){
				objs = (Object[]) dataList.get(r - tSize);
			}
			List colsList = tr.getContent();
			//整个表格的列数
			colsSize = colsList.size();
			for(int i = 0 ; i < colsSize ; i++){
				Tc tc = (Tc) XmlUtils.unwrap(colsList.get(i));
				//填充表格数据
				if(objs != null){
					fillCellData(tc, converObjToStr(objs[i], ""), fontFamily, fontSize, isBlod, jcEnumeration);
				}else{
					fillCellData(tc, "", fontFamily, fontSize, isBlod, jcEnumeration);
				}
			}
		}
	}
	
	/**
	 * 功能描述:填充表格内容,固定表头,表头宋体加粗,小五号,表格内容宋体,小五号,表格居中对齐</BR>
	 * 			其中表格数据跟表头数据结构要一致,适用于简单的n行m列的普通表格
	 * @param wordPackage  文档处理包对象
	 * @param tbl          表格对象
	 * @param dataList     表格数据
	 * @param titleList    表头数据,如果不需要表头信息,则只要传入null即可
	 * @author myclover
	 */
	public static void fillTableData(WordprocessingMLPackage wordPackage , Tbl tbl , List dataList , List titleList){
		fillTableData(wordPackage, tbl, dataList, titleList, true, "宋体", "18", true, JcEnumeration.CENTER, "宋体", "18", false, JcEnumeration.CENTER);
	}
	
	/**
	 * 功能描述:固定表头
	 * @param tr 行对象
	 * @author myclover
	 */
	public static void fixedTitle(Tr tr){
		ObjectFactory factory = Context.getWmlObjectFactory();
		BooleanDefaultTrue bdt = factory.createBooleanDefaultTrue();
		//表示固定表头
		bdt.setVal(true);
		TrPr trpr = tr.getTrPr();
		if(trpr == null){
			trpr = factory.createTrPr();
		}
		trpr.getCnfStyleOrDivIdOrGridBefore().add(factory.createCTTrPrBaseTblHeader(bdt));
		tr.setTrPr(trpr);
	}
	
	/**
	 * 功能描述:填充单元格内容
	 * @param tc          单元格对象
	 * @param data        内容
	 * @param fontFamily  字体
	 * @param fontSize    字号
	 * @param isBlod      是否加粗
	 * @param jcEnumeration 对齐方式
	 * @author myclover
	 */
	private static void fillCellData(Tc tc , String data , String fontFamily , String fontSize , boolean isBlod , JcEnumeration jcEnumeration){
		ObjectFactory factory = Context.getWmlObjectFactory();
		org.docx4j.wml.P p = (P) XmlUtils.unwrap(tc.getContent().get(0));
		//设置表格内容的对齐方式
		setCellContentStyle(p , jcEnumeration);
		org.docx4j.wml.Text t = factory.createText();
		t.setValue(data);
		org.docx4j.wml.R run = factory.createR();
		//设置表格内容字体样式
		run.setRPr(getRPr(fontFamily, fontSize, isBlod));
		TcPr tcpr = tc.getTcPr();
		if(tcpr == null){
			tcpr = factory.createTcPr();
		}
		//设置内容垂直居中
		CTVerticalJc valign = factory.createCTVerticalJc();
		valign.setVal(STVerticalJc.CENTER);
		tcpr.setVAlign(valign);
		run.getContent().add(t);
		p.getContent().add(run);
	}
	
	/**
	 * 功能描述:填充单元格内容,小五号,宋体,内容居中
	 * @param tc     单元格对象
	 * @param data   数据
	 * @param isBlod 是否加粗
	 * @author myclover
	 */
	public static void fillCellData(Tc tc , String data , boolean isBlod ){
		fillCellData(tc, data, "宋体", "18", isBlod, JcEnumeration.CENTER);
	}
	
	
	/**
	 * 功能描述:获取文字信息
	 * @param content  文字信息
	 * @return  返回值:返回值指定样式的信息
	 * @author myclover
	 */
	public static String getContentInfo(String content){
		StringBuffer sb = new StringBuffer();
		sb.append("<w:p xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" >");
		sb.append("<w:pPr><w:spacing w:line=\"360\" w:lineRule=\"auto\"/><w:ind w:firstLineChars=\"200\" w:firstLine=\"480\"/>");
		sb.append("<w:rPr><w:rFonts w:asciiTheme=\"minorEastAsia\" w:hAnsiTheme=\"minorEastAsia\"/>");
		sb.append("<w:sz w:val=\"24\"/><w:szCs w:val=\"24\"/></w:rPr></w:pPr><w:r w:rsidRPr=\"00792470\"><w:rPr>");
		sb.append("<w:rFonts w:asciiTheme=\"minorEastAsia\" w:hAnsiTheme=\"minorEastAsia\" w:hint=\"eastAsia\"/>");
		sb.append("<w:sz w:val=\"24\"/><w:szCs w:val=\"24\"/></w:rPr><w:t>");
		sb.append(content);
		sb.append("</w:t></w:r></w:p>");
		return sb.toString();
	}
	
	/**
	 * 功能描述:合并单元格</BR>
	 *			表示合并第startRow(开始行)行中的第startCol(开始列)列到(startCol + colSpan - 1)列 </BR>
	 *			表示合并第startCol(开始列)行中的第startRow(开始行)列到(startRow + rowSpan - 1)行
	 * @param tc          单元格对象
	 * @param currentRow  当前行号,传入的是遍历表格时的行索引参数
	 * @param startRow    开始行
	 * @param rowSpan     合并的行数,大于1才表示合并
	 * @param currentCol  当前列号,传入的是遍历表格时的列索引参数
	 * @param startCol    开始列
	 * @param colSpan     合并的列数,大于1才表示合并
	 * @author myclover
	 */
	public static void setCellMerge(Tc tc , int currentRow , int startRow , int rowSpan , int currentCol , int startCol , int colSpan){
		ObjectFactory factory = Context.getWmlObjectFactory();
		TcPr tcpr = tc.getTcPr();
		if(tcpr == null){
			tcpr = factory.createTcPr();
		}
		//表示合并列
		if(colSpan > 1){
			//表示从第startRow行开始
			if(currentRow == startRow){
				//表示从第startRow行的第startCol列开始合并,合并到第startCol + colSpan - 1列
				if(currentCol == startCol){
					HMerge hm = factory.createTcPrInnerHMerge();
					hm.setVal("restart");
					tcpr.setHMerge(hm);
					tc.setTcPr(tcpr);
				}else if(currentCol > startCol && currentCol <= (startCol + colSpan - 1)){
					HMerge hm = factory.createTcPrInnerHMerge();
					tcpr.setHMerge(hm);
					tc.setTcPr(tcpr);
				}
			}
		}
		//表示合并行
		if(rowSpan > 1){
			//表示从第startCol列开始
			if(currentCol == startCol){
				//表示从第startCol列的第startRow行始合并,合并到第startRow + rowSpan - 1行
				if(currentRow == startRow){
					VMerge vm = factory.createTcPrInnerVMerge();
					vm.setVal("restart");
					tcpr.setVMerge(vm);
					tc.setTcPr(tcpr);
				}else if(currentRow > startRow && currentRow <= (startRow + rowSpan - 1)){
					VMerge vm = factory.createTcPrInnerVMerge();
					tcpr.setVMerge(vm);
					tc.setTcPr(tcpr);
				}
			}
		}
		
	}
	
	/**
	 * 功能描述:合并单元格,相当于跨列的效果</BR>
	 *			表示合并第startRow(开始行)行中的第startCol(开始列)列到(startCol + colSpan - 1)列 </BR>
	 * @param tc          单元格对象
	 * @param currentRow  当前行号,传入的是遍历表格时的行索引参数
	 * @param startRow    开始行
	 * @param currentCol  当前列号,传入的是遍历表格时的列索引参数
	 * @param startCol    开始列
	 * @param colSpan     合并的列数,大于1才表示合并
	 * @author myclover
	 */
	public static void setCellHMerge(Tc tc , int currentRow , int startRow , int currentCol , int startCol , int colSpan){
		setCellMerge(tc, currentRow, startRow, 1, currentCol, startCol, colSpan);
	}
	
	/**
	 * 功能描述:合并单元格,相当于跨行的效果</BR>
	 *			表示合并第startCol(开始列)行中的第startRow(开始行)列到(startRow + rowSpan - 1)行
	 * @param tc          单元格对象
	 * @param currentRow  当前行号,传入的是遍历表格时的行索引参数
	 * @param startRow    开始行
	 * @param rowSpan     合并的行数,大于1才表示合并
	 * @param currentCol  当前列号,传入的是遍历表格时的列索引参数
	 * @param startCol    开始列
	 * @author myclover
	 */
	public static void setCellVMerage(Tc tc , int currentRow , int startRow , int rowSpan , int currentCol , int startCol){
		setCellMerge(tc, currentRow, startRow, rowSpan, currentCol, startCol, 1);
	}
	
	/**
	 * 功能描述:设置文档是否只读,包括内容和样式
	 * @param wordPackage  文档处理包对象
	 * @param isReadOnly   是否只读
	 * @throws Exception
	 * @author myclover
	 */
	public static void setReadOnly(WordprocessingMLPackage wordPackage , boolean isReadOnly)throws Exception{
		byte[] bt = "".getBytes();
		if(isReadOnly){
			bt = "123456".getBytes();
		}
		ObjectFactory factory = Context.getWmlObjectFactory();
		//创建设置文档对象
		DocumentSettingsPart ds = wordPackage.getMainDocumentPart().getDocumentSettingsPart();
		if(ds == null){
			ds = new DocumentSettingsPart();
		}
		CTSettings cs = ds.getJaxbElement();
		if(cs == null){
			cs = factory.createCTSettings();
		}
		//创建文档保护对象
		CTDocProtect cp = cs.getDocumentProtection();
		if(cp == null){
			cp = new CTDocProtect();
		}
		//设置加密方式
		cp.setCryptProviderType(STCryptProv.RSA_AES);
		cp.setCryptAlgorithmClass(STAlgClass.HASH);
		//设置任何用户
		cp.setCryptAlgorithmType(STAlgType.TYPE_ANY);
		cp.setCryptAlgorithmSid(new BigInteger("4"));
		cp.setCryptSpinCount(new BigInteger("50000"));
		//只读
		if(isReadOnly){
			cp.setEdit(STDocProtect.READ_ONLY);
			cp.setHash(bt);
			cp.setSalt(bt);
			//设置内容不可编辑
			cp.setEnforcement(true);
			//设置格式不可编辑
			cp.setFormatting(true);
		}else{
			cp.setEdit(STDocProtect.NONE);
			cp.setHash(null);
			cp.setSalt(null);
			//设置内容不可编辑
			cp.setEnforcement(false);
			//设置格式不可编辑
			cp.setFormatting(false);
		}
		
		cs.setDocumentProtection(cp);
		ds.setJaxbElement(cs);
		//添加到文档主体中
		wordPackage.getMainDocumentPart().addTargetPart(ds);
	}
	
	/**
	 * 功能描述:设置文档是否只读,包括内容和样式
	 * @param fileName    文件
	 * @param isReadOnly  是否只读
	 * @return            返回值:设置成功,则返回true,否则返回false
	 * @throws Exception
	 * @author myclover
	 */
	public static boolean setReadOnly(String fileName , boolean isReadOnly)throws Exception{
		try {
			File file = new File(fileName);
			if (!file.exists()) {
				return false;
			}
			//加载需要设置只读的文件
			WordprocessingMLPackage wordPackage = WordprocessingMLPackage.load(file);
			//设置只读
			setReadOnly(wordPackage, isReadOnly);
			//保存文件
			saveWordPackage(wordPackage, file);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * 功能描述:插入页脚条形码
	 * @param wordPackage 文档处理包对象
	 * @param code        条形码编码
	 * @author myclover
	 */
	public static void insertFooterImage(WordprocessingMLPackage wordPackage , String code)throws Exception {
		try {
			createFooterReference(wordPackage, createFooterPart(wordPackage, code));
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("insertFooterImage 插入页脚的条形码失败:" , e);
		}
	}
	
	/**
	 * 功能描述:创建页脚信息 
	 * @param wordPackage  文档处理包对象
	 * @param relationship 关联对象
	 * @throws Exception
	 * @author myclover
	 */
	private static void createFooterReference(WordprocessingMLPackage wordPackage,Relationship relationship )throws Exception {
		org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
		List<SectionWrapper> sections = wordPackage.getDocumentModel().getSections();
		SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
		if (sectPr == null ) {
			sectPr = factory.createSectPr();
			wordPackage.getMainDocumentPart().addObject(sectPr);
			sections.get(sections.size() - 1).setSectPr(sectPr);
		}
		FooterReference headerReference = factory.createFooterReference();
		headerReference.setId(relationship.getId());
		headerReference.setType(HdrFtrRef.DEFAULT);
		sectPr.getEGHdrFtrReferences().add(headerReference);
	}
	
	/**
	 * 功能描述:创建页脚部分
	 * @param wordPackage  文档处理包对象
	 * @param code         条形码编码
	 * @return
	 * @throws Exception
	 * @author myclover
	 */
	private static Relationship createFooterPart(WordprocessingMLPackage wordPackage , String code)throws Exception {
		FooterPart footerPart = new FooterPart();
		footerPart.setPackage(wordPackage);
		footerPart.setJaxbElement(getFtr(wordPackage , footerPart , code));
		return wordPackage.getMainDocumentPart().addTargetPart(footerPart);
	}
	
	/**
	 * 功能描述:获取页脚内容
	 * @param wordPackage  文档处理包对象
	 * @param sourcePart   源部分
	 * @param code         条形码编码
	 * @return
	 * @throws Exception
	 * @author myclover
	 */
	private static Ftr getFtr(WordprocessingMLPackage wordPackage,Part sourcePart , String code) throws Exception {
		org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
		Ftr ftr = factory.createFtr();
		byte[] bt = generateCode39Barcode(code);
		ftr.getContent().add(getPImage(wordPackage,sourcePart, bt, "filename", "alttext", 1, 2));
		return ftr;
	}
	
	/**
	 * 功能描述:创建页脚条形码图片信息
	 * @param wordPackage  文档处理包对象
	 * @param sourcePart   源部分
	 * @param bytes        字节数组
	 * @param filenameHint 图片名称
	 * @param altText      提示信息
	 * @param id1          id1
	 * @param id2          id2
	 * @return
	 * @throws Exception
	 * @author myclover
	 */
	private static org.docx4j.wml.P getPImage( WordprocessingMLPackage wordPackage,Part sourcePart,byte[] bytes,
			String filenameHint, String altText, 
			int id1, int id2) throws Exception {
        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordPackage,sourcePart, bytes);
        Inline inline = imagePart.createImageInline(filenameHint, altText, id1, id2, false);
		org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
		org.docx4j.wml.P  p = factory.createP();
		org.docx4j.wml.R  run = factory.createR();		
		p.getContent().add(run);        
		org.docx4j.wml.Drawing drawing = factory.createDrawing();		
		run.getContent().add(drawing);		
		drawing.getAnchorOrInline().add(inline);
		PPr pPr = p.getPPr();
		if(pPr == null){
			pPr = factory.createPPr();
		}
		Jc jc = pPr.getJc();
		if(jc == null){
			jc = new org.docx4j.wml.Jc();
		}
		//页脚条形码所处位置
		jc.setVal(JcEnumeration.RIGHT);
		pPr.setJc(jc);
		p.setPPr(pPr);
		return p;
	}	
	
	/**
	 * 功能描述:生成条形码
	 * @param code 条形码编码
	 * @return
	 * @throws Exception
	 * @author myclover
	 */
	private static byte[] generateCode39Barcode(String code)throws Exception{
		Code39Bean bean = new Code39Bean();   
	    //每英寸所打印的点数或线数,用来表示打印机打印分辨率。   
	    final int dpi = 200;   
	    bean.setModuleWidth(0.15);   
	    bean.setHeight(10);   
	    bean.setWideFactor(3);   
	    bean.doQuietZone(true);   
	    ByteArrayOutputStream out = null;
	    try {
			out = new ByteArrayOutputStream();
			BitmapCanvasProvider canvas = new BitmapCanvasProvider(dpi,BufferedImage.TYPE_BYTE_GRAY, true, 0);   
	        bean.generateBarcode(canvas, code);   
	        canvas.finish();   
	        BufferedImage barcodeImage = canvas.getBufferedImage();   
	        ImageIO.write(barcodeImage, "jpeg", out);  
	        out.flush();
			return out.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(out != null){
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
	
	/**
	 * 功能描述:Object数据转换为String类型
	 * @param obj  
	 * @param defaultStr 如果obj对象为空,则返回的值
	 * @return
	 * @author myclover
	 */
	public static String converObjToStr(Object obj , String defaultStr){
		if(obj != null){
			return obj.toString();
		}
		return defaultStr;
	}
	
}

你可能感兴趣的:(java,docx,word2010,word2007,docx4j)