From cb2ab5850895bae8b03489477c5fa14fef0b4b3d Mon Sep 17 00:00:00 2001 From: jueyue Date: Sun, 19 Mar 2017 16:05:04 +0800 Subject: [PATCH] =?UTF-8?q?HTML=20=E8=BD=ACExcel=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- easypoi-base/.project | 6 + .../.settings/org.eclipse.jdt.core.prefs | 19 +- easypoi-base/pom.xml | 7 + .../poi/excel/html/HtmlToExcelServer.java | 255 ++++++++++++++++++ .../poi/excel/html/css/CssConverImpl.java | 31 --- .../poi/excel/html/css/CssParseServer.java | 81 ++++++ .../excel/html/css/ICssConvertToExcel.java | 13 +- .../poi/excel/html/css/ICssConvertToHtml.java | 3 +- .../html/css/impl/AlignCssConvertImpl.java | 23 ++ .../css/impl/BackgroundCssConvertImpl.java | 23 ++ .../html/css/impl/BorderCssConverImpl.java | 38 ++- .../html/css/impl/HeightCssConverImpl.java | 26 +- .../html/css/impl/TextCssConvertImpl.java | 23 ++ .../html/css/impl/WidthCssConverImpl.java | 30 ++- .../excel/html/entity/CellStyleEntity.java | 12 +- .../excel/html/entity/HtmlCssConstant.java | 48 ++++ .../jeecgframework/poi/util/PoiCssUtils.java | 182 +++++++++++++ easypoi-web/.classpath | 6 + pom.xml | 7 + 19 files changed, 745 insertions(+), 88 deletions(-) create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/HtmlToExcelServer.java delete mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssConverImpl.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssParseServer.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/AlignCssConvertImpl.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BackgroundCssConvertImpl.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/TextCssConvertImpl.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/HtmlCssConstant.java create mode 100644 easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiCssUtils.java diff --git a/easypoi-base/.project b/easypoi-base/.project index 8946298..1332767 100644 --- a/easypoi-base/.project +++ b/easypoi-base/.project @@ -10,8 +10,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.springsource.ide.eclipse.gradle.core.nature org.eclipse.jdt.core.javanature diff --git a/easypoi-base/.settings/org.eclipse.jdt.core.prefs b/easypoi-base/.settings/org.eclipse.jdt.core.prefs index 897e37d..6428c68 100644 --- a/easypoi-base/.settings/org.eclipse.jdt.core.prefs +++ b/easypoi-base/.settings/org.eclipse.jdt.core.prefs @@ -1,13 +1,12 @@ -# -#Thu May 26 14:01:50 CST 2016 -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.debug.lineNumber=generate eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/easypoi-base/pom.xml b/easypoi-base/pom.xml index 5409275..b88a2a2 100644 --- a/easypoi-base/pom.xml +++ b/easypoi-base/pom.xml @@ -52,6 +52,13 @@ true + + + org.jsoup + jsoup + true + + com.google.guava diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/HtmlToExcelServer.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/HtmlToExcelServer.java new file mode 100644 index 0000000..c6901ec --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/HtmlToExcelServer.java @@ -0,0 +1,255 @@ +package org.jeecgframework.poi.excel.html; + +import java.util.Map; +import java.util.List; + +import org.jsoup.Jsoup; + +import org.slf4j.Logger; + +import java.util.HashMap; +import java.util.LinkedList; + +import org.slf4j.LoggerFactory; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import javax.management.RuntimeErrorException; + +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.CellRangeAddress; +import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerDefaultImpl; +import org.jeecgframework.poi.excel.html.css.CssParseServer; +import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; +import org.jeecgframework.poi.excel.html.css.impl.AlignCssConvertImpl; +import org.jeecgframework.poi.excel.html.css.impl.BackgroundCssConvertImpl; +import org.jeecgframework.poi.excel.html.css.impl.BorderCssConverImpl; +import org.jeecgframework.poi.excel.html.css.impl.HeightCssConverImpl; +import org.jeecgframework.poi.excel.html.css.impl.TextCssConvertImpl; +import org.jeecgframework.poi.excel.html.css.impl.WidthCssConverImpl; +import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; +import org.jeecgframework.poi.excel.html.entity.HtmlCssConstant; + +/** + * 读取Table数据生成Excel + * @author JueYue + * 2017年3月19日 + */ +public class HtmlToExcelServer { + private final Logger LOGGER = LoggerFactory + .getLogger(HtmlToExcelServer.class); + + //样式 + private final List STYLE_APPLIERS = new LinkedList(); + { + STYLE_APPLIERS.add(new AlignCssConvertImpl()); + STYLE_APPLIERS.add(new BackgroundCssConvertImpl()); + STYLE_APPLIERS.add(new BorderCssConverImpl()); + STYLE_APPLIERS.add(new TextCssConvertImpl()); + } + + //Cell 高宽 + private final List SHEET_APPLIERS = new LinkedList(); + { + SHEET_APPLIERS.add(new WidthCssConverImpl()); + SHEET_APPLIERS.add(new HeightCssConverImpl()); + } + private Sheet sheet; + private Map cellsOccupied = new HashMap(); + private Map cellStyles = new HashMap(); + private CellStyle defaultCellStyle; + private int maxRow = 0; + private CssParseServer cssParse = new CssParseServer(); + + // -- + // private methods + + private void processTable(Element table) { + int rowIndex = 0; + if (maxRow > 0) { + // blank row + maxRow += 2; + rowIndex = maxRow; + } + LOGGER.debug("Interate Table Rows."); + for (Element row : table.select("tr")) { + LOGGER.debug("Parse Table Row [{}]. Row Index [{}].", row, rowIndex); + int colIndex = 0; + LOGGER.debug("Interate Cols."); + for (Element td : row.select("td, th")) { + // skip occupied cell + while (cellsOccupied.get(rowIndex + "_" + colIndex) != null) { + LOGGER.debug("Cell [{}][{}] Has Been Occupied, Skip.", rowIndex, colIndex); + ++colIndex; + } + LOGGER.debug("Parse Col [{}], Col Index [{}].", td, colIndex); + int rowSpan = 0; + String strRowSpan = td.attr("rowspan"); + if (StringUtils.isNotBlank(strRowSpan) && StringUtils.isNumeric(strRowSpan)) { + LOGGER.debug("Found Row Span [{}].", strRowSpan); + rowSpan = Integer.parseInt(strRowSpan); + } + int colSpan = 0; + String strColSpan = td.attr("colspan"); + if (StringUtils.isNotBlank(strColSpan) && StringUtils.isNumeric(strColSpan)) { + LOGGER.debug("Found Col Span [{}].", strColSpan); + colSpan = Integer.parseInt(strColSpan); + } + // col span & row span + if (colSpan > 1 && rowSpan > 1) { + spanRowAndCol(td, rowIndex, colIndex, rowSpan, colSpan); + colIndex += colSpan; + } + // col span only + else if (colSpan > 1) { + spanCol(td, rowIndex, colIndex, colSpan); + colIndex += colSpan; + } + // row span only + else if (rowSpan > 1) { + spanRow(td, rowIndex, colIndex, rowSpan); + ++colIndex; + } + // no span + else { + createCell(td, getOrCreateRow(rowIndex), colIndex).setCellValue(td.text()); + ++colIndex; + } + } + ++rowIndex; + } + } + + public Workbook createSheet(String html, Workbook workbook) { + Elements els = Jsoup.parseBodyFragment(html).select("table"); + Map sheets = new HashMap(); + Map maxrowMap = new HashMap(); + for (Element table : els) { + String sheetName = table.attr("sheet"); + + if (StringUtils.isBlank(sheetName)) { + LOGGER.error("table必须存在name属性!"); + throw new RuntimeErrorException(null, "table必须存在name属性"); + } + + if (sheets.containsKey(sheetName)) { + maxRow = maxrowMap.get(sheetName); + //cellStyles = csStyleMap.get(sheetName); + //cellsOccupied = cellsOccupiedMap.get(sheetName); + sheet = sheets.get(sheetName); + } else { + maxRow = 0; + cellStyles.clear(); + cellsOccupied.clear(); + sheet = workbook.createSheet(sheetName); + } + //生成一个默认样式 + defaultCellStyle = new ExcelExportStylerDefaultImpl(workbook).stringNoneStyle(workbook, + false); + processTable(table); + maxrowMap.put(sheetName, maxRow); + sheets.put(sheetName, sheet); + + } + return workbook; + } + + private void spanRow(Element td, int rowIndex, int colIndex, int rowSpan) { + LOGGER.debug("Span Row , From Row [{}], Span [{}].", rowIndex, rowSpan); + mergeRegion(rowIndex, rowIndex + rowSpan - 1, colIndex, colIndex); + for (int i = 0; i < rowSpan; ++i) { + Row row = getOrCreateRow(rowIndex + i); + createCell(td, row, colIndex); + cellsOccupied.put((rowIndex + i) + "_" + colIndex, true); + } + getOrCreateRow(rowIndex).getCell(colIndex).setCellValue(td.text()); + } + + private void spanCol(Element td, int rowIndex, int colIndex, int colSpan) { + LOGGER.debug("Span Col, From Col [{}], Span [{}].", colIndex, colSpan); + mergeRegion(rowIndex, rowIndex, colIndex, colIndex + colSpan - 1); + Row row = getOrCreateRow(rowIndex); + for (int i = 0; i < colSpan; ++i) { + createCell(td, row, colIndex + i); + } + row.getCell(colIndex).setCellValue(td.text()); + } + + private void spanRowAndCol(Element td, int rowIndex, int colIndex, int rowSpan, int colSpan) { + LOGGER.debug("Span Row And Col, From Row [{}], Span [{}].", rowIndex, rowSpan); + LOGGER.debug("From Col [{}], Span [{}].", colIndex, colSpan); + mergeRegion(rowIndex, rowIndex + rowSpan - 1, colIndex, colIndex + colSpan - 1); + for (int i = 0; i < rowSpan; ++i) { + Row row = getOrCreateRow(rowIndex + i); + for (int j = 0; j < colSpan; ++j) { + createCell(td, row, colIndex + j); + cellsOccupied.put((rowIndex + i) + "_" + (colIndex + j), true); + } + } + getOrCreateRow(rowIndex).getCell(colIndex).setCellValue(td.text()); + } + + private Cell createCell(Element td, Row row, int colIndex) { + Cell cell = row.getCell(colIndex); + if (cell == null) { + LOGGER.debug("Create Cell [{}][{}].", row.getRowNum(), colIndex); + cell = row.createCell(colIndex); + } + return applyStyle(td, cell); + } + + private Cell applyStyle(Element td, Cell cell) { + String style = td.attr(HtmlCssConstant.STYLE); + CellStyle cellStyle = null; + if (StringUtils.isNotBlank(style)) { + CellStyleEntity styleEntity = cssParse.parseStyle(style.trim()); + cellStyle = cellStyles.get(styleEntity.toString()); + if (cellStyle == null) { + LOGGER.debug("No Cell Style Found In Cache, Parse New Style."); + cellStyle = cell.getRow().getSheet().getWorkbook().createCellStyle(); + cellStyle.cloneStyleFrom(defaultCellStyle); + for (ICssConvertToExcel cssConvert : STYLE_APPLIERS) { + cssConvert.convertToExcel(cell, cellStyle, styleEntity); + } + cellStyles.put(styleEntity.toString(), cellStyle); + } + for (ICssConvertToExcel cssConvert : SHEET_APPLIERS) { + cssConvert.convertToExcel(cell, cellStyle, styleEntity); + } + if (cellStyles.size() >= 4000) { + LOGGER.info( + "Custom Cell Style Exceeds 4000, Could Not Create New Style, Use Default Style."); + cellStyle = defaultCellStyle; + } + } else { + LOGGER.debug("Style is null ,Use Default Cell Style."); + cellStyle = defaultCellStyle; + } + + cell.setCellStyle(cellStyle); + return cell; + } + + private Row getOrCreateRow(int rowIndex) { + Row row = sheet.getRow(rowIndex); + if (row == null) { + LOGGER.debug("Create New Row [{}].", rowIndex); + row = sheet.createRow(rowIndex); + if (rowIndex > maxRow) { + maxRow = rowIndex; + } + } + return row; + } + + private void mergeRegion(int firstRow, int lastRow, int firstCol, int lastCol) { + LOGGER.debug("Merge Region, From Row [{}], To [{}].", firstRow, lastRow); + LOGGER.debug("From Col [{}], To [{}].", firstCol, lastCol); + sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol)); + } +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssConverImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssConverImpl.java deleted file mode 100644 index 2eaf980..0000000 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssConverImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jeecgframework.poi.excel.html.css; - -import org.apache.poi.ss.usermodel.Cell; -import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; - -public class CssConverImpl implements ICssConvertToHtml, ICssConvertToExcel { - - @Override - public void convertToExcel(Cell cell, CellStyleEntity style) { - } - - @Override - public void convertToHtml(Cell cell, CellStyleEntity entity) { - } - -} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssParseServer.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssParseServer.java new file mode 100644 index 0000000..3b0ebb8 --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/CssParseServer.java @@ -0,0 +1,81 @@ +package org.jeecgframework.poi.excel.html.css; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.jeecgframework.poi.excel.html.entity.CellStyleBorderEntity; +import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; +import org.jeecgframework.poi.excel.html.entity.HtmlCssConstant; +import org.jeecgframework.poi.util.PoiCssUtils; + +/** + * 把Css样式解析成对应的Model + * @author JueYue + * 2017年3月19日 + */ +public class CssParseServer { + + public CellStyleEntity parseStyle(String style) { + Map mapStyle = new HashMap(); + for (String s : style.split("\\s*;\\s*")) { + if (StringUtils.isNotBlank(s)) { + String[] ss = s.split("\\s*\\:\\s*"); + if (ss.length == 2 && StringUtils.isNotBlank(ss[0]) + && StringUtils.isNotBlank(ss[1])) { + String attrName = ss[0].toLowerCase(); + String attrValue = ss[1]; + // do not change font name + if (!HtmlCssConstant.FONT.equals(attrName) + && !HtmlCssConstant.FONT_FAMILY.equals(attrName)) { + attrValue = attrValue.toLowerCase(); + } + mapStyle.put(attrName, attrValue); + } + } + } + + return mapToCellStyleEntity(mapStyle); + } + + private CellStyleEntity mapToCellStyleEntity(Map mapStyle) { + CellStyleEntity entity = new CellStyleEntity(); + entity.setAlign(mapStyle.get(HtmlCssConstant.TEXT_ALIGN)); + entity.setVetical(mapStyle.get(HtmlCssConstant.VETICAL_ALIGN)); + entity.setBackground(getBackground(mapStyle)); + entity.setHeight(mapStyle.get(HtmlCssConstant.HEIGHT)); + entity.setWidth(mapStyle.get(HtmlCssConstant.WIDTH)); + // TODO 这里较为复杂,后期处理 + /*CellStyleBorderEntity border = new CellStyleBorderEntity(); + entity.setBorder(border); + border.setBorderBottom(borderBottom);*/ + return entity; + } + + private String getBackground(Map style) { + Map mapRtn = new HashMap(); + String bg = style.get(HtmlCssConstant.BACKGROUND); + String bgColor = null; + if (StringUtils.isNotBlank(bg)) { + for (String bgAttr : bg.split("(?<=\\)|\\w|%)\\s+(?=\\w)")) { + if ((bgColor = PoiCssUtils.processColor(bgAttr)) != null) { + mapRtn.put(HtmlCssConstant.BACKGROUND_COLOR, bgColor); + break; + } + } + } + bg = style.get(HtmlCssConstant.BACKGROUND_COLOR); + if (StringUtils.isNotBlank(bg) && (bgColor = PoiCssUtils.processColor(bg)) != null) { + mapRtn.put(HtmlCssConstant.BACKGROUND_COLOR, bgColor); + + } + if (bgColor != null) { + bgColor = mapRtn.get(HtmlCssConstant.BACKGROUND_COLOR); + if (!"#ffffff".equals(bgColor)) { + return mapRtn.get(HtmlCssConstant.BACKGROUND_COLOR); + } + } + return null; + } + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToExcel.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToExcel.java index b6f7b74..c231ee8 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToExcel.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToExcel.java @@ -16,6 +16,7 @@ package org.jeecgframework.poi.excel.html.css; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; /** @@ -24,11 +25,11 @@ import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; * 2016年3月20日 下午4:53:04 */ public interface ICssConvertToExcel { - /** - * 把HTML样式转换成Cell样式 - * @param cell - * @param style - */ - public void convertToExcel(Cell cell, CellStyleEntity style); + /** + * 把HTML样式转换成Cell样式 + * @param cell + * @param style + */ + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style); } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToHtml.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToHtml.java index 906b89a..1176f75 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToHtml.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/ICssConvertToHtml.java @@ -16,6 +16,7 @@ package org.jeecgframework.poi.excel.html.css; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; /** @@ -29,6 +30,6 @@ public interface ICssConvertToHtml { * @param cell * */ - public void convertToHtml(Cell cell, CellStyleEntity style); + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style); } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/AlignCssConvertImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/AlignCssConvertImpl.java new file mode 100644 index 0000000..8d6cc73 --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/AlignCssConvertImpl.java @@ -0,0 +1,23 @@ +package org.jeecgframework.poi.excel.html.css.impl; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; +import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; +import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; + +public class AlignCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml { + + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + + return null; + } + + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + } + + + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BackgroundCssConvertImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BackgroundCssConvertImpl.java new file mode 100644 index 0000000..ca35eca --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BackgroundCssConvertImpl.java @@ -0,0 +1,23 @@ +package org.jeecgframework.poi.excel.html.css.impl; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; +import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; +import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; + +public class BackgroundCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml { + + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + + return null; + } + + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + } + + + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BorderCssConverImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BorderCssConverImpl.java index 346ddd0..ff072e9 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BorderCssConverImpl.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/BorderCssConverImpl.java @@ -29,26 +29,24 @@ import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; */ public class BorderCssConverImpl implements ICssConvertToExcel, ICssConvertToHtml { - @Override - public void convertToHtml(Cell cell, CellStyleEntity style) { - } + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { - @Override - public void convertToExcel(Cell cell, CellStyleEntity style) { - CellStyle cellStyle = cell.getCellStyle(); - if (cellStyle == null) { - return; - } - CellStyleBorderEntity border = new CellStyleBorderEntity(); - border.setBorderBottom(cellStyle.getBorderBottom()); - border.setBorderBottomColor(cellStyle.getBottomBorderColor()); - border.setBorderLeft(cellStyle.getBorderLeft()); - border.setBorderLeftColor(cellStyle.getLeftBorderColor()); - border.setBorderRight(cellStyle.getBorderRight()); - border.setBorderRightColor(cellStyle.getRightBorderColor()); - border.setBorderTop(cellStyle.getBorderTop()); - border.setBorderTopColor(cellStyle.getTopBorderColor()); - style.setBorder(border); - } + return null; + } + + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + CellStyleBorderEntity border = new CellStyleBorderEntity(); + border.setBorderBottom(cellStyle.getBorderBottom()); + border.setBorderBottomColor(cellStyle.getBottomBorderColor()); + border.setBorderLeft(cellStyle.getBorderLeft()); + border.setBorderLeftColor(cellStyle.getLeftBorderColor()); + border.setBorderRight(cellStyle.getBorderRight()); + border.setBorderRightColor(cellStyle.getRightBorderColor()); + border.setBorderTop(cellStyle.getBorderTop()); + border.setBorderTopColor(cellStyle.getTopBorderColor()); + style.setBorder(border); + } } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/HeightCssConverImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/HeightCssConverImpl.java index 6465641..d905943 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/HeightCssConverImpl.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/HeightCssConverImpl.java @@ -15,10 +15,15 @@ */ package org.jeecgframework.poi.excel.html.css.impl; +import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; +import org.jeecgframework.poi.util.PoiCssUtils; + /** * 行高转换实现类 @@ -27,14 +32,21 @@ import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; */ public class HeightCssConverImpl implements ICssConvertToExcel, ICssConvertToHtml { - @Override - public void convertToHtml(Cell cell, CellStyleEntity style) { - style.setHeight(cell.getRow().getHeight()); - } + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { - @Override - public void convertToExcel(Cell cell, CellStyleEntity style) { + return null; + } - } + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + if (StringUtils.isNoneBlank(style.getHeight())) { + int height = Math.round(PoiCssUtils.getInt(style.getHeight()) * 255 / 12.75F); + Row row = cell.getRow(); + if (height > row.getHeight()) { + row.setHeight((short) height); + } + } + } } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/TextCssConvertImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/TextCssConvertImpl.java new file mode 100644 index 0000000..b3bdbd1 --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/TextCssConvertImpl.java @@ -0,0 +1,23 @@ +package org.jeecgframework.poi.excel.html.css.impl; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; +import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; +import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; + +public class TextCssConvertImpl implements ICssConvertToExcel, ICssConvertToHtml { + + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + + return null; + } + + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + } + + + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/WidthCssConverImpl.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/WidthCssConverImpl.java index 8492937..1347a8b 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/WidthCssConverImpl.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/css/impl/WidthCssConverImpl.java @@ -15,10 +15,14 @@ */ package org.jeecgframework.poi.excel.html.css.impl; +import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Sheet; import org.jeecgframework.poi.excel.html.css.ICssConvertToExcel; import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; +import org.jeecgframework.poi.util.PoiCssUtils; /** * 列宽转换实现类 @@ -27,13 +31,25 @@ import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; */ public class WidthCssConverImpl implements ICssConvertToExcel, ICssConvertToHtml { - @Override - public void convertToHtml(Cell cell, CellStyleEntity style) { - style.setWidth(cell.getRow().getSheet().getColumnWidth(cell.getColumnIndex())); - } + @Override + public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style) { - @Override - public void convertToExcel(Cell cell, CellStyleEntity style) { - } + return null; + } + + @Override + public void convertToExcel(Cell cell, CellStyle cellStyle, CellStyleEntity style) { + if (StringUtils.isNoneBlank(style.getWidth())) { + int width = (int) Math.round(PoiCssUtils.getInt(style.getWidth()) * 2048 / 8.43F); + Sheet sheet = cell.getSheet(); + int colIndex = cell.getColumnIndex(); + if (width > sheet.getColumnWidth(colIndex)) { + if (width > 255 * 256) { + width = 255 * 256; + } + sheet.setColumnWidth(colIndex, width); + } + } + } } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/CellStyleEntity.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/CellStyleEntity.java index 8874b02..d16fab8 100644 --- a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/CellStyleEntity.java +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/CellStyleEntity.java @@ -24,11 +24,11 @@ public class CellStyleEntity { /** * 宽 */ - private double width; + private String width; /** * 高 */ - private double height; + private String height; /** * 边框 */ @@ -46,19 +46,19 @@ public class CellStyleEntity { */ private String vetical; - public double getWidth() { + public String getWidth() { return width; } - public void setWidth(double width) { + public void setWidth(String width) { this.width = width; } - public double getHeight() { + public String getHeight() { return height; } - public void setHeight(double height) { + public void setHeight(String height) { this.height = height; } diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/HtmlCssConstant.java b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/HtmlCssConstant.java new file mode 100644 index 0000000..ab2c00f --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/excel/html/entity/HtmlCssConstant.java @@ -0,0 +1,48 @@ +/** + * Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jeecgframework.poi.excel.html.entity; + +public interface HtmlCssConstant { + + // constants + public final String PATTERN_LENGTH = "\\d*\\.?\\d+\\s*(?:em|ex|cm|mm|q|in|pt|pc|px)?"; + public final String STYLE = "style"; + // direction + public final String TOP = "top"; + public final String RIGHT = "right"; + public final String BOTTOM = "bottom"; + public final String LEFT = "left"; + public final String WIDTH = "width"; + public final String HEIGHT = "height"; + public final String COLOR = "color"; + public final String BORDER = "border"; + public final String CENTER = "center"; + public final String JUSTIFY = "justify"; + public final String MIDDLE = "middle"; + public final String FONT = "font"; + public final String FONT_STYLE = "font-style"; + public final String FONT_WEIGHT = "font-weight"; + public final String FONT_SIZE = "font-size"; + public final String FONT_FAMILY = "font-family"; + public final String ITALIC = "italic"; + public final String BOLD = "bold"; + public final String NORMAL = "normal"; + public final String TEXT_ALIGN = "text-align"; + public final String VETICAL_ALIGN = "vertical-align"; + public final String BACKGROUND = "background"; + public final String BACKGROUND_COLOR = "background-color"; + +} diff --git a/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiCssUtils.java b/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiCssUtils.java new file mode 100644 index 0000000..b660527 --- /dev/null +++ b/easypoi-base/src/main/java/org/jeecgframework/poi/util/PoiCssUtils.java @@ -0,0 +1,182 @@ +package org.jeecgframework.poi.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.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.HSSFPalette; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +/** + * @version 2.0.1 + * @author Shaun Chyxion + * @author JueYue + */ +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*\\))$"; + // color name -> POI Color + private static Map colors = new HashMap(); + // static init + static { + for (Map.Entry color : HSSFColor.getIndexHash().entrySet()) { + colors.put(colorName(color.getValue().getClass()), color.getValue()); + } + // light gray + HSSFColor color = colors.get(colorName(HSSFColor.GREY_25_PERCENT.class)); + colors.put("lightgray", color); + colors.put("lightgrey", color); + // silver + colors.put("silver", colors.get(colorName(HSSFColor.GREY_40_PERCENT.class))); + // darkgray + color = colors.get(colorName(HSSFColor.GREY_50_PERCENT.class)); + colors.put("darkgray", color); + colors.put("darkgrey", color); + // gray + color = colors.get(colorName(HSSFColor.GREY_80_PERCENT.class)); + colors.put("gray", color); + colors.put("grey", color); + } + + /** + * get color name + * @param color HSSFColor + * @return color name + */ + private static String colorName(Class color) { + return color.getSimpleName().replace("_", "").toLowerCase(); + } + + /** + * get int value of string + * @param strValue string value + * @return int value + */ + public static int getInt(String strValue) { + int value = 0; + if (StringUtils.isNotBlank(strValue)) { + Matcher m = Pattern.compile("^(\\d+)(?:\\w+|%)?$").matcher(strValue); + if (m.find()) { + value = Integer.parseInt(m.group(1)); + } + } + return value; + } + + /** + * check number string + * @param strValue string + * @return true if string is number + */ + public static boolean isNum(String strValue) { + return StringUtils.isNotBlank(strValue) && strValue.matches("^\\d+(\\w+|%)?$"); + } + + /** + * process color + * @param color color to process + * @return color after process + */ + public static String processColor(String color) { + log.info("Process Color [{}].", color); + String colorRtn = null; + if (StringUtils.isNotBlank(color)) { + HSSFColor poiColor = null; + // #rgb -> #rrggbb + if (color.matches(COLOR_PATTERN_VALUE_SHORT)) { + log.debug("Short Hex Color [{}] Found.", color); + StringBuffer sbColor = new StringBuffer(); + Matcher m = Pattern.compile("([a-f]|\\d)").matcher(color); + while (m.find()) { + m.appendReplacement(sbColor, "$1$1"); + } + colorRtn = sbColor.toString(); + log.debug("Translate Short Hex Color [{}] To [{}].", color, colorRtn); + } + // #rrggbb + else if (color.matches(COLOR_PATTERN_VALUE_LONG)) { + colorRtn = color; + log.debug("Hex Color [{}] Found, Return.", color); + } + // rgb(r, g, b) + else if (color.matches(COLOR_PATTERN_RGB)) { + Matcher m = Pattern.compile(COLOR_PATTERN_RGB).matcher(color); + if (m.matches()) { + log.debug("RGB Color [{}] Found.", color); + colorRtn = convertColor(calcColorValue(m.group(2)), calcColorValue(m.group(3)), + calcColorValue(m.group(4))); + log.debug("Translate RGB Color [{}] To Hex [{}].", color, colorRtn); + } + } + // color name, red, green, ... + else if ((poiColor = getColor(color)) != null) { + log.debug("Color Name [{}] Found.", color); + short[] t = poiColor.getTriplet(); + colorRtn = convertColor(t[0], t[1], t[2]); + log.debug("Translate Color Name [{}] To Hex [{}].", color, colorRtn); + } + } + return colorRtn; + } + + /** + * parse color + * @param workBook work book + * @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); + if (awtColor != null) { + int r = awtColor.getRed(); + int g = awtColor.getGreen(); + int b = awtColor.getBlue(); + HSSFPalette palette = workBook.getCustomPalette(); + poiColor = palette.findColor((byte) r, (byte) g, (byte) b); + if (poiColor == null) { + poiColor = palette.findSimilarColor(r, g, b); + } + } + } + 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); + } + + private static int calcColorValue(String color) { + int rtn = 0; + // matches 64 or 64% + Matcher m = Pattern.compile("^(\\d*\\.?\\d+)\\s*(%)?$").matcher(color); + if (m.matches()) { + // % not found + if (m.group(2) == null) { + rtn = Math.round(Float.parseFloat(m.group(1))) % 256; + } else { + rtn = Math.round(Float.parseFloat(m.group(1)) * 255 / 100) % 256; + } + } + return rtn; + } +} diff --git a/easypoi-web/.classpath b/easypoi-web/.classpath index 31d55c9..11e65e6 100644 --- a/easypoi-web/.classpath +++ b/easypoi-web/.classpath @@ -17,5 +17,11 @@ + + + + + + diff --git a/pom.xml b/pom.xml index d721b01..2433822 100644 --- a/pom.xml +++ b/pom.xml @@ -159,6 +159,13 @@ 1.1.0.Final + + + org.jsoup + jsoup + 1.8.3 + + org.jeecg