| @@ -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); | |||
| } | |||