poi實現excel轉html

使用poi將excel轉爲html,如果需要表格可編輯,可以讓你們前端給提供樣式設置到代碼裏,碼雲代碼庫位置poiexample,歡迎來豐富它的功能

poi版本 4.1.2

pom依賴

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.2</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-scratchpad</artifactId>
	<version>4.1.2</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.2</version>
</dependency>

使用方法:

main方法調用測試:

public class Tmp {
    public static void main(String[] args) throws Exception {
        String arg1 = "C:\\Users\\test.xlsx";
        StringBuilder stringBuilder = new StringBuilder();
        // 打印實現Appendable 接口,可打印到stringbuilder、stringbuffer、BufferedWriter等
        ExcelToHtml excelToHtml = ExcelToHtml.create(arg1, stringBuilder);
        excelToHtml.setCompleteHTML(true);// 是否打印完整html
        excelToHtml.printPage();// 打印
        System.out.println(stringBuilder.toString());// 輸出打印結果
    }
}

下面幾個工具文件:

ExcelToHtml.java 主要操作方法類

HtmlHelper.java 幫助類接口

HSSFHtmlHelper.java 97-2007版本excel實現幫助類
XSSFHtmlHelper.java 新版本excel實現幫助類

ExcelToHtml.java:

package com.demo.exceltohtml;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.format.CellFormat;
import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.*;

public class ExcelToHtml {

    private final Workbook wb;
    private final Appendable output;
    private boolean completeHTML;
    private Formatter out;
    private boolean gotBounds;
    private int firstColumn;
    private int endColumn;
    private HtmlHelper helper;

    private static final String DEFAULTS_CLASS = "excelDefaults";
    private static final String COL_HEAD_CLASS = "colHeader";
    private static final String ROW_HEAD_CLASS = "rowHeader";

    private static final Map<HorizontalAlignment, String> HALIGN = mapFor(
            HorizontalAlignment.LEFT, "left",
            HorizontalAlignment.CENTER, "center",
            HorizontalAlignment.RIGHT, "right",
            HorizontalAlignment.FILL, "left",
            HorizontalAlignment.JUSTIFY, "left",
            HorizontalAlignment.CENTER_SELECTION, "center");

    private static final Map<VerticalAlignment, String> VALIGN = mapFor(
            VerticalAlignment.BOTTOM, "bottom",
            VerticalAlignment.CENTER, "middle",
            VerticalAlignment.TOP, "top");

    private static final Map<BorderStyle, String> BORDER = mapFor(
            BorderStyle.DASH_DOT, "dashed 1pt",
            BorderStyle.DASH_DOT_DOT, "dashed 1pt",
            BorderStyle.DASHED, "dashed 1pt",
            BorderStyle.DOTTED, "dotted 1pt",
            BorderStyle.DOUBLE, "double 3pt",
            BorderStyle.HAIR, "solid 1px",
            BorderStyle.MEDIUM, "solid 2pt",
            BorderStyle.MEDIUM_DASH_DOT, "dashed 2pt",
            BorderStyle.MEDIUM_DASH_DOT_DOT, "dashed 2pt",
            BorderStyle.MEDIUM_DASHED, "dashed 2pt",
            BorderStyle.NONE, "none",
            BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
            BorderStyle.THICK, "solid 3pt",
            BorderStyle.THIN, "dashed 1pt");

    private static final int IDX_TABLE_WIDTH = -2;
    private static final int IDX_HEADER_COL_WIDTH = -1;

    @SuppressWarnings({"unchecked"})
    private static <K, V> Map<K, V> mapFor(Object... mapping) {
        Map<K, V> map = new HashMap<>();
        for (int i = 0; i < mapping.length; i += 2) {
            map.put((K) mapping[i], (V) mapping[i + 1]);
        }
        return map;
    }

    public static ExcelToHtml create(Workbook wb, Appendable output) {
        return new ExcelToHtml(wb, output);
    }

    public static ExcelToHtml create(String path, Appendable output)
            throws IOException {
        return create(new FileInputStream(path), output);
    }

    public static ExcelToHtml create(InputStream in, Appendable output)
            throws IOException {
        Workbook wb = WorkbookFactory.create(in);
        return create(wb, output);
    }

    private ExcelToHtml(Workbook wb, Appendable output) {
        if (wb == null) {
            throw new NullPointerException("wb");
        }
        if (output == null) {
            throw new NullPointerException("output");
        }
        this.wb = wb;
        this.output = output;
        setupColorMap();
    }

    private void setupColorMap() {
        if (wb instanceof HSSFWorkbook) {
            helper = new HSSFHtmlHelper((HSSFWorkbook) wb);
        } else if (wb instanceof XSSFWorkbook) {
            helper = new XSSFHtmlHelper();
        } else {
            throw new IllegalArgumentException(
                    "unknown workbook type: " + wb.getClass().getSimpleName());
        }
    }

