8e4c5efd39f154f4e9a5a506d4fe2bfdf5e5586a.svn-base 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package cn.com.goldenwater.dcproj.utils;
  2. import org.apache.commons.lang3.StringUtils;
  3. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  4. import org.apache.poi.util.Units;
  5. import org.apache.poi.xwpf.usermodel.*;
  6. import org.jsoup.Jsoup;
  7. import org.jsoup.nodes.Document;
  8. import org.jsoup.nodes.Element;
  9. import org.jsoup.select.Elements;
  10. import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
  11. import java.io.File;
  12. import java.io.FileOutputStream;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.math.BigInteger;
  16. public class WorldExoprtWithPicUtils {
  17. /**
  18. * 1厘米
  19. */
  20. public static final int ONE_UNIT = 567;
  21. public static String createWord(String filename, String contents, String path, String uploadPath, String type) throws Exception {
  22. File f = new File(path);
  23. if (!f.exists()) {
  24. f.mkdirs();
  25. }
  26. XWPFDocument docxDocument = new XWPFDocument();
  27. Document doc = Jsoup.parseBodyFragment(contents);
  28. Element body = doc.body();
  29. Elements es = body.getAllElements();
  30. boolean tag = false;
  31. for (Element e : es) {
  32. //跳过第一个(默认会把整个对象当做第一个)
  33. if (!tag) {
  34. tag = true;
  35. continue;
  36. }
  37. //创建段落:生成word(核心)
  38. if (!"8".equals(type)) {
  39. createXWPFParagraph(docxDocument, e, uploadPath);
  40. } else {
  41. createNewXWPFParagraph(docxDocument, e, uploadPath);
  42. }
  43. }
  44. setDocumentMargin(docxDocument, (int) (WorldExoprtWithPicUtils.ONE_UNIT * 2.5) + "", (WorldExoprtWithPicUtils.ONE_UNIT * 2) + "", (int) (WorldExoprtWithPicUtils.ONE_UNIT * 2.5) + "", (WorldExoprtWithPicUtils.ONE_UNIT * 2) + "");
  45. // word写入到文件
  46. //删除部分历史数据
  47. File file = new File(path);
  48. InspUtils.initTempDocFile(file);
  49. FileOutputStream out = new FileOutputStream(new File(path + "/" + filename + ".docx"));
  50. docxDocument.write(out);
  51. out.flush();
  52. out.close();
  53. return filename + ".docx";
  54. }
  55. private static void createNewXWPFParagraph(XWPFDocument docxDocument, Element e, String uploadPath) {
  56. if (StringUtils.isBlank(e.text().trim())) {
  57. return;
  58. }
  59. XWPFParagraph paragraph = docxDocument.createParagraph();
  60. XWPFRun run = paragraph.createRun();
  61. if ("h3".equals(e.tagName())) {
  62. paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式
  63. addCustomHeadingStyle(docxDocument, "标题 3", 3);
  64. paragraph.setStyle("标题 3");
  65. run.setBold(true);
  66. run.setColor("000000");
  67. run.setFontFamily("宋体");
  68. run.setFontSize(16);
  69. run.setText(e.text());
  70. run.setTextPosition(20);//设置行间距
  71. } else if ("h4".equals(e.tagName())) {
  72. paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式
  73. addCustomHeadingStyle(docxDocument, "标题 4", 4);
  74. paragraph.setStyle("标题 4");
  75. run.setBold(false);
  76. run.setColor("000000");
  77. run.setFontFamily("宋体");
  78. run.setFontSize(15);
  79. run.setText(e.text());
  80. run.setTextPosition(15);//设置行间距
  81. } else if ("h5".equals(e.tagName())) {
  82. paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式
  83. addCustomHeadingStyle(docxDocument, "标题 4", 4);
  84. paragraph.setStyle("标题 4");
  85. run.setBold(false);
  86. run.setColor("000000");
  87. run.setFontFamily("宋体");
  88. run.setFontSize(14);
  89. run.setText(e.text());
  90. run.setTextPosition(15);//设置行间距
  91. } else if ("p".equals(e.tagName())) {
  92. paragraph.setAlignment(ParagraphAlignment.BOTH);//对齐方式
  93. paragraph.setIndentationFirstLine(WorldExoprtWithPicUtils.ONE_UNIT);//首行缩进:567==1厘米
  94. run.setBold(false);
  95. run.setColor("000000");
  96. run.setFontFamily("宋体");
  97. run.setFontSize(13);
  98. run.setText(e.text());
  99. run.setTextPosition(15);//设置行间距
  100. } else if ("break".equals(e.tagName())) {
  101. paragraph.setPageBreak(true);//段前分页(ctrl+enter)
  102. } else if ("br".equals(e.tagName())) {
  103. run.addCarriageReturn();
  104. }
  105. }
  106. /**
  107. * 增加自定义标题样式。这里用的是stackoverflow的源码
  108. *
  109. * @param docxDocument 目标文档
  110. * @param strStyleId 样式名称
  111. * @param headingLevel 样式级别
  112. */
  113. private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {
  114. CTStyle ctStyle = CTStyle.Factory.newInstance();
  115. ctStyle.setStyleId(strStyleId);
  116. CTString styleName = CTString.Factory.newInstance();
  117. styleName.setVal(strStyleId);
  118. ctStyle.setName(styleName);
  119. CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
  120. indentNumber.setVal(BigInteger.valueOf(headingLevel));
  121. // lower number > style is more prominent in the formats bar
  122. ctStyle.setUiPriority(indentNumber);
  123. CTOnOff onoffnull = CTOnOff.Factory.newInstance();
  124. ctStyle.setUnhideWhenUsed(onoffnull);
  125. // style shows up in the formats bar
  126. ctStyle.setQFormat(onoffnull);
  127. // style defines a heading of the given level
  128. CTPPr ppr = CTPPr.Factory.newInstance();
  129. ppr.setOutlineLvl(indentNumber);
  130. ctStyle.setPPr(ppr);
  131. XWPFStyle style = new XWPFStyle(ctStyle);
  132. // is a null op if already defined
  133. XWPFStyles styles = docxDocument.createStyles();
  134. style.setType(STStyleType.PARAGRAPH);
  135. styles.addStyle(style);
  136. }
  137. /**
  138. * 构建段落
  139. *
  140. * @param docxDocument
  141. * @param e
  142. */
  143. public static void createXWPFParagraph(XWPFDocument docxDocument, Element e, String uploadPath) {
  144. if ("div".equals(e.tagName()) || "table".equals(e.tagName()) || "tr".equals(e.tagName())
  145. || "head".equals(e.tagName()) || "html".equals(e.tagName()) || "body".equals(e.tagName()) || "td".equals(e.tagName())) {
  146. return;
  147. }
  148. if (!"img".equals(e.tagName()) && StringUtils.isBlank(e.text().trim())) {
  149. return;
  150. }
  151. if ("img".equals(e.tagName())) {
  152. String imgpath = e.attr("src");
  153. if (imgpath.endsWith(".xlsx")) {
  154. return;
  155. }
  156. if (-1 == getPictureFormat(imgpath)) {
  157. return;
  158. }
  159. InputStream fis = OfficeUtil.retFileStream(imgpath, uploadPath);
  160. if (fis == null) {
  161. return;
  162. }
  163. String fileName = imgpath.substring(imgpath.lastIndexOf("/") + 1, imgpath.length());
  164. try {
  165. XWPFParagraph paragraph = docxDocument.createParagraph();
  166. XWPFRun run = paragraph.createRun();
  167. paragraph.setAlignment(ParagraphAlignment.CENTER);
  168. run.addPicture(fis, getPictureFormat(imgpath), fileName, Units.toEMU(400), Units.toEMU(300));
  169. run.setTextPosition(15);//设置行间距
  170. } catch (InvalidFormatException e1) {
  171. e1.printStackTrace();
  172. } catch (IOException e1) {
  173. e1.printStackTrace();
  174. } finally {
  175. try {
  176. fis.close();
  177. } catch (IOException e1) {
  178. e1.printStackTrace();
  179. }
  180. }
  181. } else {
  182. XWPFParagraph paragraph = docxDocument.createParagraph();
  183. XWPFRun run = paragraph.createRun();
  184. if ("titlename".equals(e.tagName())) {
  185. paragraph.setAlignment(ParagraphAlignment.CENTER);//对齐方式
  186. run.setBold(true);//加粗
  187. run.setColor("000000");//设置颜色--十六进制
  188. run.setFontFamily("宋体");//字体
  189. run.setFontSize(24);//字体大小
  190. run.setText(e.text());
  191. run.setTextPosition(35);//设置行间距
  192. } else if ("h3".equals(e.tagName())) {
  193. addCustomHeadingStyle(docxDocument, "标题 3", 3);
  194. paragraph.setStyle("标题 3");
  195. run.setBold(true);
  196. run.setColor("000000");
  197. run.setFontFamily("宋体");
  198. run.setFontSize(16);
  199. run.setText(e.text());
  200. run.setTextPosition(20);//设置行间距
  201. } else if ("h4".equals(e.tagName())) {
  202. addCustomHeadingStyle(docxDocument, "标题 4", 4);
  203. paragraph.setStyle("标题 4");
  204. run.setBold(true);
  205. run.setColor("000000");
  206. run.setFontFamily("宋体");
  207. run.setFontSize(15);
  208. run.setText(e.text());
  209. run.setTextPosition(15);//设置行间距
  210. } else if ("h5".equals(e.tagName())) {
  211. addCustomHeadingStyle(docxDocument, "标题 4", 4);
  212. paragraph.setStyle("标题 4");
  213. run.setBold(true);
  214. run.setColor("000000");
  215. run.setFontFamily("宋体");
  216. run.setFontSize(14);
  217. run.setText(e.text());
  218. run.setTextPosition(15);//设置行间距
  219. } else if ("p".equals(e.tagName())) {
  220. //内容
  221. paragraph.setAlignment(ParagraphAlignment.BOTH);//对齐方式
  222. paragraph.setIndentationFirstLine(WorldExoprtWithPicUtils.ONE_UNIT);//首行缩进:567==1厘米
  223. run.setBold(false);
  224. run.setColor("000000");
  225. run.setFontFamily("宋体");
  226. run.setFontSize(13);
  227. run.setText(e.text());
  228. run.setTextPosition(15);//设置行间距
  229. //run.addCarriageReturn();//回车键
  230. } else if ("break".equals(e.tagName())) {
  231. paragraph.setPageBreak(true);//段前分页(ctrl+enter)
  232. } else if ("br".equals(e.tagName())) {
  233. run.addCarriageReturn();
  234. }
  235. }
  236. }
  237. public static int getPictureFormat(String imgFile) {
  238. int format;
  239. if (imgFile.endsWith(".emf")) {
  240. format = XWPFDocument.PICTURE_TYPE_EMF;
  241. } else if (imgFile.endsWith(".wmf")) {
  242. format = XWPFDocument.PICTURE_TYPE_WMF;
  243. } else if (imgFile.endsWith(".pict")) {
  244. format = XWPFDocument.PICTURE_TYPE_PICT;
  245. } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
  246. format = XWPFDocument.PICTURE_TYPE_JPEG;
  247. } else if (imgFile.endsWith(".png")) {
  248. format = XWPFDocument.PICTURE_TYPE_PNG;
  249. } else if (imgFile.endsWith(".dib")) {
  250. format = XWPFDocument.PICTURE_TYPE_DIB;
  251. } else if (imgFile.endsWith(".gif")) {
  252. format = XWPFDocument.PICTURE_TYPE_GIF;
  253. } else if (imgFile.endsWith(".tiff")) {
  254. format = XWPFDocument.PICTURE_TYPE_TIFF;
  255. } else if (imgFile.endsWith(".eps")) {
  256. format = XWPFDocument.PICTURE_TYPE_EPS;
  257. } else if (imgFile.endsWith(".bmp")) {
  258. format = XWPFDocument.PICTURE_TYPE_BMP;
  259. } else if (imgFile.endsWith(".wpg")) {
  260. format = XWPFDocument.PICTURE_TYPE_WPG;
  261. } else {
  262. format = -1;
  263. }
  264. return format;
  265. }
  266. /**
  267. * 设置页边距 (word中1厘米约等于567)
  268. *
  269. * @param document
  270. * @param left
  271. * @param top
  272. * @param right
  273. * @param bottom
  274. */
  275. public static void setDocumentMargin(XWPFDocument document, String left, String top, String right, String bottom) {
  276. CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
  277. CTPageMar ctpagemar = sectPr.addNewPgMar();
  278. if (StringUtils.isNotBlank(left)) {
  279. ctpagemar.setLeft(new BigInteger(left));
  280. }
  281. if (StringUtils.isNotBlank(top)) {
  282. ctpagemar.setTop(new BigInteger(top));
  283. }
  284. if (StringUtils.isNotBlank(right)) {
  285. ctpagemar.setRight(new BigInteger(right));
  286. }
  287. if (StringUtils.isNotBlank(bottom)) {
  288. ctpagemar.setBottom(new BigInteger(bottom));
  289. }
  290. }
  291. }