最新POI将word文档转为HTML代码

作者:超级无敌大飞   阅读 (4049)  |  收藏 (0)  |  点赞 (0)

摘要

本文将会讲述如何使用JAVA poi将word文档中的内容转为HTML页面,本文使用POI 的jar,能够处理2003的word各种内容,比如图片在word中的位置的处理问题,而且支持自定义转换的样式,支持锚点设置。下面将会讲述如何使用POI读取word文档中的图片,并确定图片的位置,然后在HTML页面显示出来。


原文链接:最新POI将word文档转为HTML代码

引用本文请注明出处:

  目前网上的使用POIword转为HTML页面时的代码普遍集中在两种解决方式:一种为一个字符一个字符的遍历word内容,然后将其全部转为Span标签输出,另一种方式采用poi自带的jar来强制转换。

  就上述这两种方式来说,都存在自己的一个很大的缺点是,转换成的HTML页面很难适应自己Web项目的前端框架,样式更是很难符合自己项目的框架要求。

  本文将会在网上流传的其他代码的基础上,改进了生成HTML页面的样式和逻辑,使使用者能够按照自己的意愿随意修改生成的HTML中的图片的定位,比如,可以真实的使用POI定位图片在Word中的位置,并将其保存至任意位置。

  word文档中的表格的样式和位置也能够在本代码中随意修改它的样式。

  注意,本文不是坑,作者也是尝试了各种坑以后才解决了这个问题,下面将会讲述如何使用POI读取word文档中的图片,并确定图片的位置,然后在HTML页面显示出来。

 jar准备

\\\\\\\"a.png\\\\\\\"/

本例的实际代码仅仅有一个类,而且支持用户自己修改文件位置:

