| @@ -10,8 +10,14 @@ | |||||
| <arguments> | <arguments> | ||||
| </arguments> | </arguments> | ||||
| </buildCommand> | </buildCommand> | ||||
| <buildCommand> | |||||
| <name>org.eclipse.m2e.core.maven2Builder</name> | |||||
| <arguments> | |||||
| </arguments> | |||||
| </buildCommand> | |||||
| </buildSpec> | </buildSpec> | ||||
| <natures> | <natures> | ||||
| <nature>org.eclipse.m2e.core.maven2Nature</nature> | |||||
| <nature>org.springsource.ide.eclipse.gradle.core.nature</nature> | <nature>org.springsource.ide.eclipse.gradle.core.nature</nature> | ||||
| <nature>org.eclipse.jdt.core.javanature</nature> | <nature>org.eclipse.jdt.core.javanature</nature> | ||||
| </natures> | </natures> | ||||
| @@ -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 | eclipse.preferences.version=1 | ||||
| org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | 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.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 | |||||
| @@ -52,6 +52,13 @@ | |||||
| <optional>true</optional> | <optional>true</optional> | ||||
| </dependency> | </dependency> | ||||
| <!-- 处理Excel --> | |||||
| <dependency> | |||||
| <groupId>org.jsoup</groupId> | |||||
| <artifactId>jsoup</artifactId> | |||||
| <optional>true</optional> | |||||
| </dependency> | |||||
| <!-- google 工具类 --> | <!-- google 工具类 --> | ||||
| <dependency> | <dependency> | ||||
| <groupId>com.google.guava</groupId> | <groupId>com.google.guava</groupId> | ||||
| @@ -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<ICssConvertToExcel> STYLE_APPLIERS = new LinkedList<ICssConvertToExcel>(); | |||||
| { | |||||
| STYLE_APPLIERS.add(new AlignCssConvertImpl()); | |||||
| STYLE_APPLIERS.add(new BackgroundCssConvertImpl()); | |||||
| STYLE_APPLIERS.add(new BorderCssConverImpl()); | |||||
| STYLE_APPLIERS.add(new TextCssConvertImpl()); | |||||
| } | |||||
| //Cell 高宽 | |||||
| private final List<ICssConvertToExcel> SHEET_APPLIERS = new LinkedList<ICssConvertToExcel>(); | |||||
| { | |||||
| SHEET_APPLIERS.add(new WidthCssConverImpl()); | |||||
| SHEET_APPLIERS.add(new HeightCssConverImpl()); | |||||
| } | |||||
| private Sheet sheet; | |||||
| private Map<String, Object> cellsOccupied = new HashMap<String, Object>(); | |||||
| private Map<String, CellStyle> cellStyles = new HashMap<String, CellStyle>(); | |||||
| 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<String, Sheet> sheets = new HashMap<String, Sheet>(); | |||||
| Map<String, Integer> maxrowMap = new HashMap<String, Integer>(); | |||||
| 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)); | |||||
| } | |||||
| } | |||||
| @@ -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) { | |||||
| } | |||||
| } | |||||
| @@ -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<String, String> mapStyle = new HashMap<String, String>(); | |||||
| 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<String, String> 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<String, String> style) { | |||||
| Map<String, String> mapRtn = new HashMap<String, String>(); | |||||
| 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; | |||||
| } | |||||
| } | |||||
| @@ -16,6 +16,7 @@ | |||||
| package org.jeecgframework.poi.excel.html.css; | package org.jeecgframework.poi.excel.html.css; | ||||
| import org.apache.poi.ss.usermodel.Cell; | import org.apache.poi.ss.usermodel.Cell; | ||||
| import org.apache.poi.ss.usermodel.CellStyle; | |||||
| import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | 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 | * 2016年3月20日 下午4:53:04 | ||||
| */ | */ | ||||
| public interface ICssConvertToExcel { | 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); | |||||
| } | } | ||||
| @@ -16,6 +16,7 @@ | |||||
| package org.jeecgframework.poi.excel.html.css; | package org.jeecgframework.poi.excel.html.css; | ||||
| import org.apache.poi.ss.usermodel.Cell; | import org.apache.poi.ss.usermodel.Cell; | ||||
| import org.apache.poi.ss.usermodel.CellStyle; | |||||
| import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | ||||
| /** | /** | ||||
| @@ -29,6 +30,6 @@ public interface ICssConvertToHtml { | |||||
| * @param cell | * @param cell | ||||
| * | * | ||||
| */ | */ | ||||
| public void convertToHtml(Cell cell, CellStyleEntity style); | |||||
| public String convertToHtml(Cell cell, CellStyle cellStyle, CellStyleEntity style); | |||||
| } | } | ||||
| @@ -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) { | |||||
| } | |||||
| } | |||||
| @@ -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) { | |||||
| } | |||||
| } | |||||
| @@ -29,26 +29,24 @@ import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | |||||
| */ | */ | ||||
| public class BorderCssConverImpl implements ICssConvertToExcel, ICssConvertToHtml { | 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); | |||||
| } | |||||
| } | } | ||||
| @@ -15,10 +15,15 @@ | |||||
| */ | */ | ||||
| package org.jeecgframework.poi.excel.html.css.impl; | 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.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.ICssConvertToExcel; | ||||
| import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; | import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; | ||||
| import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | 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 { | 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); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -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) { | |||||
| } | |||||
| } | |||||
| @@ -15,10 +15,14 @@ | |||||
| */ | */ | ||||
| package org.jeecgframework.poi.excel.html.css.impl; | 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.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.ICssConvertToExcel; | ||||
| import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; | import org.jeecgframework.poi.excel.html.css.ICssConvertToHtml; | ||||
| import org.jeecgframework.poi.excel.html.entity.CellStyleEntity; | 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 { | 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); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -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; | private String vetical; | ||||
| public double getWidth() { | |||||
| public String getWidth() { | |||||
| return width; | return width; | ||||
| } | } | ||||
| public void setWidth(double width) { | |||||
| public void setWidth(String width) { | |||||
| this.width = width; | this.width = width; | ||||
| } | } | ||||
| public double getHeight() { | |||||
| public String getHeight() { | |||||
| return height; | return height; | ||||
| } | } | ||||
| public void setHeight(double height) { | |||||
| public void setHeight(String height) { | |||||
| this.height = height; | this.height = height; | ||||
| } | } | ||||
| @@ -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"; | |||||
| } | |||||
| @@ -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<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.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<? extends HSSFColor> 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; | |||||
| } | |||||
| } | |||||
| @@ -17,5 +17,11 @@ | |||||
| <attribute name="maven.pomderived" value="true"/> | <attribute name="maven.pomderived" value="true"/> | ||||
| </attributes> | </attributes> | ||||
| </classpathentry> | </classpathentry> | ||||
| <classpathentry kind="src" output="target/test-classes" path="src/test/java"> | |||||
| <attributes> | |||||
| <attribute name="optional" value="true"/> | |||||
| <attribute name="maven.pomderived" value="true"/> | |||||
| </attributes> | |||||
| </classpathentry> | |||||
| <classpathentry kind="output" path="target/classes"/> | <classpathentry kind="output" path="target/classes"/> | ||||
| </classpath> | </classpath> | ||||
| @@ -159,6 +159,13 @@ | |||||
| <version>1.1.0.Final</version> | <version>1.1.0.Final</version> | ||||
| </dependency> | </dependency> | ||||
| <!-- 读取Excel --> | |||||
| <dependency> | |||||
| <groupId>org.jsoup</groupId> | |||||
| <artifactId>jsoup</artifactId> | |||||
| <version>1.8.3</version> | |||||
| </dependency> | |||||
| <!-- 模块版本 --> | <!-- 模块版本 --> | ||||
| <dependency> | <dependency> | ||||
| <groupId>org.jeecg</groupId> | <groupId>org.jeecg</groupId> | ||||