    public void setCompleteHTML(boolean completeHTML) {
        this.completeHTML = completeHTML;
    }

    public void printPage() throws IOException {
        try {
            ensureOut();
            if (completeHTML) {
                out.format(
                        "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>%n");
                out.format("<html>%n");
                out.format("<head>%n");
                out.format("</head>%n");
                out.format("<body>%n");
            }

            print();

            if (completeHTML) {
                out.format("</body>%n");
                out.format("</html>%n");
            }
        } finally {
            IOUtils.closeQuietly(out);
            if (output instanceof Closeable) {
                IOUtils.closeQuietly((Closeable) output);
            }
        }
    }

    public void print() {
        printInlineStyle();
        printSheets();
    }

    private void printInlineStyle() {
        //out.format("<link href=\"excelStyle.css\" rel=\"stylesheet\" type=\"text/css\">%n");
        out.format("<style type=\"text/css\">%n");
        printStyles();
        out.format("</style>%n");
    }

    private void ensureOut() {
        if (out == null) {
            out = new Formatter(output);
        }
    }

    public void printStyles() {
        ensureOut();
        // First, copy the base css
        out.format(".excelDefaults {%n");
        out.format("	background-color: white;%n");
        out.format("	color: black;%n");
        out.format("	text-decoration: none;%n");
        out.format("	direction: ltr;%n");
        out.format("	text-transform: none;%n");
        out.format("	text-indent: 0;%n");
        out.format("	letter-spacing: 0;%n");
        out.format("	word-spacing: 0;%n");
        out.format("	white-space: pre-wrap;%n");
        out.format("	unicode-bidi: normal;%n");
        out.format("	vertical-align: 0;%n");
        out.format("	background-image: none;%n");
        out.format("	text-shadow: none;%n");
        out.format("	list-style-image: none;%n");
        out.format("	list-style-type: none;%n");
        out.format("	padding: 0;%n");
        out.format("	margin: 0;%n");
        out.format("	border-collapse: collapse;%n");
        out.format("	vertical-align: bottom;%n");
        out.format("	font-style: normal;%n");
        out.format("	font-family: sans-serif;%n");
        out.format("	font-variant: normal;%n");
        out.format("	font-weight: normal;%n");
        out.format("	font-size: 10pt;%n");
        out.format("	text-align: right;%n");
        out.format("	table-layout: fixed;%n");
        out.format("	word-wrap: break-word;%n");
        out.format("	overflow-wrap: break-word;%n");
        out.format("}%n");
        out.format("%n");
        out.format(".excelDefaults td {%n");
        out.format("	padding: 1px 5px;%n");
        out.format("	border: 1px solid silver;%n");
        out.format("}%n");
        out.format("%n");
        out.format(".excelDefaults .colHeader {%n");
        out.format("	background-color: silver;%n");
        out.format("	font-weight: bold;%n");
        out.format("	border: 1px solid black;%n");
        out.format("	text-align: center;%n");
        out.format("	padding: 1px 5px;%n");
        out.format("}%n");
        out.format("%n");
        out.format(".excelDefaults .rowHeader {%n");
        out.format("	background-color: silver;%n");
        out.format("	font-weight: bold;%n");
        out.format("	border: 1px solid black;%n");
        out.format("	text-align: right;%n");
        out.format("	padding: 1px 5px;%n");
        out.format("}%n");
        // now add css for each used style
        Set<CellStyle> seen = new HashSet<>();
        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
            Sheet sheet = wb.getSheetAt(i);
            Iterator<Row> rows = sheet.rowIterator();
            while (rows.hasNext()) {
                Row row = rows.next();
                for (Cell cell : row) {
                    CellStyle style = cell.getCellStyle();
                    if (!seen.contains(style)) {
                        printStyle(style);
                        seen.add(style);
                    }
                }
            }
        }
    }

    private void printStyle(CellStyle style) {
        out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style));
        styleContents(style);
        out.format("}%n");
    }

    private void styleContents(CellStyle style) {
        styleOut("text-align", style.getAlignment(), HALIGN);
        styleOut("vertical-align", style.getVerticalAlignment(), VALIGN);
        fontStyle(style);
        borderStyles(style);
        helper.colorStyles(style, out);
    }

    private void borderStyles(CellStyle style) {
        styleOut("border-left", style.getBorderLeft(), BORDER);
        styleOut("border-right", style.getBorderRight(), BORDER);
        styleOut("border-top", style.getBorderTop(), BORDER);
        styleOut("border-bottom", style.getBorderBottom(), BORDER);
    }

    private void fontStyle(CellStyle style) {
        Font font = wb.getFontAt(style.getFontIndexAsInt());

        if (font.getBold()) {
            out.format("  font-weight: bold;%n");
        }
        if (font.getItalic()) {
            out.format("  font-style: italic;%n");
        }

        int fontheight = font.getFontHeightInPoints();
        if (fontheight == 9) {
            //fix for stupid ol Windows
            fontheight = 10;
        }
        out.format("  font-size: %dpt;%n", fontheight);

        // Font color is handled with the other colors
    }

    private String styleName(CellStyle style) {
        if (style == null) {
            style = wb.getCellStyleAt((short) 0);
        }
        StringBuilder sb = new StringBuilder();
        try (Formatter fmt = new Formatter(sb)) {
            fmt.format("style_%02x", style.getIndex());
            return fmt.toString();
        }
    }

    private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
        String value = mapping.get(key);
        if (value != null) {
            out.format("  %s: %s;%n", attr, value);
        }
    }

    private static CellType ultimateCellType(Cell c) {
        CellType type = c.getCellType();
        if (type == CellType.FORMULA) {
            type = c.getCachedFormulaResultType();
        }
        return type;
    }

    private void printSheets() {
        ensureOut();
        Sheet sheet = wb.getSheetAt(0);
        printSheet(sheet);
    }

    public void printSheet(Sheet sheet) {
        ensureOut();
        Map<Integer, Integer> widths = computeWidths(sheet);
        int tableWidth = widths.get(IDX_TABLE_WIDTH);
        out.format("<table class=%s style=\"width:%dpx;\">%n", DEFAULTS_CLASS, tableWidth);
        printCols(widths);
        printSheetContent(sheet);
        out.format("</table>%n");
    }

    /**
     * computes the column widths, defined by the sheet.
     *
     * @param sheet The sheet for which to compute widths
     * @return Map with key: column index; value: column width in pixels
     * <br>special keys:
     * <br>{@link #IDX_HEADER_COL_WIDTH} - width of the header column
     * <br>{@link #IDX_TABLE_WIDTH} - width of the entire table
     */
    private Map<Integer, Integer> computeWidths(Sheet sheet) {
        Map<Integer, Integer> ret = new TreeMap<>();
        int tableWidth = 0;

        ensureColumnBounds(sheet);

        // compute width of the header column
        int lastRowNum = sheet.getLastRowNum();
        int headerCharCount = String.valueOf(lastRowNum).length();
        int headerColWidth = widthToPixels((headerCharCount + 1) * 256.0);
        ret.put(IDX_HEADER_COL_WIDTH, headerColWidth);
        tableWidth += headerColWidth;

        for (int i = firstColumn; i < endColumn; i++) {
            int colWidth = widthToPixels(sheet.getColumnWidth(i));
            ret.put(i, colWidth);
            tableWidth += colWidth;
        }

        ret.put(IDX_TABLE_WIDTH, tableWidth);
        return ret;
    }

    /**
     * Probably platform-specific, but appears to be a close approximation on some systems
     *
     * @param widthUnits POI's native width unit (twips)
     * @return the approximate number of pixels for a typical display
     */
    protected int widthToPixels(final double widthUnits) {
        return Math.toIntExact(Math.round(widthUnits * 9 / 256));
    }

    private void printCols(Map<Integer, Integer> widths) {
        int headerColWidth = widths.get(IDX_HEADER_COL_WIDTH);
        out.format("<col style=\"width:%dpx\"/>%n", headerColWidth);
        for (int i = firstColumn; i < endColumn; i++) {
            int colWidth = widths.get(i);
            out.format("<col style=\"width:%dpx;\"/>%n", colWidth);
        }
    }

    private void ensureColumnBounds(Sheet sheet) {
        if (gotBounds) {
            return;
        }

        Iterator<Row> iter = sheet.rowIterator();
        firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0);
        endColumn = 0;
        while (iter.hasNext()) {
            Row row = iter.next();
            short firstCell = row.getFirstCellNum();
            if (firstCell >= 0) {
                firstColumn = Math.min(firstColumn, firstCell);
                endColumn = Math.max(endColumn, row.getLastCellNum());
            }
        }
        gotBounds = true;
    }

    private void printColumnHeads() {
        out.format("<thead>%n");
        out.format("  <tr class=%s>%n", COL_HEAD_CLASS);
        out.format("    <th class=%s>&#x25CA;</th>%n", COL_HEAD_CLASS);
        //noinspection UnusedDeclaration
        StringBuilder colName = new StringBuilder();
        for (int i = firstColumn; i < endColumn; i++) {
            colName.setLength(0);
            int cnum = i;
            do {
                colName.insert(0, (char) ('A' + cnum % 26));
                cnum /= 26;
            } while (cnum > 0);
            out.format("    <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName);
        }
        out.format("  </tr>%n");
        out.format("</thead>%n");
    }

    private void printSheetContent(Sheet sheet) {
        printColumnHeads();

        out.format("<tbody>%n");
        Iterator<Row> rows = sheet.rowIterator();
        while (rows.hasNext()) {
            Row row = rows.next();

            out.format("  <tr>%n");
            out.format("    <td class=%s>%d</td>%n", ROW_HEAD_CLASS,
                    row.getRowNum() + 1);
            for (int i = firstColumn; i < endColumn; i++) {
                String content = "&nbsp;";
                String attrs = "";
                CellStyle style = null;
                if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) {
                    Cell cell = row.getCell(i);
                    if (cell != null) {
                        style = cell.getCellStyle();
                        attrs = tagStyle(cell, style);
                        //Set the value that is rendered for the cell
                        //also applies the format
                        CellFormat cf = CellFormat.getInstance(
                                style.getDataFormatString());
                        CellFormatResult result = cf.apply(cell);
                        content = result.text; //never null
                        if (content.isEmpty()) {
                            content = "&nbsp;";
                        }
                    }
                }
                out.format("    <td class=%s %s>%s</td>%n", styleName(style),
                        attrs, content);
            }
            out.format("  </tr>%n");
        }
        out.format("</tbody>%n");
    }

    private String tagStyle(Cell cell, CellStyle style) {
        if (style.getAlignment() == HorizontalAlignment.GENERAL) {
            switch (ultimateCellType(cell)) {
                case STRING:
                    return "style=\"text-align: left;\"";
                case BOOLEAN:
                case ERROR:
                    return "style=\"text-align: center;\"";
                case NUMERIC:
                default:
                    // "right" is the default
                    break;
            }
        }
        return "";
    }
}