package com.demo.test;\\\\n \\\\n import java.io.BufferedWriter;\\\\n import java.io.File;\\\\n import java.io.FileInputStream;\\\\n import java.io.FileNotFoundException;\\\\n import java.io.FileOutputStream;\\\\n import java.io.IOException;\\\\n import java.io.OutputStream;\\\\n import java.io.OutputStreamWriter;\\\\n import java.util.HashMap;\\\\n import java.util.Map;\\\\n \\\\n import org.apache.poi.hwpf.HWPFDocument;\\\\n import org.apache.poi.hwpf.model.PicturesTable;\\\\n import org.apache.poi.hwpf.model.StyleDescription;\\\\n import org.apache.poi.hwpf.model.StyleSheet;\\\\n import org.apache.poi.hwpf.usermodel.CharacterRun;\\\\n import org.apache.poi.hwpf.usermodel.Picture;\\\\n import org.apache.poi.hwpf.usermodel.Range;\\\\n import org.apache.poi.hwpf.usermodel.Paragraph;\\\\n import org.apache.poi.hwpf.usermodel.Table;\\\\n import org.apache.poi.hwpf.usermodel.TableCell;\\\\n import org.apache.poi.hwpf.usermodel.TableIterator;\\\\n import org.apache.poi.hwpf.usermodel.TableRow;\\\\n \\\\n public class WordExcelToHtml_new {\\\\n \\\\n /**\\\\n * 回车符ASCII码\\\\n */\\\\n private static final short ENTER_ASCII = 13;\\\\n \\\\n /**\\\\n * 空格符ASCII码\\\\n */\\\\n private static final short SPACE_ASCII = 32;\\\\n \\\\n /**\\\\n * 水平制表符ASCII码\\\\n */\\\\n private static final short TABULATION_ASCII = 9;\\\\n \\\\n public static String htmlText = "";\\\\n public static String htmlTextTbl = "";\\\\n public static int counter = 0;\\\\n public static int beginPosi = 0;\\\\n public static int endPosi = 0;\\\\n public static int beginArray[];\\\\n public static int endArray[];\\\\n public static String htmlTextArray[];\\\\n public static boolean tblExist = false;\\\\n \\\\n public static final String inputFile = "K://test/test.doc";\\\\n public static final String outPutFile = "K://test/fanyi.html";\\\\n public static final String picFile = "K://test";\\\\n \\\\n public static void main(String argv[]) {\\\\n try {\\\\n getWordAndStyle(inputFile);\\\\n } catch (Exception e) {\\\\n // TODO Auto-generated catch block\\\\n e.printStackTrace();\\\\n }\\\\n }\\\\n \\\\n /**\\\\n * 获取当前字符是不是标题,如果是,返回当前标题级别\\\\n * \\\\n * @param range\\\\n * @param doc\\\\n * @return\\\\n */\\\\n public static Map<String, Object> getStyle(Range range, HWPFDocument doc) {\\\\n Map<String, Object> map = new HashMap<String, Object>();\\\\n Paragraph p = range.getParagraph(0);\\\\n // check if style index is greater than total number of styles\\\\n int numStyles = doc.getStyleSheet().numStyles();\\\\n int styleIndex = p.getStyleIndex();\\\\n if (numStyles > styleIndex) {\\\\n StyleSheet style_sheet = doc.getStyleSheet();\\\\n StyleDescription style = style_sheet\\\\n .getStyleDescription(styleIndex);\\\\n String styleName = style.getName();\\\\n if (styleName != null && styleName.contains("标题")) {\\\\n map.put("lvl", p.getLvl() + 1);\\\\n map.put("isTitle", true);\\\\n } else {\\\\n map.put("isTitle", false);\\\\n }\\\\n }\\\\n return map;\\\\n }\\\\n \\\\n /**\\\\n * 初始化一个标题级别的map,用户存储标题级别信息\\\\n * \\\\n * @param i\\\\n *            一共需要几个级别的标题\\\\n * @return\\\\n */\\\\n public static Map<String, Integer> initCountMap(Integer i) {\\\\n Map<String, Integer> count_Map = new HashMap<String, Integer>(); // 计数标题级别,生成唯一的标题id,为后续生成锚点做准备\\\\n if (i > 0) {\\\\n for (int j = 1; j <= i; j++) {\\\\n count_Map.put("title_" + j, 0); // 以及标题\\\\n }\\\\n }\\\\n return count_Map;\\\\n }\\\\n \\\\n /**\\\\n * 根据当前级别获取唯一id\\\\n * \\\\n * @param i\\\\n *            当前级别\\\\n * @param map\\\\n * @return\\\\n */\\\\n public static Integer getCurrent_lvl_id(Integer i, Map<String, Integer> map) {\\\\n Integer lvl_id = map.get("title_" + i);\\\\n return lvl_id;\\\\n }\\\\n \\\\n /**\\\\n * 清除掉该级别下的所有子级别的数据\\\\n * \\\\n * @param map\\\\n *            存储所有级别的集合\\\\n * @param i\\\\n *            当前级别\\\\n * @param max_lvl\\\\n *            最高级别\\\\n */\\\\n public static void clearBotton(Map<String, Integer> map, Integer i,\\\\n Integer max_lvl) {\\\\n map.put("title_" + i, i + 1);\\\\n for (i = i + 1; i <= max_lvl; i++) {\\\\n map.put("title_" + i, 0);\\\\n }\\\\n }\\\\n \\\\n /**\\\\n * 获取文档最高的标题级别\\\\n * \\\\n * @param doc\\\\n * @return\\\\n */\\\\n public static Integer getDocLvl(HWPFDocument doc) {\\\\n Integer max_lvl = 0;\\\\n Range r = doc.getRange();\\\\n for (int i = 0; i < r.numParagraphs(); i++) {\\\\n Paragraph p = r.getParagraph(i);\\\\n // check if style index is greater than total number of styles\\\\n int numStyles = doc.getStyleSheet().numStyles();\\\\n int styleIndex = p.getStyleIndex();\\\\n if (numStyles > styleIndex) {\\\\n StyleSheet style_sheet = doc.getStyleSheet();\\\\n StyleDescription style = style_sheet\\\\n .getStyleDescription(styleIndex);\\\\n String styleName = style.getName();\\\\n if (styleName != null && styleName.contains("标题")) {\\\\n max_lvl = max_lvl > (p.getLvl() + 1) ? max_lvl : (p\\\\n .getLvl() + 1);\\\\n }\\\\n }\\\\n }\\\\n return max_lvl;\\\\n }\\\\n \\\\n /**\\\\n * 读取每个文字样式\\\\n * \\\\n * @param fileName\\\\n * @throws Exception\\\\n */\\\\n \\\\n public static void getWordAndStyle(String fileName) throws Exception {\\\\n \\\\n File file = new File(fileName);\\\\n \\\\n FileInputStream in = new FileInputStream(file);\\\\n HWPFDocument doc = new HWPFDocument(in);\\\\n \\\\n Integer tottle_lvl = getDocLvl(doc);\\\\n System.out.println("文章最高级别为:\\\\\\\\t" + tottle_lvl);\\\\n Map<String, Integer> countMap = initCountMap(tottle_lvl);\\\\n \\\\n Range rangetbl = doc.getRange();// 得到文档的读取范围\\\\n \\\\n TableIterator it = new TableIterator(rangetbl);\\\\n int num = 100;\\\\n \\\\n beginArray = new int[num];\\\\n endArray = new int[num];\\\\n htmlTextArray = new String[num];\\\\n \\\\n // 取得文档中字符的总数\\\\n int length = doc.characterLength();\\\\n // 创建图片容器\\\\n PicturesTable pTable = doc.getPicturesTable();\\\\n \\\\n htmlText = "<!DOCTYPE html><html lang=\\\\\\\\"zh-CN\\\\\\\\"><head><meta http-equiv=\\\\\\\\"Content-Type\\\\\\\\" content=\\\\\\\\"text/html; charset=UTF-8\\\\\\\\"><title>"\\\\n + file.getName()\\\\n + "</title>"\\\\n + "<link rel=\\\\\\\\"stylesheet\\\\\\\\" href=\\\\\\\\"bootstrap-3.3.5-dist/css/bootstrap.min.css\\\\\\\\" type=\\\\\\\\"text/css\\\\\\\\">"\\\\n + "<script type=\\\\\\\\"text/javascript\\\\\\\\" src=\\\\\\\\"js/jquery-1.12.3.min.js\\\\\\\\"></script>"\\\\n + "<script type=\\\\\\\\"text/javascript\\\\\\\\" src=\\\\\\\\"bootstrap-3.3.5-dist/js/bootstrap.min.js\\\\\\\\"></script>"\\\\n + "</head><body>";\\\\n // 创建临时字符串,好加以判断一串字符是否存在相同格式\\\\n \\\\n if (it.hasNext()) {\\\\n readTable(it, rangetbl);\\\\n }\\\\n \\\\n int cur = 0;\\\\n \\\\n String tempString = "";\\\\n for (int i = 0; i < length - 1; i++) {\\\\n // 整篇文章的字符通过一个个字符的来判断,range为得到文档的范围\\\\n Range range = new Range(i, i + 1, doc);\\\\n \\\\n CharacterRun cr = range.getCharacterRun(0);\\\\n \\\\n if (tblExist) {\\\\n if (i == beginArray[cur]) {\\\\n htmlText += tempString + htmlTextArray[cur];\\\\n tempString = "";\\\\n i = endArray[cur] - 1;\\\\n cur++;\\\\n continue;\\\\n }\\\\n }\\\\n if (pTable.hasPicture(cr)) {\\\\n htmlText += tempString;\\\\n // 读写图片\\\\n readPicture(pTable, cr);\\\\n tempString = "";\\\\n } else {\\\\n Range range2 = new Range(i + 1, i + 2, doc);\\\\n // 第二个字符\\\\n CharacterRun cr2 = range2.getCharacterRun(0);\\\\n char c = cr.text().charAt(0);\\\\n \\\\n // 判断是否为回车符\\\\n if (c == ENTER_ASCII) {\\\\n tempString += "<br/>";\\\\n \\\\n }\\\\n // 判断是否为空格符\\\\n else if (c == SPACE_ASCII)\\\\n tempString += " ";\\\\n // 判断是否为水平制表符\\\\n else if (c == TABULATION_ASCII)\\\\n tempString += "    ";\\\\n // 比较前后2个字符是否具有相同的格式\\\\n boolean flag = compareCharStyle(cr, cr2);\\\\n if (flag)\\\\n tempString += cr.text();\\\\n else {\\\\n \\\\n Map<String, Object> map = getStyle(range, doc);\\\\n boolean isTitle = (Boolean) map.get("isTitle");\\\\n if (isTitle) {\\\\n Integer lvl = (Integer) map.get("lvl");\\\\n Integer id_lvl = getCurrent_lvl_id(lvl, countMap);\\\\n clearBotton(countMap, lvl, tottle_lvl);\\\\n htmlText += "<h" + lvl + " id=\\\\\\\\"title_" + id_lvl\\\\n + "\\\\\\\\">" + tempString + cr.text() + "</h" + lvl\\\\n + ">";\\\\n } else {\\\\n htmlText += "<span>" + tempString + cr.text()\\\\n + "</span>";\\\\n }\\\\n tempString = "";\\\\n }\\\\n }\\\\n }\\\\n \\\\n htmlText += tempString + "</body></html>";\\\\n writeFile(htmlText);\\\\n }\\\\n \\\\n /**\\\\n * 读写文档中的表格\\\\n * \\\\n * @param pTable\\\\n * @param cr\\\\n * @throws Exception\\\\n */\\\\n public static void readTable(TableIterator it, Range rangetbl)\\\\n throws Exception {\\\\n \\\\n htmlTextTbl = "";\\\\n // 迭代文档中的表格\\\\n \\\\n counter = -1;\\\\n while (it.hasNext()) {\\\\n tblExist = true;\\\\n htmlTextTbl = "";\\\\n Table tb = (Table) it.next();\\\\n beginPosi = tb.getStartOffset();\\\\n endPosi = tb.getEndOffset();\\\\n \\\\n System.out.println("............" + beginPosi + "...." + endPosi);\\\\n counter = counter + 1;\\\\n // 迭代行,默认从0开始\\\\n beginArray[counter] = beginPosi;\\\\n endArray[counter] = endPosi;\\\\n \\\\n htmlTextTbl += "<table class=\\\\\\\\"table table-bordered\\\\\\\\">";\\\\n for (int i = 0; i < tb.numRows(); i++) {\\\\n TableRow tr = tb.getRow(i);\\\\n \\\\n htmlTextTbl += "<tr>";\\\\n // 迭代列,默认从0开始\\\\n for (int j = 0; j < tr.numCells(); j++) {\\\\n TableCell td = tr.getCell(j);// 取得单元格\\\\n // int cellWidth = td.getWidth();\\\\n \\\\n // 取得单元格的内容\\\\n for (int k = 0; k < td.numParagraphs(); k++) {\\\\n Paragraph para = td.getParagraph(k);\\\\n String s = para.text().toString().trim();\\\\n if (s == "") {\\\\n s = " ";\\\\n }\\\\n System.out.println(s);\\\\n \\\\n String td_th = null;\\\\n if (0 == i) {\\\\n td_th = "th";\\\\n } else {\\\\n td_th = "td";\\\\n }\\\\n htmlTextTbl += "<" + td_th + " >" + s + "</" + td_th\\\\n + ">";\\\\n \\\\n } // end for\\\\n } // end for\\\\n } // end for\\\\n htmlTextTbl += "</table>";\\\\n htmlTextArray[counter] = htmlTextTbl;\\\\n \\\\n } // end while\\\\n }\\\\n \\\\n /**\\\\n * 读写文档中的图片\\\\n * \\\\n * @param pTable\\\\n * @param cr\\\\n * @throws Exception\\\\n */\\\\n public static void readPicture(PicturesTable pTable, CharacterRun cr)\\\\n throws Exception {\\\\n // 提取图片\\\\n Picture pic = pTable.extractPicture(cr, false);\\\\n // 返回POI建议的图片文件名\\\\n String afileName = pic.suggestFullFileName();\\\\n OutputStream out = new FileOutputStream(new File(picFile\\\\n + File.separator + afileName));\\\\n pic.writeImageContent(out);\\\\n htmlText += "<img src=\\\\\\\\"" + picFile + File.separator + afileName\\\\n + "\\\\\\\\" mce_src=\\\\\\\\"" + picFile + File.separator + afileName\\\\n + "\\\\\\\\"/>";\\\\n }\\\\n \\\\n public static boolean compareCharStyle(CharacterRun cr1, CharacterRun cr2) {\\\\n boolean flag = false;\\\\n if (cr1.isBold() == cr2.isBold() && cr1.isItalic() == cr2.isItalic()\\\\n && cr1.getFontName().equals(cr2.getFontName())\\\\n && cr1.getFontSize() == cr2.getFontSize()) {\\\\n flag = true;\\\\n }\\\\n return flag;\\\\n }\\\\n \\\\n /**\\\\n * 写入文件\\\\n * \\\\n * @param s\\\\n */\\\\n public static void writeFile(String s) {\\\\n FileOutputStream fos = null;\\\\n BufferedWriter bw = null;\\\\n try {\\\\n File file = new File(outPutFile);\\\\n fos = new FileOutputStream(file);\\\\n bw = new BufferedWriter(new OutputStreamWriter(fos));\\\\n bw.write(s);\\\\n } catch (FileNotFoundException fnfe) {\\\\n fnfe.printStackTrace();\\\\n } catch (IOException ioe) {\\\\n ioe.printStackTrace();\\\\n } finally {\\\\n try {\\\\n if (bw != null)\\\\n bw.close();\\\\n if (fos != null)\\\\n fos.close();\\\\n } catch (IOException ie) {\\\\n }\\\\n }\\\\n }\\\\n }

通过上述代码,您可以自己修改文件位置,生成的HTML页面位置,保存的图片位置等,注意本文仅支持以.doc格式的word文档。


分类   项目开发逻辑
字数   9773

博客标签    poi 获取 word中的图片   poi 获取图片位置   poi生成html   最新poi 读写word 图片  

评论