POI写入word

package com.test;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFStyle;
import org.apache.poi.xwpf.usermodel.XWPFStyles;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

public class ReadDoc {
	private static Map<String, Map<String, Object>> orderMap = new HashMap<String, Map<String, Object>>();

	public void init(String targetPath, String sourcePath) {
		InputStream is = null;
		XWPFDocument doc = null;
		OutputStream out = null;
		try {
			XWPFDocument createDoc = new XWPFDocument();

			is = new FileInputStream(sourcePath);
			doc = new XWPFDocument(is);
			// 获取段落
			List<XWPFParagraph> paras = doc.getParagraphs();

			for (XWPFParagraph para : paras) {
				// System.out.println(para.getCTP());//得到xml格式
				System.out.println(para.getStyleID());// 段落级别
				System.out.println(para.getParagraphText());// 段落内容

				String titleLvl = getTitleLvl(doc, para);// 获取段落级别
				if ("a5".equals(titleLvl) || "HTML".equals(titleLvl) || "".equals(titleLvl) || null == titleLvl) {
					titleLvl = "8";
				}
				System.out.println(titleLvl + "-----");// 0,1,2
				if (!"8".equals(titleLvl)) {
					System.out.println(titleLvl + "====" + para.getParagraphText());
				}

				XWPFParagraph ctPara = createDoc.createParagraph();
				// 一个XWPFRun代表具有相同属性的一个区域。
				XWPFRun ctRun = ctPara.createRun();
				String ctText = para.getParagraphText();
				ctRun.setFontFamily("宋体");// 字体
				ctRun.setFontSize(12);

				if (null != titleLvl && !"".equals(titleLvl) && !"8".equals(titleLvl)) {
					addCustomHeadingStyle(createDoc, titleLvl, Integer.parseInt(titleLvl));
					String orderCode = getOrderCode(titleLvl);// 获取编号
					ctText = orderCode + " " + ctText;
					ctRun.setBold(true);// 标题加粗
					ctRun.setFontSize(14);

					ctPara.setStyle(titleLvl);

				} else {// 正文
					ctPara.setIndentationFirstLine(567);// 首行缩进:567==1厘米
//                  ctRun.setTextPosition(6);//设置行间距
				}

				ctRun.setText(ctText);// 内容
			}
			out = new FileOutputStream(targetPath);
			createDoc.write(out);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != out) {
					out.close();
				}
				if (null != is) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Word中的大纲级别,可以通过getPPr().getOutlineLvl()直接提取,但需要注意,Word中段落级别,通过如下三种方式定义:
	 * 1、直接对段落进行定义; 2、对段落的样式进行定义; 3、对段落样式的基础样式进行定义。
	 * 因此,在通过“getPPr().getOutlineLvl()”提取时,需要依次在如上三处读取。
	 * 
	 * @param doc
	 * @param para
	 * @return
	 */
	private static String getTitleLvl(XWPFDocument doc, XWPFParagraph para) {
		String titleLvl = "";
		try {
			// 判断该段落是否设置了大纲级别
			if (para.getCTP().getPPr().getOutlineLvl() != null) {
				// System.out.println("getCTP()");
//              System.out.println(para.getParagraphText());
//              System.out.println(para.getCTP().getPPr().getOutlineLvl().getVal());

				return String.valueOf(para.getCTP().getPPr().getOutlineLvl().getVal());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			// 判断该段落的样式是否设置了大纲级别
			if (doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl() != null) {

				// System.out.println("getStyle");
//              System.out.println(para.getParagraphText());
//              System.out.println(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());

				return String.valueOf(
						doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			// 判断该段落的样式的基础样式是否设置了大纲级别
			if (doc.getStyles().getStyle(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal())
					.getCTStyle().getPPr().getOutlineLvl() != null) {
				// System.out.println("getBasedOn");
//              System.out.println(para.getParagraphText());
				String styleName = doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal();
//              System.out.println(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());

				return String
						.valueOf(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			if (para.getStyleID() != null) {
				return para.getStyleID();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return titleLvl;
	}

	/**
	 * 增加自定义标题样式。这里用的是stackoverflow的源码
	 * 
	 * @param docxDocument 目标文档
	 * @param strStyleId   样式名称
	 * @param headingLevel 样式级别
	 */
	private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {

		CTStyle ctStyle = CTStyle.Factory.newInstance();
		ctStyle.setStyleId(strStyleId);

		CTString styleName = CTString.Factory.newInstance();
		styleName.setVal(strStyleId);
		ctStyle.setName(styleName);

		CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
		indentNumber.setVal(BigInteger.valueOf(headingLevel));

		// lower number > style is more prominent in the formats bar
		ctStyle.setUiPriority(indentNumber);

		CTOnOff onoffnull = CTOnOff.Factory.newInstance();
		ctStyle.setUnhideWhenUsed(onoffnull);

		// style shows up in the formats bar
		ctStyle.setQFormat(onoffnull);

		// style defines a heading of the given level
		CTPPr ppr = CTPPr.Factory.newInstance();
		ppr.setOutlineLvl(indentNumber);
		ctStyle.setPPr(ppr);

		XWPFStyle style = new XWPFStyle(ctStyle);

		// is a null op if already defined
		XWPFStyles styles = docxDocument.createStyles();

		style.setType(STStyleType.PARAGRAPH);
		styles.addStyle(style);
		
	}
	
	/**
	 * @param id
	 * @param width
	 *            宽
	 * @param height
	 *            高
	 * @param paragraph
	 *            段落
	 */
	public static void createPicture(XWPFDocument docxDocument, int id, int width, int height, XWPFParagraph paragraph) {
		final int EMU = 9525;
		width *= EMU;
		height *= EMU;
		String blipId = docxDocument.getAllPictures().get(id).getPackageRelationship().getId();
		CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();
		String picXml = ""
				+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
				+ "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
				+ "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
				+ "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""
				+ id
				+ "\" name=\"Generated\"/>"
				+ "            <pic:cNvPicPr/>"
				+ "         </pic:nvPicPr>"
				+ "         <pic:blipFill>"
				+ "            <a:blip r:embed=\""
				+ blipId
				+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
				+ "            <a:stretch>"
				+ "               <a:fillRect/>"
				+ "            </a:stretch>"
				+ "         </pic:blipFill>"
				+ "         <pic:spPr>"
				+ "            <a:xfrm>"
				+ "               <a:off x=\"0\" y=\"0\"/>"
				+ "               <a:ext cx=\""
				+ width
				+ "\" cy=\""
				+ height
				+ "\"/>"
				+ "            </a:xfrm>"
				+ "            <a:prstGeom prst=\"rect\">"
				+ "               <a:avLst/>"
				+ "            </a:prstGeom>"
				+ "         </pic:spPr>"
				+ "      </pic:pic>"
				+ "   </a:graphicData>" + "</a:graphic>";

		inline.addNewGraphic().addNewGraphicData();
		XmlToken xmlToken = null;
		try {
			xmlToken = XmlToken.Factory.parse(picXml);
		} catch (XmlException xe) {
			xe.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("图片名称");
		docPr.setDescr("描述信息");
	}

	/**
	 * 获取标题编号
	 * 
	 * @param titleLvl
	 * @return
	 */
	private static String getOrderCode(String titleLvl) {
		String order = "";

		if ("0".equals(titleLvl) || Integer.parseInt(titleLvl) == 8) {// 文档标题||正文
			return "";
		} else if (Integer.parseInt(titleLvl) > 0 && Integer.parseInt(titleLvl) < 8) {// 段落标题

			// 设置最高级别标题
			Map<String, Object> maxTitleMap = orderMap.get("maxTitleLvlMap");
			if (null == maxTitleMap) {// 没有,表示第一次进来
				// 最高级别标题赋值
				maxTitleMap = new HashMap<String, Object>();
				maxTitleMap.put("lvl", titleLvl);
				orderMap.put("maxTitleLvlMap", maxTitleMap);
			} else {
				String maxTitleLvl = maxTitleMap.get("lvl") + "";// 最上层标题级别(0,1,2,3)
				if (Integer.parseInt(titleLvl) < Integer.parseInt(maxTitleLvl)) {// 当前标题级别更高
					maxTitleMap.put("lvl", titleLvl);// 设置最高级别标题
					orderMap.put("maxTitleLvlMap", maxTitleMap);
				}
			}

			// 查父节点标题
			int parentTitleLvl = Integer.parseInt(titleLvl) - 1;// 父节点标题级别
			Map<String, Object> cMap = orderMap.get(titleLvl);// 当前节点信息
			Map<String, Object> pMap = orderMap.get(parentTitleLvl + "");// 父节点信息

			if (0 == parentTitleLvl) {// 父节点为文档标题,表明当前节点为1级标题
				int count = 0;
				// 最上层标题,没有父节点信息
				if (null == cMap) {// 没有当前节点信息
					cMap = new HashMap<String, Object>();
				} else {
					count = Integer.parseInt(String.valueOf(cMap.get("cCount")));// 当前序个数
				}
				count++;
				order = count + "";
				cMap.put("cOrder", order);// 当前序
				cMap.put("cCount", count);// 当前序个数
				orderMap.put(titleLvl, cMap);

			} else {// 父节点为非文档标题
				int count = 0;
				// 如果没有相邻的父节点信息,当前标题级别自动升级
				if (null == pMap) {
					return getOrderCode(String.valueOf(parentTitleLvl));
				} else {
					String pOrder = String.valueOf(pMap.get("cOrder"));// 父节点序
					if (null == cMap) {// 没有当前节点信息
						cMap = new HashMap<String, Object>();
					} else {
						count = Integer.parseInt(String.valueOf(cMap.get("cCount")));// 当前序个数
					}
					count++;
					order = pOrder + "." + count;// 当前序编号
					cMap.put("cOrder", order);// 当前序
					cMap.put("cCount", count);// 当前序个数
					orderMap.put(titleLvl, cMap);
				}
			}

			// 字节点标题计数清零
			int childTitleLvl = Integer.parseInt(titleLvl) + 1;// 子节点标题级别
			Map<String, Object> cdMap = orderMap.get(childTitleLvl + "");//
			if (null != cdMap) {
				cdMap.put("cCount", 0);// 子节点序个数
				orderMap.get(childTitleLvl + "").put("cCount", 0);
			}
		}
		return order;
	}

	public static void main(String[] args) {
		InputStream is = null;
		OutputStream out = null;
		try {
			XWPFDocument createDoc = new XWPFDocument();
			
			addCustomHeadingStyle(createDoc, "z标题 1", 1);
		    addCustomHeadingStyle(createDoc, "z标题 2", 2); // 标题 1
		    XWPFParagraph paragraph = createDoc.createParagraph();
		    XWPFRun run = paragraph.createRun();
		    run.setText("z标题 1");
		    run.setFontFamily("宋体");// 字体
		    run.setBold(true);
			run.setFontSize(24);
		    paragraph.setStyle("z标题 1"); // 标题 2
		    paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式
		    XWPFParagraph paragraph2 = createDoc.createParagraph();
		    XWPFRun run2 = paragraph2.createRun();
		    run2.setText("z标题 2");
		    run2.setFontFamily("宋体");// 字体
		    run2.setBold(true);
			run2.setFontSize(20);
		    paragraph2.setStyle("z标题 2"); // 正文
		    paragraph2.setAlignment(ParagraphAlignment.CENTER);//对齐方式
		    XWPFParagraph paragraphX = createDoc.createParagraph();
		    XWPFRun runX = paragraphX.createRun();
		    runX.setText("正文"); // word 写入到文件
			

			/*is = new FileInputStream("D:/20190417-MRO-工程设计-招标书(标段一).docx");
			doc = new XWPFDocument(is);
			// 获取段落
			List<XWPFParagraph> paras = doc.getParagraphs();*/

			// for (XWPFParagraph para : paras) {
			// System.out.println("得到xml格式-->" + para.getCTP());//得到xml格式
			// System.out.println("段落级别-->" + para.getStyleID());// 段落级别
			// System.out.println("段落内容-->" + para.getParagraphText());// 段落内容

			/*
			 * String titleLvl = getTitleLvl(doc, para);// 获取段落级别 if ("a5".equals(titleLvl)
			 * || "HTML".equals(titleLvl) || "".equals(titleLvl) || null == titleLvl) {
			 * titleLvl = "8"; } System.out.println("获取段落级别-->" + titleLvl);// 0,1,2 if
			 * (!"8".equals(titleLvl)) { System.out.println("获取段落级别-->" + titleLvl +
			 * "====段落内容-->" + para.getParagraphText()); }
			 */

			XWPFParagraph ctPara = createDoc.createParagraph();
			// 一个XWPFRun代表具有相同属性的一个区域。
			XWPFRun ctRun = ctPara.createRun();
			ctPara.setIndentationFirstLine(567);// 首行缩进:567==1厘米 //
			// String ctText = para.getParagraphText();
			ctRun.setFontFamily("宋体");// 字体
			ctRun.setFontSize(12);
			ctRun.setTextPosition(6);//设置行间距

			String con = "areaTxt--><h1 style=\"text-align: center;\"><span style=\"font-weight: bold; font-family: 宋体; background-color: rgb(194, 79, 74);\">15</span></h1><div><span style=\"font-family: 宋体; background-color: rgb(255, 255, 255);\">1sdfsdf</span></div><div><span style=\"font-family: 宋体; background-color: rgb(255, 255, 255);\">2水电费都是发生的</span></div>";

			ctRun.setText(con);// 内容
			// }
			XWPFParagraph ctPara2 = createDoc.createParagraph();
			XWPFRun ctRun2 = ctPara2.createRun();
			// String ctText = para.getParagraphText();
			ctRun2.setFontFamily("宋体");// 字体
			ctRun2.setFontSize(12);

			String con2 = "areaTxt--><h1 style=\"text-align: center;\"><span style=\"font-weight: bold; font-family: 宋体; background-color: rgb(194, 79, 74);\">15</span></h1><div><span style=\"font-family: 宋体; background-color: rgb(255, 255, 255);\">1sdfsdf</span></div><div><span style=\"font-family: 宋体; background-color: rgb(255, 255, 255);\">2水电费都是发生的</span></div>";

			ctRun2.setText(con2);// 内容

			// XWPFDocument doc = new XWPFDocument(); // 创建一个 5 行 5 列的表格
			XWPFTable table = createDoc.createTable(5, 5); // 这里增加的列原本初始化创建的那 5 行在通过 getTableCells()方法获取时获取不到,但通过 row 新增的就可以。
			//table.addNewCol(); // 给表格增加一列,变成 6 列
			table.createRow(); // 给表格新增一行,变成 6 行
			List<XWPFTableRow> rows = table.getRows(); // 表格属性
			CTTblPr tablePr = table.getCTTbl().addNewTblPr(); // 表格宽度
			CTTblWidth width = tablePr.addNewTblW();
			width.setW(BigInteger.valueOf(8000));
			XWPFTableRow row;
			List<XWPFTableCell> cells;
			XWPFTableCell cell;
			for (int i1 = 0; i1 < rows.size(); i1++) {
				row = rows.get(i1); // 新增单元格
				row.addNewTableCell(); // 设置行的高度
				row.setHeight(500); // 行属性 //CTTrPr rowPr = row.getCtRow().addNewTrPr(); // 这种方式是可以获取到新增的 cell 的。
									// //List list = row.getCtRow().getTcList();
				cells = row.getTableCells();
				for (int j = 0; j < cells.size(); j++) {
					cell = cells.get(j);
					if ((i1 + j) % 2 == 0) { // 设置单元格的颜色
						cell.setColor("ff0000"); // 红色
					} else {
						cell.setColor("0000ff"); // 蓝色
					} // 单元格属性
					CTTcPr cellPr = cell.getCTTc().addNewTcPr();
					cellPr.addNewVAlign().setVal(STVerticalJc.CENTER);
					if (j == 3) { // 设置宽度
						cellPr.addNewTcW().setW(BigInteger.valueOf(3000));
					}
					cell.setText(i1 + "," + j);
				}
			}
			
			
			FileInputStream in = new FileInputStream("IMG20190130_160416.png");
			byte[] ba = new byte[in.available()];
			in.read(ba);
			ByteArrayInputStream byteInputStream = new ByteArrayInputStream(ba);
			XWPFParagraph picture = createDoc.createParagraph();
			//添加图片
			createDoc.addPictureData(byteInputStream, XWPFDocument.PICTURE_TYPE_PNG);
			//图片大小、位置
			createPicture(createDoc, createDoc.getAllPictures().size() - 1, 500, 500, picture);
			
			
			// 文件不存在时会自动创建
			out = new FileOutputStream("new1.docx");
			createDoc.write(out);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != out) {
					out.close();
				}
				if (null != is) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值