HtmlHelper.java

package com.demo.exceltohtml;

import java.util.Formatter;
import org.apache.poi.ss.usermodel.CellStyle;

public interface HtmlHelper {
    void colorStyles(CellStyle var1, Formatter var2);
}

HSSFHtmlHelper.java

package com.demo.exceltohtml;

import java.util.Formatter;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.CellStyle;

public class HSSFHtmlHelper implements HtmlHelper {
    private final HSSFWorkbook wb;
    private final HSSFPalette colors;
    private static final HSSFColor HSSF_AUTO;

    public HSSFHtmlHelper(HSSFWorkbook wb) {
        this.wb = wb;
        this.colors = wb.getCustomPalette();
    }

    public void colorStyles(CellStyle style, Formatter out) {
        HSSFCellStyle cs = (HSSFCellStyle) style;
        out.format("  /* fill pattern = %d */%n", cs.getFillPattern().getCode());
        this.styleColor(out, "background-color", cs.getFillForegroundColor());
        this.styleColor(out, "color", cs.getFont(this.wb).getColor());
        this.styleColor(out, "border-left-color", cs.getLeftBorderColor());
        this.styleColor(out, "border-right-color", cs.getRightBorderColor());
        this.styleColor(out, "border-top-color", cs.getTopBorderColor());
        this.styleColor(out, "border-bottom-color", cs.getBottomBorderColor());
    }

