package cn.com.goldenwater.dcproj.utils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.*; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; public class WorldExoprtWithPicUtils { /** * 1厘米 */ public static final int ONE_UNIT = 567; public static String createWord(String filename, String contents, String path, String uploadPath, String type) throws Exception { File f = new File(path); if (!f.exists()) { f.mkdirs(); } XWPFDocument docxDocument = new XWPFDocument(); Document doc = Jsoup.parseBodyFragment(contents); Element body = doc.body(); Elements es = body.getAllElements(); boolean tag = false; for (Element e : es) { //跳过第一个(默认会把整个对象当做第一个) if (!tag) { tag = true; continue; } //创建段落:生成word(核心) if (!"8".equals(type)) { createXWPFParagraph(docxDocument, e, uploadPath); } else { createNewXWPFParagraph(docxDocument, e, uploadPath); } } setDocumentMargin(docxDocument, (int) (WorldExoprtWithPicUtils.ONE_UNIT * 2.5) + "", (WorldExoprtWithPicUtils.ONE_UNIT * 2) + "", (int) (WorldExoprtWithPicUtils.ONE_UNIT * 2.5) + "", (WorldExoprtWithPicUtils.ONE_UNIT * 2) + ""); // word写入到文件 //删除部分历史数据 File file = new File(path); InspUtils.initTempDocFile(file); FileOutputStream out = new FileOutputStream(new File(path + "/" + filename + ".docx")); docxDocument.write(out); out.flush(); out.close(); return filename + ".docx"; } private static void createNewXWPFParagraph(XWPFDocument docxDocument, Element e, String uploadPath) { if (StringUtils.isBlank(e.text().trim())) { return; } XWPFParagraph paragraph = docxDocument.createParagraph(); XWPFRun run = paragraph.createRun(); if ("h3".equals(e.tagName())) { paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式 addCustomHeadingStyle(docxDocument, "标题 3", 3); paragraph.setStyle("标题 3"); run.setBold(true); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(16); run.setText(e.text()); run.setTextPosition(20);//设置行间距 } else if ("h4".equals(e.tagName())) { paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式 addCustomHeadingStyle(docxDocument, "标题 4", 4); paragraph.setStyle("标题 4"); run.setBold(false); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(15); run.setText(e.text()); run.setTextPosition(15);//设置行间距 } else if ("h5".equals(e.tagName())) { paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式 addCustomHeadingStyle(docxDocument, "标题 4", 4); paragraph.setStyle("标题 4"); run.setBold(false); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(14); run.setText(e.text()); run.setTextPosition(15);//设置行间距 } else if ("p".equals(e.tagName())) { paragraph.setAlignment(ParagraphAlignment.BOTH);//对齐方式 paragraph.setIndentationFirstLine(WorldExoprtWithPicUtils.ONE_UNIT);//首行缩进:567==1厘米 run.setBold(false); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(13); run.setText(e.text()); run.setTextPosition(15);//设置行间距 } else if ("break".equals(e.tagName())) { paragraph.setPageBreak(true);//段前分页(ctrl+enter) } else if ("br".equals(e.tagName())) { run.addCarriageReturn(); } } /** * 增加自定义标题样式。这里用的是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 docxDocument * @param e */ public static void createXWPFParagraph(XWPFDocument docxDocument, Element e, String uploadPath) { if ("div".equals(e.tagName()) || "table".equals(e.tagName()) || "tr".equals(e.tagName()) || "head".equals(e.tagName()) || "html".equals(e.tagName()) || "body".equals(e.tagName()) || "td".equals(e.tagName())) { return; } if (!"img".equals(e.tagName()) && StringUtils.isBlank(e.text().trim())) { return; } if ("img".equals(e.tagName())) { String imgpath = e.attr("src"); if (imgpath.endsWith(".xlsx")) { return; } if (-1 == getPictureFormat(imgpath)) { return; } InputStream fis = OfficeUtil.retFileStream(imgpath, uploadPath); if (fis == null) { return; } String fileName = imgpath.substring(imgpath.lastIndexOf("/") + 1, imgpath.length()); try { XWPFParagraph paragraph = docxDocument.createParagraph(); XWPFRun run = paragraph.createRun(); paragraph.setAlignment(ParagraphAlignment.CENTER); run.addPicture(fis, getPictureFormat(imgpath), fileName, Units.toEMU(400), Units.toEMU(300)); run.setTextPosition(15);//设置行间距 } catch (InvalidFormatException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } finally { try { fis.close(); } catch (IOException e1) { e1.printStackTrace(); } } } else { XWPFParagraph paragraph = docxDocument.createParagraph(); XWPFRun run = paragraph.createRun(); if ("titlename".equals(e.tagName())) { paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式 run.setBold(true);//加粗 run.setColor("000000");//设置颜色--十六进制 run.setFontFamily("宋体");//字体 run.setFontSize(24);//字体大小 run.setText(e.text()); run.setTextPosition(35);//设置行间距 } else if ("h3".equals(e.tagName())) { addCustomHeadingStyle(docxDocument, "标题 3", 3); paragraph.setStyle("标题 3"); run.setBold(true); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(16); run.setText(e.text()); run.setTextPosition(20);//设置行间距 } else if ("h4".equals(e.tagName())) { addCustomHeadingStyle(docxDocument, "标题 4", 4); paragraph.setStyle("标题 4"); run.setBold(true); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(15); run.setText(e.text()); run.setTextPosition(15);//设置行间距 } else if ("h5".equals(e.tagName())) { addCustomHeadingStyle(docxDocument, "标题 4", 4); paragraph.setStyle("标题 4"); run.setBold(true); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(14); run.setText(e.text()); run.setTextPosition(15);//设置行间距 } else if ("p".equals(e.tagName())) { //内容 paragraph.setAlignment(ParagraphAlignment.BOTH);//对齐方式 paragraph.setIndentationFirstLine(WorldExoprtWithPicUtils.ONE_UNIT);//首行缩进:567==1厘米 run.setBold(false); run.setColor("000000"); run.setFontFamily("宋体"); run.setFontSize(13); run.setText(e.text()); run.setTextPosition(15);//设置行间距 //run.addCarriageReturn();//回车键 } else if ("break".equals(e.tagName())) { paragraph.setPageBreak(true);//段前分页(ctrl+enter) } else if ("br".equals(e.tagName())) { run.addCarriageReturn(); } } } public static int getPictureFormat(String imgFile) { int format; if (imgFile.endsWith(".emf")) { format = XWPFDocument.PICTURE_TYPE_EMF; } else if (imgFile.endsWith(".wmf")) { format = XWPFDocument.PICTURE_TYPE_WMF; } else if (imgFile.endsWith(".pict")) { format = XWPFDocument.PICTURE_TYPE_PICT; } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) { format = XWPFDocument.PICTURE_TYPE_JPEG; } else if (imgFile.endsWith(".png")) { format = XWPFDocument.PICTURE_TYPE_PNG; } else if (imgFile.endsWith(".dib")) { format = XWPFDocument.PICTURE_TYPE_DIB; } else if (imgFile.endsWith(".gif")) { format = XWPFDocument.PICTURE_TYPE_GIF; } else if (imgFile.endsWith(".tiff")) { format = XWPFDocument.PICTURE_TYPE_TIFF; } else if (imgFile.endsWith(".eps")) { format = XWPFDocument.PICTURE_TYPE_EPS; } else if (imgFile.endsWith(".bmp")) { format = XWPFDocument.PICTURE_TYPE_BMP; } else if (imgFile.endsWith(".wpg")) { format = XWPFDocument.PICTURE_TYPE_WPG; } else { format = -1; } return format; } /** * 设置页边距 (word中1厘米约等于567) * * @param document * @param left * @param top * @param right * @param bottom */ public static void setDocumentMargin(XWPFDocument document, String left, String top, String right, String bottom) { CTSectPr sectPr = document.getDocument().getBody().addNewSectPr(); CTPageMar ctpagemar = sectPr.addNewPgMar(); if (StringUtils.isNotBlank(left)) { ctpagemar.setLeft(new BigInteger(left)); } if (StringUtils.isNotBlank(top)) { ctpagemar.setTop(new BigInteger(top)); } if (StringUtils.isNotBlank(right)) { ctpagemar.setRight(new BigInteger(right)); } if (StringUtils.isNotBlank(bottom)) { ctpagemar.setBottom(new BigInteger(bottom)); } } }