@@ -1,67 +1,57 @@ | |||
package cn.afterturn.easypoi.excel.html; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import java.util.Formatter; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import cn.afterturn.easypoi.excel.entity.ExcelToHtmlParams; | |||
import cn.afterturn.easypoi.excel.html.helper.CellValueHelper; | |||
import cn.afterturn.easypoi.excel.html.helper.MergedRegionHelper; | |||
import cn.afterturn.easypoi.excel.html.helper.StyleHelper; | |||
import cn.afterturn.easypoi.util.PoiPublicUtil; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.apache.poi.hssf.usermodel.HSSFSheet; | |||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||
import org.apache.poi.ss.usermodel.Cell; | |||
import org.apache.poi.ss.usermodel.CellStyle; | |||
import org.apache.poi.ss.usermodel.PictureData; | |||
import org.apache.poi.ss.usermodel.Row; | |||
import org.apache.poi.ss.usermodel.Sheet; | |||
import org.apache.poi.ss.usermodel.Workbook; | |||
import org.apache.poi.ss.usermodel.*; | |||
import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import sun.misc.BASE64Encoder; | |||
import cn.afterturn.easypoi.excel.entity.ExcelToHtmlParams; | |||
import cn.afterturn.easypoi.excel.html.helper.CellValueHelper; | |||
import cn.afterturn.easypoi.excel.html.helper.MergedRegionHelper; | |||
import cn.afterturn.easypoi.excel.html.helper.StylerHelper; | |||
import cn.afterturn.easypoi.util.PoiPublicUtil; | |||
import java.text.SimpleDateFormat; | |||
import java.util.*; | |||
/** | |||
* Excel转换成Html 服务 | |||
* | |||
* @author JueYue | |||
* 2015年5月10日 上午11:41:15 | |||
* 2015年5月10日 上午11:41:15 | |||
*/ | |||
public class ExcelToHtmlService { | |||
private static final Logger LOGGER = LoggerFactory | |||
.getLogger(ExcelToHtmlService.class); | |||
private static final Logger LOGGER = LoggerFactory | |||
.getLogger(ExcelToHtmlService.class); | |||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd"); | |||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd"); | |||
private String today; | |||
private String today; | |||
private Workbook wb; | |||
private int sheetNum; | |||
private int cssRandom; | |||
private Workbook wb; | |||
private int sheetNum; | |||
private int cssRandom; | |||
/*是不是完成界面*/ | |||
private boolean completeHTML; | |||
private Formatter out; | |||
private boolean completeHTML; | |||
private Formatter out; | |||
/*已经完成范围处理*/ | |||
private boolean gotBounds; | |||
private int firstColumn; | |||
private int endColumn; | |||
private String imageCachePath; | |||
private static final String COL_HEAD_CLASS = "colHeader"; | |||
private boolean gotBounds; | |||
private int firstColumn; | |||
private int endColumn; | |||
private String imageCachePath; | |||
private static final String COL_HEAD_CLASS = "colHeader"; | |||
//private static final String ROW_HEAD_CLASS = "rowHeader"; | |||
private static final String DEFAULTS_CLASS = "excelDefaults"; | |||
private static final String DEFAULTS_CLASS = "excelDefaults"; | |||
//图片缓存 | |||
private Map<String, PictureData> pictures = new HashMap<String, PictureData>(); | |||
private Map<String, PictureData> pictures = new HashMap<String, PictureData>(); | |||
public ExcelToHtmlService(ExcelToHtmlParams params) { | |||
this.wb = params.getWb(); | |||
@@ -79,13 +69,13 @@ public class ExcelToHtmlService { | |||
out.format("<!DOCTYPE HTML>%n"); | |||
out.format("<html>%n"); | |||
out.format( | |||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">%n"); | |||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">%n"); | |||
out.format("<head>%n"); | |||
} | |||
if (StringUtils.isNotEmpty(imageCachePath)) { | |||
getPictures(); | |||
} | |||
new StylerHelper(wb, out, sheetNum, cssRandom); | |||
new StyleHelper(wb, out, sheetNum, cssRandom); | |||
if (completeHTML) { | |||
out.format("</head>%n"); | |||
out.format("<body>%n"); | |||
@@ -112,10 +102,10 @@ public class ExcelToHtmlService { | |||
private void getPictures() { | |||
if (wb instanceof XSSFWorkbook) { | |||
pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) wb.getSheetAt(sheetNum), | |||
(XSSFWorkbook) wb); | |||
(XSSFWorkbook) wb); | |||
} else { | |||
pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) wb.getSheetAt(sheetNum), | |||
(HSSFWorkbook) wb); | |||
(HSSFWorkbook) wb); | |||
} | |||
} | |||
@@ -220,17 +210,17 @@ public class ExcelToHtmlService { | |||
} | |||
} | |||
if (pictures.containsKey((rowIndex - 1) + "_" + i)) { | |||
content = "<img src='data:image/"+PoiPublicUtil.getFileExtendName(pictures.get((rowIndex - 1) + "_" + i).getData()) | |||
+";base64," + getImageSrc(pictures.get((rowIndex - 1) + "_" + i)) | |||
+ "' style='max-width: " | |||
+ getImageMaxWidth( | |||
mergedRegionHelper.getRowAndColSpan(rowIndex, i), i, sheet) | |||
+ "px;' />"; | |||
content = "<img src='data:image/" + PoiPublicUtil.getFileExtendName(pictures.get((rowIndex - 1) + "_" + i).getData()) | |||
+ ";base64," + getImageSrc(pictures.get((rowIndex - 1) + "_" + i)) | |||
+ "' style='max-width: " | |||
+ getImageMaxWidth( | |||
mergedRegionHelper.getRowAndColSpan(rowIndex, i), i, sheet) | |||
+ "px;' />"; | |||
} | |||
if (mergedRegionHelper.isMergedRegion(rowIndex, i)) { | |||
Integer[] rowAndColSpan = mergedRegionHelper.getRowAndColSpan(rowIndex, i); | |||
out.format(" <td rowspan='%s' colspan='%s' class='%s' >%s</td>%n", | |||
rowAndColSpan[0], rowAndColSpan[1], styleName(style), content); | |||
rowAndColSpan[0], rowAndColSpan[1], styleName(style), content); | |||
} else { | |||
out.format(" <td class='%s'>%s</td>%n", styleName(style), content); | |||
} | |||
@@ -245,9 +235,10 @@ public class ExcelToHtmlService { | |||
/** | |||
* 获取图片最大宽度 | |||
* @param colIndex | |||
* @param sheet | |||
* @param rowAndColSpan | |||
* | |||
* @param colIndex | |||
* @param sheet | |||
* @param rowAndColSpan | |||
* @return | |||
*/ | |||
private int getImageMaxWidth(Integer[] rowAndColSpan, int colIndex, Sheet sheet) { | |||
@@ -263,6 +254,7 @@ public class ExcelToHtmlService { | |||
/** | |||
* 获取图片路径 | |||
* | |||
* @param pictureData | |||
* @return | |||
*/ | |||
@@ -306,6 +298,6 @@ public class ExcelToHtmlService { | |||
return ""; | |||
} | |||
return String.format("style_%02x_%s font_%s_%s", style.getIndex(), cssRandom, | |||
style.getFontIndex(), cssRandom); | |||
style.getFontIndex(), cssRandom); | |||
} | |||
} |
@@ -19,6 +19,9 @@ import cn.afterturn.easypoi.excel.html.css.ICssConvertToHtml; | |||
import cn.afterturn.easypoi.excel.html.entity.style.CellStyleEntity; | |||
import cn.afterturn.easypoi.util.PoiCssUtils; | |||
/** | |||
* @author jueyue | |||
*/ | |||
public class TextCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml { | |||
@Override | |||
@@ -50,9 +53,9 @@ public class TextCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml | |||
String color = style.getFont().getColor(); | |||
if (StringUtils.isNoneEmpty(color)) { | |||
if (font instanceof HSSFFont) { | |||
setFoutForHSSF(font, cell.getSheet().getWorkbook(), color); | |||
setFontForHSSF(font, cell.getSheet().getWorkbook(), color); | |||
} else if (font instanceof XSSFFont) { | |||
setFoutForXSSF(font, color); | |||
setFontForXSSF(font, color); | |||
} | |||
} | |||
if (UNDERLINE.equals(style.getFont().getDecoration())) { | |||
@@ -61,12 +64,12 @@ public class TextCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml | |||
cellStyle.setFont(font); | |||
} | |||
private void setFoutForXSSF(Font font, String colorStr) { | |||
private void setFontForXSSF(Font font, String colorStr) { | |||
XSSFColor color = PoiCssUtils.parseColor(colorStr); | |||
((XSSFFont)font).setColor(color); | |||
} | |||
private void setFoutForHSSF(Font font, Workbook workbook, String colorStr) { | |||
private void setFontForHSSF(Font font, Workbook workbook, String colorStr) { | |||
HSSFColor color = PoiCssUtils.parseColor((HSSFWorkbook) workbook, colorStr); | |||
if (color != null) { | |||
if (color.getIndex() != BLACK.index) { | |||
@@ -1,272 +1,269 @@ | |||
package cn.afterturn.easypoi.excel.html.helper; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.util.Formatter; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import java.util.Set; | |||
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.ss.usermodel.*; | |||
import org.apache.poi.xssf.usermodel.XSSFCellStyle; | |||
import org.apache.poi.xssf.usermodel.XSSFColor; | |||
import org.apache.poi.xssf.usermodel.XSSFFont; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import cn.afterturn.easypoi.util.PoiPublicUtil; | |||
/** | |||
* 样式帮助类 | |||
* | |||
* @author JueYue | |||
* 2015年5月9日 下午4:04:24 | |||
*/ | |||
public class StylerHelper { | |||
private static String DEFAULTS_CLASS_CSS = ".excelDefaults {background-color: white;color: black;text-decoration: none;direction: ltr;text-transform: none;text-indent: 0;letter-spacing: 0;word-spacing: 0;white-space: normal;unicode-bidi: normal;vertical-align: 0;text-shadow: none;padding: 0;margin: 0;border-collapse: collapse;white-space: pre-wrap;word-wrap: break-word;word-break: break-all;}.excelDefaults td {padding: 1px 5px;border: 1px solid silver;border-color: #000000;text-align: center;vertical-align: middle;font-size: 12pt;}.excelDefaults .colHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: center;padding: 1px 5px;}.excelDefaults .rowHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: right;padding: 1px 5px;}"; | |||
private static final String DEFAULTS_CLASS = "excelDefaults"; | |||
private static final Map<HorizontalAlignment, String> ALIGN = PoiPublicUtil.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> VERTICAL_ALIGN = PoiPublicUtil | |||
.mapFor(VerticalAlignment.BOTTOM, "bottom", VerticalAlignment.CENTER, | |||
"middle", VerticalAlignment.TOP, "top"); | |||
private Formatter out; | |||
private Sheet sheet; | |||
private HtmlHelper helper; | |||
private int sheetNum; | |||
private int cssRandom; | |||
public StylerHelper(Workbook wb, Formatter out, int sheetNum, int cssRandom) { | |||
this.out = out; | |||
this.sheetNum = sheetNum; | |||
this.cssRandom = cssRandom; | |||
if (wb instanceof HSSFWorkbook) { | |||
helper = new HSSFHtmlHelper((HSSFWorkbook) wb); | |||
} else if (wb instanceof XSSFWorkbook) { | |||
helper = new XSSFHtmlHelper((XSSFWorkbook) wb); | |||
} else { | |||
throw new IllegalArgumentException( | |||
"unknown workbook type: " + wb.getClass().getSimpleName()); | |||
} | |||
printInlineStyle(wb); | |||
} | |||
private void printInlineStyle(Workbook wb) { | |||
out.format("<style type=\"text/css\">%n"); | |||
printStyles(wb); | |||
printFonts(wb); | |||
out.format("</style>%n"); | |||
} | |||
private void printFonts(Workbook wb) { | |||
for (short i = 0, le = wb.getNumberOfFonts(); i < le; i++) { | |||
Font font = wb.getFontAt(i); | |||
out.format(".%s .%s {%n", DEFAULTS_CLASS, "font_" + i + "_" + cssRandom); | |||
fontStyle(font); | |||
out.format("}%n"); | |||
} | |||
} | |||
public void printStyles(Workbook wb) { | |||
if (DEFAULTS_CLASS_CSS == null) { | |||
DEFAULTS_CLASS_CSS = getDefaultsClassCss(); | |||
} | |||
out.format(DEFAULTS_CLASS_CSS); | |||
Set<CellStyle> seen = new HashSet<CellStyle>(); | |||
sheet = wb.getSheetAt(sheetNum); | |||
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 String getDefaultsClassCss() { | |||
BufferedReader in = null; | |||
StringBuilder sb = new StringBuilder(); | |||
Formatter formatter = new Formatter(sb); | |||
try { | |||
in = new BufferedReader( | |||
new InputStreamReader(StylerHelper.class.getResourceAsStream("excelStyle.css"))); | |||
String line; | |||
while ((line = in.readLine()) != null) { | |||
formatter.format("%s%n", line); | |||
} | |||
return formatter.toString(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Reading standard css", e); | |||
} finally { | |||
if (in != null) { | |||
try { | |||
in.close(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Reading standard css", e); | |||
} | |||
} | |||
formatter.close(); | |||
} | |||
} | |||
private void printStyle(CellStyle style) { | |||
out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style)); | |||
styleContents(style); | |||
out.format("}%n"); | |||
} | |||
private void styleContents(CellStyle style) { | |||
if (style.getAlignment() != HorizontalAlignment.CENTER) { | |||
styleOut("text-align", style.getAlignment(), ALIGN); | |||
styleOut("vertical-align", style.getVerticalAlignment(), VERTICAL_ALIGN); | |||
} | |||
helper.colorStyles(style, out); | |||
} | |||
private void fontStyle(Font font) { | |||
if (font.getBold()) { | |||
out.format(" font-weight: bold;%n"); | |||
} | |||
if (font.getItalic()) { | |||
out.format(" font-style: italic;%n"); | |||
} | |||
out.format(" font-family: %s;%n", font.getFontName()); | |||
int fontheight = font.getFontHeightInPoints(); | |||
if (fontheight == 9) { | |||
fontheight = 10; | |||
} | |||
out.format(" font-size: %dpt;%n", fontheight); | |||
helper.styleColor(out, "color", getColor(font)); | |||
} | |||
private Color getColor(Font font) { | |||
if (helper instanceof HSSFHtmlHelper) { | |||
return ((HSSFWorkbook) sheet.getWorkbook()).getCustomPalette() | |||
.getColor(font.getColor()); | |||
} else { | |||
return ((XSSFFont) font).getXSSFColor(); | |||
} | |||
} | |||
private String styleName(CellStyle style) { | |||
if (style == null) { | |||
return ""; | |||
} | |||
return String.format("style_%02x_%s", style.getIndex(), cssRandom); | |||
} | |||
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 interface HtmlHelper { | |||
/** | |||
* Outputs the appropriate CSS style for the given cell style. | |||
* | |||
* @param style The cell style. | |||
* @param out The place to write the output. | |||
*/ | |||
void colorStyles(CellStyle style, Formatter out); | |||
void styleColor(Formatter out, String attr, Color color); | |||
} | |||
private class HSSFHtmlHelper implements HtmlHelper { | |||
private final HSSFWorkbook wb; | |||
private final HSSFPalette colors; | |||
private HSSFColor hssfAuto = HSSFColor.HSSFColorPredefined.AUTOMATIC.getColor(); | |||
public HSSFHtmlHelper(HSSFWorkbook wb) { | |||
this.wb = wb; | |||
colors = wb.getCustomPalette(); | |||
} | |||
@Override | |||
public void colorStyles(CellStyle style, Formatter out) { | |||
HSSFCellStyle cs = (HSSFCellStyle) style; | |||
out.format(" /* fill pattern = %d */%n", cs.getFillPattern()); | |||
styleColor(out, "background-color", cs.getFillForegroundColor()); | |||
styleColor(out, "color", colors.getColor(cs.getFont(wb).getColor())); | |||
} | |||
private void styleColor(Formatter out, String attr, short index) { | |||
HSSFColor color = colors.getColor(index); | |||
if (index == hssfAuto.getIndex() || color == null) { | |||
out.format(" /* %s: index = %d */%n", attr, index); | |||
} else { | |||
short[] rgb = color.getTriplet(); | |||
out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0], rgb[1], rgb[2], | |||
index); | |||
} | |||
} | |||
@Override | |||
public void styleColor(Formatter out, String attr, Color color) { | |||
if (color == null) { | |||
return; | |||
} | |||
HSSFColor hSSFColor = (HSSFColor) color; | |||
short[] rgb = hSSFColor.getTriplet(); | |||
out.format(" %s: #%02x%02x%02x; %n", attr, rgb[0], rgb[1], rgb[2]); | |||
} | |||
} | |||
/** | |||
* Implementation of {@link HtmlHelper} for XSSF files. | |||
* | |||
* @author Ken Arnold, Industrious Media LLC | |||
*/ | |||
private class XSSFHtmlHelper implements HtmlHelper { | |||
public XSSFHtmlHelper(XSSFWorkbook wb) { | |||
} | |||
@Override | |||
public void colorStyles(CellStyle style, Formatter out) { | |||
XSSFCellStyle cs = (XSSFCellStyle) style; | |||
styleColor(out, "background-color", cs.getFillForegroundXSSFColor()); | |||
styleColor(out, "color", cs.getFont().getXSSFColor()); | |||
} | |||
@Override | |||
public void styleColor(Formatter out, String attr, Color color) { | |||
XSSFColor xSSFColor = (XSSFColor) color; | |||
if (color == null || xSSFColor.isAuto()) { | |||
return; | |||
} | |||
byte[] rgb = xSSFColor.getRGB(); | |||
if (rgb == null) { | |||
return; | |||
} | |||
out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]); | |||
} | |||
} | |||
} | |||
package cn.afterturn.easypoi.excel.html.helper; | |||
import cn.afterturn.easypoi.util.PoiPublicUtil; | |||
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.ss.usermodel.*; | |||
import org.apache.poi.xssf.usermodel.XSSFCellStyle; | |||
import org.apache.poi.xssf.usermodel.XSSFColor; | |||
import org.apache.poi.xssf.usermodel.XSSFFont; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.util.*; | |||
/** | |||
* 样式帮助类 | |||
* | |||
* @author JueYue | |||
* 2015年5月9日 下午4:04:24 | |||
*/ | |||
public class StyleHelper { | |||
private static String DEFAULTS_CLASS_CSS = ".excelDefaults {background-color: white;color: black;text-decoration: none;direction: ltr;text-transform: none;text-indent: 0;letter-spacing: 0;word-spacing: 0;white-space: normal;unicode-bidi: normal;vertical-align: 0;text-shadow: none;padding: 0;margin: 0;border-collapse: collapse;white-space: pre-wrap;word-wrap: break-word;word-break: break-all;}.excelDefaults td {padding: 1px 5px;border: 1px solid silver;border-color: #000000;text-align: center;vertical-align: middle;font-size: 12pt;}.excelDefaults .colHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: center;padding: 1px 5px;}.excelDefaults .rowHeader {background-color: silver;font-weight: bold;border: 1px solid black;text-align: right;padding: 1px 5px;}"; | |||
private static final String DEFAULTS_CLASS = "excelDefaults"; | |||
private static final Map<HorizontalAlignment, String> ALIGN = PoiPublicUtil.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> VERTICAL_ALIGN = PoiPublicUtil | |||
.mapFor(VerticalAlignment.BOTTOM, "bottom", VerticalAlignment.CENTER, | |||
"middle", VerticalAlignment.TOP, "top"); | |||
private Formatter out; | |||
private Sheet sheet; | |||
private HtmlHelper helper; | |||
private int sheetNum; | |||
private int cssRandom; | |||
public StyleHelper(Workbook wb, Formatter out, int sheetNum, int cssRandom) { | |||
this.out = out; | |||
this.sheetNum = sheetNum; | |||
this.cssRandom = cssRandom; | |||
if (wb instanceof HSSFWorkbook) { | |||
helper = new HSSFHtmlHelper((HSSFWorkbook) wb); | |||
} else if (wb instanceof XSSFWorkbook) { | |||
helper = new XSSFHtmlHelper((XSSFWorkbook) wb); | |||
} else { | |||
throw new IllegalArgumentException( | |||
"unknown workbook type: " + wb.getClass().getSimpleName()); | |||
} | |||
printInlineStyle(wb); | |||
} | |||
private void printInlineStyle(Workbook wb) { | |||
out.format("<style type=\"text/css\">%n"); | |||
printStyles(wb); | |||
printFonts(wb); | |||
out.format("</style>%n"); | |||
} | |||
private void printFonts(Workbook wb) { | |||
for (short i = 0, le = wb.getNumberOfFonts(); i < le; i++) { | |||
Font font = wb.getFontAt(i); | |||
out.format(".%s .%s {%n", DEFAULTS_CLASS, "font_" + i + "_" + cssRandom); | |||
fontStyle(font); | |||
out.format("}%n"); | |||
} | |||
} | |||
public void printStyles(Workbook wb) { | |||
if (DEFAULTS_CLASS_CSS == null) { | |||
DEFAULTS_CLASS_CSS = getDefaultsClassCss(); | |||
} | |||
out.format(DEFAULTS_CLASS_CSS); | |||
Set<CellStyle> seen = new HashSet<CellStyle>(); | |||
sheet = wb.getSheetAt(sheetNum); | |||
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 String getDefaultsClassCss() { | |||
BufferedReader in = null; | |||
StringBuilder sb = new StringBuilder(); | |||
Formatter formatter = new Formatter(sb); | |||
try { | |||
in = new BufferedReader( | |||
new InputStreamReader(StyleHelper.class.getResourceAsStream("excelStyle.css"))); | |||
String line; | |||
while ((line = in.readLine()) != null) { | |||
formatter.format("%s%n", line); | |||
} | |||
return formatter.toString(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Reading standard css", e); | |||
} finally { | |||
if (in != null) { | |||
try { | |||
in.close(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Reading standard css", e); | |||
} | |||
} | |||
formatter.close(); | |||
} | |||
} | |||
private void printStyle(CellStyle style) { | |||
out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style)); | |||
styleContents(style); | |||
out.format("}%n"); | |||
} | |||
private void styleContents(CellStyle style) { | |||
if (style.getAlignment() != HorizontalAlignment.CENTER) { | |||
styleOut("text-align", style.getAlignment(), ALIGN); | |||
styleOut("vertical-align", style.getVerticalAlignment(), VERTICAL_ALIGN); | |||
} | |||
helper.colorStyles(style, out); | |||
} | |||
private void fontStyle(Font font) { | |||
if (font.getBold()) { | |||
out.format(" font-weight: bold;%n"); | |||
} | |||
if (font.getItalic()) { | |||
out.format(" font-style: italic;%n"); | |||
} | |||
out.format(" font-family: %s;%n", font.getFontName()); | |||
int fontheight = font.getFontHeightInPoints(); | |||
if (fontheight == 9) { | |||
fontheight = 10; | |||
} | |||
out.format(" font-size: %dpt;%n", fontheight); | |||
helper.styleColor(out, "color", getColor(font)); | |||
} | |||
private Color getColor(Font font) { | |||
if (helper instanceof HSSFHtmlHelper) { | |||
return ((HSSFWorkbook) sheet.getWorkbook()).getCustomPalette() | |||
.getColor(font.getColor()); | |||
} else { | |||
return ((XSSFFont) font).getXSSFColor(); | |||
} | |||
} | |||
private String styleName(CellStyle style) { | |||
if (style == null) { | |||
return ""; | |||
} | |||
return String.format("style_%02x_%s", style.getIndex(), cssRandom); | |||
} | |||
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 interface HtmlHelper { | |||
/** | |||
* Outputs the appropriate CSS style for the given cell style. | |||
* | |||
* @param style The cell style. | |||
* @param out The place to write the output. | |||
*/ | |||
void colorStyles(CellStyle style, Formatter out); | |||
void styleColor(Formatter out, String attr, Color color); | |||
} | |||
private class HSSFHtmlHelper implements HtmlHelper { | |||
private final HSSFWorkbook wb; | |||
private final HSSFPalette colors; | |||
private HSSFColor hssfAuto = HSSFColor.HSSFColorPredefined.AUTOMATIC.getColor(); | |||
public HSSFHtmlHelper(HSSFWorkbook wb) { | |||
this.wb = wb; | |||
colors = wb.getCustomPalette(); | |||
} | |||
@Override | |||
public void colorStyles(CellStyle style, Formatter out) { | |||
HSSFCellStyle cs = (HSSFCellStyle) style; | |||
if (cs.getFillPattern() != FillPatternType.NO_FILL) { | |||
out.format(" /* fill pattern = %s */%n", cs.getFillPattern()); | |||
} | |||
styleColor(out, "background-color", cs.getFillForegroundColor()); | |||
styleColor(out, "color", colors.getColor(cs.getFont(wb).getColor())); | |||
} | |||
private void styleColor(Formatter out, String attr, short index) { | |||
HSSFColor color = colors.getColor(index); | |||
if (index == hssfAuto.getIndex() || color == null) { | |||
out.format(" /* %s: index = %d */%n", attr, index); | |||
} else { | |||
short[] rgb = color.getTriplet(); | |||
out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0], rgb[1], rgb[2], | |||
index); | |||
} | |||
} | |||
@Override | |||
public void styleColor(Formatter out, String attr, Color color) { | |||
if (color == null) { | |||
return; | |||
} | |||
HSSFColor hSSFColor = (HSSFColor) color; | |||
short[] rgb = hSSFColor.getTriplet(); | |||
out.format(" %s: #%02x%02x%02x; %n", attr, rgb[0], rgb[1], rgb[2]); | |||
} | |||
} | |||
/** | |||
* Implementation of {@link HtmlHelper} for XSSF files. | |||
* | |||
* @author Ken Arnold, Industrious Media LLC | |||
*/ | |||
private class XSSFHtmlHelper implements HtmlHelper { | |||
public XSSFHtmlHelper(XSSFWorkbook wb) { | |||
} | |||
@Override | |||
public void colorStyles(CellStyle style, Formatter out) { | |||
XSSFCellStyle cs = (XSSFCellStyle) style; | |||
styleColor(out, "background-color", cs.getFillForegroundXSSFColor()); | |||
styleColor(out, "color", cs.getFont().getXSSFColor()); | |||
} | |||
@Override | |||
public void styleColor(Formatter out, String attr, Color color) { | |||
XSSFColor xSSFColor = (XSSFColor) color; | |||
if (color == null || xSSFColor.isAuto()) { | |||
return; | |||
} | |||
byte[] rgb = xSSFColor.getRGB(); | |||
if (rgb == null) { | |||
return; | |||
} | |||
out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]); | |||
} | |||
} | |||
} |
@@ -1,62 +1,45 @@ | |||
package cn.afterturn.easypoi.util; | |||
import java.util.Map; | |||
import java.awt.Color; | |||
import org.slf4j.Logger; | |||
import java.util.HashMap; | |||
import java.util.regex.Pattern; | |||
import java.util.regex.Matcher; | |||
import org.slf4j.LoggerFactory; | |||
import org.apache.poi.hssf.util.HSSFColor; | |||
import org.apache.poi.xssf.usermodel.XSSFColor; | |||
import org.apache.commons.lang3.StringUtils; | |||
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.xssf.usermodel.XSSFColor; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.awt.*; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
/** | |||
* @version 2.0.1 | |||
* @author Shaun Chyxion | |||
* @author JueYue | |||
* @version 2.0.1 | |||
*/ | |||
public class PoiCssUtils { | |||
private static final Logger log = LoggerFactory | |||
.getLogger(PoiCssUtils.class); | |||
// matches #rgb | |||
private static final String COLOR_PATTERN_VALUE_SHORT = "^(#(?:[a-f]|\\d){3})$"; | |||
// matches #rrggbb | |||
private static final String COLOR_PATTERN_VALUE_LONG = "^(#(?:[a-f]|\\d{2}){3})$"; | |||
// matches #rgb(r, g, b) | |||
private static final String COLOR_PATTERN_RGB = "^(rgb\\s*\\(\\s*(.+)\\s*,\\s*(.+)\\s*,\\s*(.+)\\s*\\))$"; | |||
private static final Pattern COLOR_PATTERN_VALUE_SHORT_PATTERN = Pattern.compile("([a-f]|\\d)"); | |||
private static final Pattern INT_PATTERN = Pattern.compile("^(\\d+)(?:\\w+|%)?$"); | |||
private static final Pattern INT_AND_PER_PATTERN = Pattern.compile("^(\\d*\\.?\\d+)\\s*(%)?$"); | |||
private static final Logger log = LoggerFactory | |||
.getLogger(PoiCssUtils.class); | |||
/** | |||
* matches #rgb | |||
*/ | |||
private static final String COLOR_PATTERN_VALUE_SHORT = "^(#(?:[a-f]|\\d){3})$"; | |||
/** | |||
* matches #rrggbb | |||
*/ | |||
private static final String COLOR_PATTERN_VALUE_LONG = "^(#(?:[a-f]|\\d{2}){3})$"; | |||
/** | |||
* matches #rgb(r, g, b) | |||
**/ | |||
private static final String COLOR_PATTERN_RGB = "^(rgb\\s*\\(\\s*(.+)\\s*,\\s*(.+)\\s*,\\s*(.+)\\s*\\))$"; | |||
// color name -> POI Color | |||
private static Map<String, HSSFColor> colors = new HashMap<String, HSSFColor>(); | |||
// static init | |||
static { | |||
for (Map.Entry<Integer, HSSFColor> color : HSSFColor.getIndexHash().entrySet()) { | |||
colors.put(colorName(color.getValue().getClass()), color.getValue()); | |||
} | |||
// light gray | |||
HSSFColor color = colors.get(colorName(HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getColor().getClass())); | |||
colors.put("lightgray", color); | |||
colors.put("lightgrey", color); | |||
// silver | |||
colors.put("silver", colors.get(colorName(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getColor().getClass()))); | |||
// darkgray | |||
color = colors.get(colorName(HSSFColor.HSSFColorPredefined.GREY_50_PERCENT.getColor().getClass())); | |||
colors.put("darkgray", color); | |||
colors.put("darkgrey", color); | |||
// gray | |||
color = colors.get(colorName(HSSFColor.HSSFColorPredefined.GREY_80_PERCENT.getColor().getClass())); | |||
colors.put("gray", color); | |||
colors.put("grey", color); | |||
} | |||
private static final Pattern COLOR_PATTERN_VALUE_SHORT_PATTERN = Pattern.compile("([a-f]|\\d)"); | |||
private static final Pattern INT_PATTERN = Pattern.compile("^(\\d+)(?:\\w+|%)?$"); | |||
private static final Pattern INT_AND_PER_PATTERN = Pattern.compile("^(\\d*\\.?\\d+)\\s*(%)?$"); | |||
/** | |||
* get color name | |||
* | |||
* @param color HSSFColor | |||
* @return color name | |||
*/ | |||
@@ -66,6 +49,7 @@ public class PoiCssUtils { | |||
/** | |||
* get int value of string | |||
* | |||
* @param strValue string value | |||
* @return int value | |||
*/ | |||
@@ -81,7 +65,8 @@ public class PoiCssUtils { | |||
} | |||
/** | |||
* check number string | |||
* check number string | |||
* | |||
* @param strValue string | |||
* @return true if string is number | |||
*/ | |||
@@ -91,6 +76,7 @@ public class PoiCssUtils { | |||
/** | |||
* process color | |||
* | |||
* @param color color to process | |||
* @return color after process | |||
*/ | |||
@@ -121,12 +107,12 @@ public class PoiCssUtils { | |||
if (m.matches()) { | |||
log.debug("RGB Color [{}] Found.", color); | |||
colorRtn = convertColor(calcColorValue(m.group(2)), calcColorValue(m.group(3)), | |||
calcColorValue(m.group(4))); | |||
calcColorValue(m.group(4))); | |||
log.debug("Translate RGB Color [{}] To Hex [{}].", color, colorRtn); | |||
} | |||
} | |||
// color name, red, green, ... | |||
else if ((poiColor = getColor(color)) != null) { | |||
else if ((poiColor = getHssfColor(color)) != null) { | |||
log.debug("Color Name [{}] Found.", color); | |||
short[] t = poiColor.getTriplet(); | |||
colorRtn = convertColor(t[0], t[1], t[2]); | |||
@@ -136,16 +122,116 @@ public class PoiCssUtils { | |||
return colorRtn; | |||
} | |||
private static HSSFColor getHssfColor(String color) { | |||
String tmpColor = color.replace("_", "").toUpperCase(); | |||
switch (tmpColor) { | |||
case "BLACK": | |||
return HSSFColor.HSSFColorPredefined.BLACK.getColor(); | |||
case "BROWN": | |||
return HSSFColor.HSSFColorPredefined.BROWN.getColor(); | |||
case "OLIVEGREEN": | |||
return HSSFColor.HSSFColorPredefined.OLIVE_GREEN.getColor(); | |||
case "DARKGREEN": | |||
return HSSFColor.HSSFColorPredefined.DARK_GREEN.getColor(); | |||
case "DARKTEAL": | |||
return HSSFColor.HSSFColorPredefined.DARK_TEAL.getColor(); | |||
case "DARKBLUE": | |||
return HSSFColor.HSSFColorPredefined.DARK_BLUE.getColor(); | |||
case "INDIGO": | |||
return HSSFColor.HSSFColorPredefined.INDIGO.getColor(); | |||
case "GREY80PERCENT": | |||
return HSSFColor.HSSFColorPredefined.GREY_80_PERCENT.getColor(); | |||
case "ORANGE": | |||
return HSSFColor.HSSFColorPredefined.ORANGE.getColor(); | |||
case "DARKYELLOW": | |||
return HSSFColor.HSSFColorPredefined.DARK_YELLOW.getColor(); | |||
case "GREEN": | |||
return HSSFColor.HSSFColorPredefined.GREEN.getColor(); | |||
case "TEAL": | |||
return HSSFColor.HSSFColorPredefined.TEAL.getColor(); | |||
case "BLUE": | |||
return HSSFColor.HSSFColorPredefined.BLUE.getColor(); | |||
case "BLUEGREY": | |||
return HSSFColor.HSSFColorPredefined.BLUE_GREY.getColor(); | |||
case "GREY50PERCENT": | |||
return HSSFColor.HSSFColorPredefined.GREY_50_PERCENT.getColor(); | |||
case "RED": | |||
return HSSFColor.HSSFColorPredefined.RED.getColor(); | |||
case "LIGHTORANGE": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_ORANGE.getColor(); | |||
case "LIME": | |||
return HSSFColor.HSSFColorPredefined.LIME.getColor(); | |||
case "SEAGREEN": | |||
return HSSFColor.HSSFColorPredefined.SEA_GREEN.getColor(); | |||
case "AQUA": | |||
return HSSFColor.HSSFColorPredefined.AQUA.getColor(); | |||
case "LIGHTBLUE": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_BLUE.getColor(); | |||
case "VIOLET": | |||
return HSSFColor.HSSFColorPredefined.VIOLET.getColor(); | |||
case "GREY40PERCENT": | |||
return HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getColor(); | |||
case "GOLD": | |||
return HSSFColor.HSSFColorPredefined.GOLD.getColor(); | |||
case "YELLOW": | |||
return HSSFColor.HSSFColorPredefined.YELLOW.getColor(); | |||
case "BRIGHTGREEN": | |||
return HSSFColor.HSSFColorPredefined.BRIGHT_GREEN.getColor(); | |||
case "TURQUOISE": | |||
return HSSFColor.HSSFColorPredefined.TURQUOISE.getColor(); | |||
case "DARKRED": | |||
return HSSFColor.HSSFColorPredefined.DARK_RED.getColor(); | |||
case "SKYBLUE": | |||
return HSSFColor.HSSFColorPredefined.SKY_BLUE.getColor(); | |||
case "PLUM": | |||
return HSSFColor.HSSFColorPredefined.PLUM.getColor(); | |||
case "GREY25PERCENT": | |||
return HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getColor(); | |||
case "ROSE": | |||
return HSSFColor.HSSFColorPredefined.ROSE.getColor(); | |||
case "LIGHTYELLOW": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_YELLOW.getColor(); | |||
case "LIGHTGREEN": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_GREEN.getColor(); | |||
case "LIGHTTURQUOISE": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_TURQUOISE.getColor(); | |||
case "PALEBLUE": | |||
return HSSFColor.HSSFColorPredefined.PALE_BLUE.getColor(); | |||
case "LAVENDER": | |||
return HSSFColor.HSSFColorPredefined.LAVENDER.getColor(); | |||
case "WHITE": | |||
return HSSFColor.HSSFColorPredefined.WHITE.getColor(); | |||
case "CORNFLOWERBLUE": | |||
return HSSFColor.HSSFColorPredefined.CORNFLOWER_BLUE.getColor(); | |||
case "LEMONCHIFFON": | |||
return HSSFColor.HSSFColorPredefined.LEMON_CHIFFON.getColor(); | |||
case "MAROON": | |||
return HSSFColor.HSSFColorPredefined.MAROON.getColor(); | |||
case "ORCHID": | |||
return HSSFColor.HSSFColorPredefined.ORANGE.getColor(); | |||
case "CORAL": | |||
return HSSFColor.HSSFColorPredefined.CORAL.getColor(); | |||
case "ROYALBLUE": | |||
return HSSFColor.HSSFColorPredefined.ROYAL_BLUE.getColor(); | |||
case "LIGHTCORNFLOWERBLUE": | |||
return HSSFColor.HSSFColorPredefined.LIGHT_CORNFLOWER_BLUE.getColor(); | |||
case "TAN": | |||
return HSSFColor.HSSFColorPredefined.TAN.getColor(); | |||
} | |||
return null; | |||
} | |||
/** | |||
* parse color | |||
* | |||
* @param workBook work book | |||
* @param color string color | |||
* @return HSSFColor | |||
* @param color string color | |||
* @return HSSFColor | |||
*/ | |||
public static HSSFColor parseColor(HSSFWorkbook workBook, String color) { | |||
HSSFColor poiColor = null; | |||
if (StringUtils.isNotBlank(color)) { | |||
Color awtColor = Color.decode(color); | |||
Color awtColor = getAwtColor(color); | |||
if (awtColor != null) { | |||
int r = awtColor.getRed(); | |||
int g = awtColor.getGreen(); | |||
@@ -160,24 +246,41 @@ public class PoiCssUtils { | |||
return poiColor; | |||
} | |||
private static Color getAwtColor(String color) { | |||
HSSFColor hssfColor = getHssfColor(color); | |||
if (hssfColor != null) { | |||
short[] t = hssfColor.getTriplet(); | |||
return new Color(t[0], t[1], t[2]); | |||
} | |||
String tmpColor = color.replace("_", "").toLowerCase(); | |||
switch (tmpColor) { | |||
case "lightgray": | |||
return Color.LIGHT_GRAY; | |||
case "gray": | |||
return Color.GRAY; | |||
case "darkgray": | |||
return Color.DARK_GRAY; | |||
case "pink": | |||
return Color.PINK; | |||
case "magenta": | |||
return Color.MAGENTA; | |||
case "cyan": | |||
return Color.CYAN; | |||
} | |||
return Color.decode(color); | |||
} | |||
public static XSSFColor parseColor(String color) { | |||
XSSFColor poiColor = null; | |||
if (StringUtils.isNotBlank(color)) { | |||
Color awtColor = Color.decode(color); | |||
Color awtColor = getAwtColor(color); | |||
if (awtColor != null) { | |||
poiColor = new XSSFColor(awtColor,null); | |||
poiColor = new XSSFColor(awtColor, null); | |||
} | |||
} | |||
return poiColor; | |||
} | |||
// -- | |||
// private methods | |||
private static HSSFColor getColor(String color) { | |||
return colors.get(color.replace("_", "")); | |||
} | |||
private static String convertColor(int r, int g, int b) { | |||
return String.format("#%02x%02x%02x", r, g, b); | |||
} | |||