    private void styleColor(Formatter out, String attr, short index) {
        HSSFColor color = this.colors.getColor(index);
        if (index != HSSF_AUTO.getIndex() && color != null) {
            short[] rgb = color.getTriplet();
            out.format("  %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0], rgb[1], rgb[2], index);
        } else {
            out.format("  /* %s: index = %d */%n", attr, index);
        }

    }

    static {
        HSSF_AUTO = HSSFColorPredefined.AUTOMATIC.getColor();
    }
}

XSSFHtmlHelper.java

package com.demo.exceltohtml;

import java.util.Formatter;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;

public class XSSFHtmlHelper implements HtmlHelper {
    public XSSFHtmlHelper() {
    }

    public void colorStyles(CellStyle style, Formatter out) {
        XSSFCellStyle cs = (XSSFCellStyle)style;
        this.styleColor(out, "background-color", cs.getFillForegroundXSSFColor());
        this.styleColor(out, "text-color", cs.getFont().getXSSFColor());
    }

    private void styleColor(Formatter out, String attr, XSSFColor color) {
        if (color != null && !color.isAuto()) {
            byte[] rgb = color.getRGB();
            if (rgb != null) {
                out.format("  %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]);
                byte[] argb = color.getARGB();
                if (argb != null) {
                    out.format("  %s: rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x);%n", attr, argb[3], argb[0], argb[1], argb[2]);
                }
            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章