@@ -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> | ||||