| @@ -50,23 +50,27 @@ maven | |||||
| <dependency> | <dependency> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi-base</artifactId> | <artifactId>easypoi-base</artifactId> | ||||
| <version>2.0.9</version> | |||||
| <version>2.1.1</version> | |||||
| </dependency> | </dependency> | ||||
| <dependency> | <dependency> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi-web</artifactId> | <artifactId>easypoi-web</artifactId> | ||||
| <version>2.0.9</version> | |||||
| <version>2.1.1</version> | |||||
| </dependency> | </dependency> | ||||
| <dependency> | <dependency> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi-annotation</artifactId> | <artifactId>easypoi-annotation</artifactId> | ||||
| <version>2.0.9</version> | |||||
| <version>2.1.1</version> | |||||
| </dependency> | </dependency> | ||||
| ``` | ``` | ||||
| -------------------------- | -------------------------- | ||||
| 版本修改 | 版本修改 | ||||
| -------------------------- | -------------------------- | ||||
| - 2.1.1-release -小更新/防止下一个预览功能太久不能发布更新 | |||||
| - $fe标签 | |||||
| - 几个可能影响使用的bug | |||||
| - 导入Map的支持 | |||||
| - 2.0.9-release--模板功能更新 | - 2.0.9-release--模板功能更新 | ||||
| - 修复了中文路径,float类型导入等bug | - 修复了中文路径,float类型导入等bug | ||||
| - 增加了根据CellStyler判断cell类型的功能 | - 增加了根据CellStyler判断cell类型的功能 | ||||
| @@ -4,7 +4,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi</artifactId> | <artifactId>easypoi</artifactId> | ||||
| <version>2.1.1-SNAPSHOT</version> | |||||
| <version>2.1.2-SNAPSHOT</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>easypoi-annotation</artifactId> | <artifactId>easypoi-annotation</artifactId> | ||||
| <description>基础注解类,解耦合</description> | <description>基础注解类,解耦合</description> | ||||
| @@ -4,7 +4,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi</artifactId> | <artifactId>easypoi</artifactId> | ||||
| <version>2.1.1-SNAPSHOT</version> | |||||
| <version>2.1.2-SNAPSHOT</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>easypoi-base</artifactId> | <artifactId>easypoi-base</artifactId> | ||||
| <dependencies> | <dependencies> | ||||
| @@ -0,0 +1,55 @@ | |||||
| package org.jeecgframework.poi.excel; | |||||
| import org.apache.poi.ss.usermodel.Workbook; | |||||
| import org.jeecgframework.poi.excel.html.ExcelToHtmlServer; | |||||
| /** | |||||
| * Excel 变成界面 | |||||
| * @author JueYue | |||||
| * @date 2015年5月10日 上午11:51:48 | |||||
| */ | |||||
| public final class ExcelToHtmlUtil { | |||||
| private ExcelToHtmlUtil() { | |||||
| } | |||||
| /** | |||||
| * 转换成为Table | |||||
| * @param wb Excel | |||||
| * @return | |||||
| */ | |||||
| public static String toTableHtml(Workbook wb) { | |||||
| return new ExcelToHtmlServer(wb, false, 0).printPage(); | |||||
| } | |||||
| /** | |||||
| * 转换成为Table | |||||
| * @param wb Excel | |||||
| * @param sheetNum sheetNum | |||||
| * @return | |||||
| */ | |||||
| public static String toTableHtml(Workbook wb, int sheetNum) { | |||||
| return new ExcelToHtmlServer(wb, false, sheetNum).printPage(); | |||||
| } | |||||
| /** | |||||
| * 转换成为完整界面 | |||||
| * @param wb Excel | |||||
| * @param sheetNum sheetNum | |||||
| * @return | |||||
| */ | |||||
| public static String toAllHtml(Workbook wb) { | |||||
| return new ExcelToHtmlServer(wb, true, 0).printPage(); | |||||
| } | |||||
| /** | |||||
| * 转换成为完整界面 | |||||
| * @param wb Excel | |||||
| * @param sheetNum sheetNum | |||||
| * @return | |||||
| */ | |||||
| public static String toAllHtml(Workbook wb, int sheetNum) { | |||||
| return new ExcelToHtmlServer(wb, true, sheetNum).printPage(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,180 @@ | |||||
| package org.jeecgframework.poi.excel.html; | |||||
| import java.util.Formatter; | |||||
| import java.util.Iterator; | |||||
| import org.apache.poi.ss.usermodel.Cell; | |||||
| import org.apache.poi.ss.usermodel.CellStyle; | |||||
| import org.apache.poi.ss.usermodel.Row; | |||||
| import org.apache.poi.ss.usermodel.Sheet; | |||||
| import org.apache.poi.ss.usermodel.Workbook; | |||||
| import org.jeecgframework.poi.excel.html.helper.CellValueHelper; | |||||
| import org.jeecgframework.poi.excel.html.helper.MergedRegionHelper; | |||||
| import org.jeecgframework.poi.excel.html.helper.StylerHelper; | |||||
| /** | |||||
| * Excel转换成Html 服务 | |||||
| * @author JueYue | |||||
| * @date 2015年5月10日 上午11:41:15 | |||||
| */ | |||||
| public class ExcelToHtmlServer { | |||||
| private Workbook wb; | |||||
| private int sheetNum; | |||||
| private int cssRandom; | |||||
| /*是不是完成界面*/ | |||||
| private boolean completeHTML; | |||||
| private Formatter out; | |||||
| /*已经完成范围处理*/ | |||||
| private boolean gotBounds; | |||||
| private int firstColumn; | |||||
| private int endColumn; | |||||
| private static final String COL_HEAD_CLASS = "colHeader"; | |||||
| private static final String ROW_HEAD_CLASS = "rowHeader"; | |||||
| private static final String DEFAULTS_CLASS = "excelDefaults"; | |||||
| public ExcelToHtmlServer(Workbook wb, boolean completeHTML, int sheetNum) { | |||||
| this.wb = wb; | |||||
| this.completeHTML = completeHTML; | |||||
| this.sheetNum = sheetNum; | |||||
| cssRandom = (int) Math.ceil(Math.random() * 1000); | |||||
| } | |||||
| public String printPage() { | |||||
| try { | |||||
| ensureOut(); | |||||
| if (completeHTML) { | |||||
| out.format("<!DOCTYPE HTML>%n"); | |||||
| out.format("<html>%n"); | |||||
| out.format("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">%n"); | |||||
| out.format("<head>%n"); | |||||
| } | |||||
| new StylerHelper(wb, out, sheetNum, cssRandom); | |||||
| if (completeHTML) { | |||||
| out.format("</head>%n"); | |||||
| out.format("<body>%n"); | |||||
| } | |||||
| print(); | |||||
| if (completeHTML) { | |||||
| out.format("</body>%n"); | |||||
| out.format("</html>%n"); | |||||
| } | |||||
| return out.toString(); | |||||
| } finally { | |||||
| if (out != null) | |||||
| out.close(); | |||||
| } | |||||
| } | |||||
| private void print() { | |||||
| printSheets(); | |||||
| } | |||||
| private void ensureOut() { | |||||
| if (out == null) | |||||
| out = new Formatter(new StringBuilder()); | |||||
| } | |||||
| private void printSheets() { | |||||
| Sheet sheet = wb.getSheetAt(sheetNum); | |||||
| printSheet(sheet); | |||||
| } | |||||
| private void printSheet(Sheet sheet) { | |||||
| out.format("<table style='word-break:break-all' class=%s>%n", DEFAULTS_CLASS); | |||||
| printCols(sheet); | |||||
| printSheetContent(sheet); | |||||
| out.format("</table>%n"); | |||||
| } | |||||
| private void printCols(Sheet sheet) { | |||||
| out.format("<col/>%n"); | |||||
| ensureColumnBounds(sheet); | |||||
| for (int i = firstColumn; i < endColumn; i++) { | |||||
| out.format("<col style='width:%spx;' />%n", sheet.getColumnWidth(i) / 32); | |||||
| } | |||||
| } | |||||
| private void ensureColumnBounds(Sheet sheet) { | |||||
| if (gotBounds) | |||||
| return; | |||||
| Iterator<Row> iter = sheet.rowIterator(); | |||||
| firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0); | |||||
| endColumn = 0; | |||||
| while (iter.hasNext()) { | |||||
| Row row = iter.next(); | |||||
| short firstCell = row.getFirstCellNum(); | |||||
| if (firstCell >= 0) { | |||||
| firstColumn = Math.min(firstColumn, firstCell); | |||||
| endColumn = Math.max(endColumn, row.getLastCellNum()); | |||||
| } | |||||
| } | |||||
| gotBounds = true; | |||||
| } | |||||
| private void printColumnHeads(Sheet sheet) { | |||||
| out.format("<thead>%n"); | |||||
| out.format(" <tr class=%s>%n", COL_HEAD_CLASS); | |||||
| out.format(" <th class=%s>◊</th>%n", COL_HEAD_CLASS); | |||||
| StringBuilder colName = new StringBuilder(); | |||||
| for (int i = firstColumn; i < endColumn; i++) { | |||||
| colName.setLength(0); | |||||
| int cnum = i; | |||||
| do { | |||||
| colName.insert(0, (char) ('A' + cnum % 26)); | |||||
| cnum /= 26; | |||||
| } while (cnum > 0); | |||||
| out.format(" <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName); | |||||
| } | |||||
| out.format(" </tr>%n"); | |||||
| out.format("</thead>%n"); | |||||
| } | |||||
| private void printSheetContent(Sheet sheet) { | |||||
| printColumnHeads(sheet); | |||||
| MergedRegionHelper mergedRegionHelper = new MergedRegionHelper(sheet); | |||||
| CellValueHelper cellValueHelper = new CellValueHelper(wb, cssRandom); | |||||
| out.format("<tbody>%n"); | |||||
| Iterator<Row> rows = sheet.rowIterator(); | |||||
| int rowIndex = 1; | |||||
| while (rows.hasNext()) { | |||||
| Row row = rows.next(); | |||||
| out.format(" <tr style='height:%spx;'>%n", row.getHeight() / 15); | |||||
| out.format(" <td class='%s'>%d</td>%n", ROW_HEAD_CLASS, row.getRowNum() + 1); | |||||
| for (int i = firstColumn; i < endColumn; i++) { | |||||
| if (mergedRegionHelper.isNeedCreate(rowIndex, i)) { | |||||
| String content = " "; | |||||
| CellStyle style = null; | |||||
| if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) { | |||||
| Cell cell = row.getCell(i); | |||||
| if (cell != null) { | |||||
| style = cell.getCellStyle(); | |||||
| content = cellValueHelper.getHtmlValue(cell); | |||||
| } | |||||
| } | |||||
| if (mergedRegionHelper.isMergedRegion(rowIndex, i)) { | |||||
| Integer[] rowAndColSpan = mergedRegionHelper.getRowAndColSpan(rowIndex, i); | |||||
| out.format(" <td rowspan='%s' colspan='%s' class='%s' >%s</td>%n", | |||||
| rowAndColSpan[0], rowAndColSpan[1], styleName(style), content); | |||||
| } else { | |||||
| out.format(" <td class='%s'>%s</td>%n", styleName(style), content); | |||||
| } | |||||
| } | |||||
| } | |||||
| out.format(" </tr>%n"); | |||||
| rowIndex++; | |||||
| } | |||||
| out.format("</tbody>%n"); | |||||
| } | |||||
| private String styleName(CellStyle style) { | |||||
| if (style == null) | |||||
| return ""; | |||||
| return String.format("style_%02x_%s font_%s_%s", style.getIndex(), cssRandom, | |||||
| style.getFontIndex(), cssRandom); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,140 @@ | |||||
| package org.jeecgframework.poi.excel.html.helper; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import org.apache.poi.hssf.usermodel.HSSFRichTextString; | |||||
| import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||||
| import org.apache.poi.ss.usermodel.Cell; | |||||
| import org.apache.poi.ss.usermodel.Font; | |||||
| import org.apache.poi.ss.usermodel.Workbook; | |||||
| import org.apache.poi.xssf.usermodel.XSSFFont; | |||||
| import org.apache.poi.xssf.usermodel.XSSFRichTextString; | |||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||||
| import com.google.common.xml.XmlEscapers; | |||||
| /** | |||||
| * Cell值帮助类 | |||||
| * @author JueYue | |||||
| * @date 2015年5月9日 下午10:31:32 | |||||
| */ | |||||
| public class CellValueHelper { | |||||
| /** | |||||
| * Excel 格式 | |||||
| */ | |||||
| private boolean is07; | |||||
| private int cssRandom; | |||||
| private Map<String, String> fontCache = new HashMap<String, String>(); | |||||
| public CellValueHelper(Workbook wb, int cssRandom) { | |||||
| this.cssRandom = cssRandom; | |||||
| if (wb instanceof HSSFWorkbook) | |||||
| is07 = false; | |||||
| else if (wb instanceof XSSFWorkbook) { | |||||
| is07 = true; | |||||
| cacheFontInfo(wb); | |||||
| } else | |||||
| throw new IllegalArgumentException("unknown workbook type: " | |||||
| + wb.getClass().getSimpleName()); | |||||
| } | |||||
| /** | |||||
| * O7 版本坑爹bug | |||||
| * @param wb | |||||
| */ | |||||
| private void cacheFontInfo(Workbook wb) { | |||||
| for (short i = 0, le = wb.getNumberOfFonts(); i < le; i++) { | |||||
| Font font = wb.getFontAt(i); | |||||
| fontCache.put(font.getBoldweight() + "_" + font.getItalic() + "_" + font.getFontName() | |||||
| + "_" + font.getFontHeightInPoints() + "_" + font.getColor(), | |||||
| font.getIndex() + ""); | |||||
| } | |||||
| } | |||||
| public String getHtmlValue(Cell cell) { | |||||
| if (Cell.CELL_TYPE_BOOLEAN == cell.getCellType() | |||||
| || Cell.CELL_TYPE_NUMERIC == cell.getCellType()) { | |||||
| cell.setCellType(Cell.CELL_TYPE_STRING); | |||||
| return cell.getStringCellValue(); | |||||
| } else if (Cell.CELL_TYPE_STRING == cell.getCellType()) { | |||||
| if (cell.getRichStringCellValue().numFormattingRuns() == 0) { | |||||
| return XmlEscapers.xmlContentEscaper().escape(cell.getStringCellValue()); | |||||
| } else if (is07) { | |||||
| return getXSSFRichString((XSSFRichTextString) cell.getRichStringCellValue()); | |||||
| } else { | |||||
| return getHSSFRichString((HSSFRichTextString) cell.getRichStringCellValue()); | |||||
| } | |||||
| } | |||||
| return ""; | |||||
| } | |||||
| /** | |||||
| * 03版本复杂数据 | |||||
| * @param rich | |||||
| * @return | |||||
| */ | |||||
| private String getHSSFRichString(HSSFRichTextString rich) { | |||||
| int nums = rich.numFormattingRuns(); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| String text = rich.toString(); | |||||
| int currentIndex = 0; | |||||
| sb.append(text.substring(0, rich.getIndexOfFormattingRun(0))); | |||||
| for (int i = 0; i < nums; i++) { | |||||
| sb.append("<span "); | |||||
| sb.append("class='font_" + rich.getFontOfFormattingRun(i)); | |||||
| sb.append("_"); | |||||
| sb.append(cssRandom); | |||||
| sb.append("'>"); | |||||
| currentIndex = rich.getIndexOfFormattingRun(i); | |||||
| if (i < nums - 1) { | |||||
| sb.append(XmlEscapers.xmlContentEscaper().escape( | |||||
| text.substring(currentIndex, rich.getIndexOfFormattingRun(i + 1)))); | |||||
| } else { | |||||
| sb.append(XmlEscapers.xmlContentEscaper().escape( | |||||
| text.substring(currentIndex, text.length()))); | |||||
| } | |||||
| sb.append("</span>"); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * 07版本复杂数据 | |||||
| * @param rich | |||||
| * @return | |||||
| */ | |||||
| private String getXSSFRichString(XSSFRichTextString rich) { | |||||
| int nums = rich.numFormattingRuns(); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| String text = rich.toString(); | |||||
| int currentIndex = 0, lastIndex = 0; | |||||
| for (int i = 1; i <= nums; i++) { | |||||
| sb.append("<span "); | |||||
| try { | |||||
| sb.append("class='font_" + getFontIndex(rich.getFontOfFormattingRun(i - 1))); | |||||
| sb.append("_"); | |||||
| sb.append(cssRandom); | |||||
| sb.append("'"); | |||||
| } catch (Exception e) { | |||||
| } | |||||
| sb.append(">"); | |||||
| currentIndex = rich.getIndexOfFormattingRun(i) == -1 ? text.length() : rich | |||||
| .getIndexOfFormattingRun(i); | |||||
| sb.append(XmlEscapers.xmlContentEscaper().escape( | |||||
| text.substring(lastIndex, currentIndex))); | |||||
| sb.append("</span>"); | |||||
| lastIndex = currentIndex; | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| private String getFontIndex(XSSFFont font) { | |||||
| return fontCache.get(font.getBoldweight() + "_" + font.getItalic() + "_" | |||||
| + font.getFontName() + "_" + font.getFontHeightInPoints() + "_" | |||||
| + font.getColor()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,81 @@ | |||||
| package org.jeecgframework.poi.excel.html.helper; | |||||
| import java.util.HashMap; | |||||
| import java.util.HashSet; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| import org.apache.poi.ss.usermodel.Sheet; | |||||
| /** | |||||
| * 合并单元格帮助类 | |||||
| * @author JueYue | |||||
| * @date 2015年5月9日 下午2:13:35 | |||||
| */ | |||||
| public class MergedRegionHelper { | |||||
| private Map<String, Integer[]> mergedCache = new HashMap<String, Integer[]>(); | |||||
| private Set<String> notNeedCread = new HashSet<String>(); | |||||
| public MergedRegionHelper(Sheet sheet) { | |||||
| getAllMergedRegion(sheet); | |||||
| } | |||||
| private void getAllMergedRegion(Sheet sheet) { | |||||
| int nums = sheet.getNumMergedRegions(); | |||||
| for (int i = 0; i < nums; i++) { | |||||
| handerMergedString(sheet.getMergedRegion(i).formatAsString()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 根据合并输出内容,处理合并单元格事情 | |||||
| * @param formatAsString | |||||
| */ | |||||
| private void handerMergedString(String formatAsString) { | |||||
| String[] strArr = formatAsString.split(":"); | |||||
| int startCol = strArr[0].charAt(0) - 65; | |||||
| int startRol = Integer.valueOf(strArr[0].substring(1)); | |||||
| int endCol = strArr[1].charAt(0) - 65; | |||||
| int endRol = Integer.valueOf(strArr[1].substring(1)); | |||||
| mergedCache.put(startRol + "_" + startCol, new Integer[] { endRol - startRol + 1, | |||||
| endCol - startCol + 1 }); | |||||
| for (int i = startRol; i <= endRol; i++) { | |||||
| for (int j = startCol; j <= endCol; j++) { | |||||
| notNeedCread.add(i + "_" + j); | |||||
| } | |||||
| } | |||||
| notNeedCread.remove(startRol + "_" + startCol); | |||||
| } | |||||
| /** | |||||
| * 是不是需要创建这个TD | |||||
| * @param row | |||||
| * @param col | |||||
| * @return | |||||
| */ | |||||
| public boolean isNeedCreate(int row, int col) { | |||||
| return !notNeedCread.contains(row + "_" + col); | |||||
| } | |||||
| /** | |||||
| * 是不是合并区域 | |||||
| * @param row | |||||
| * @param col | |||||
| * @return | |||||
| */ | |||||
| public boolean isMergedRegion(int row, int col) { | |||||
| return mergedCache.containsKey(row + "_" + col); | |||||
| } | |||||
| /** | |||||
| * 获取合并区域 | |||||
| * @param row | |||||
| * @param col | |||||
| * @return | |||||
| */ | |||||
| public Integer[] getRowAndColSpan(int row, int col) { | |||||
| return mergedCache.get(row + "_" + col); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,278 @@ | |||||
| package org.jeecgframework.poi.excel.html.helper; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_CENTER; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_CENTER_SELECTION; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_FILL; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_JUSTIFY; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_LEFT; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.ALIGN_RIGHT; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.VERTICAL_BOTTOM; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.VERTICAL_CENTER; | |||||
| import static org.apache.poi.ss.usermodel.CellStyle.VERTICAL_TOP; | |||||
| import java.io.BufferedReader; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStreamReader; | |||||
| import java.util.Formatter; | |||||
| import java.util.HashSet; | |||||
| import java.util.Iterator; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| import org.apache.poi.hssf.usermodel.HSSFCellStyle; | |||||
| import org.apache.poi.hssf.usermodel.HSSFPalette; | |||||
| import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||||
| import org.apache.poi.hssf.util.HSSFColor; | |||||
| import org.apache.poi.ss.usermodel.Cell; | |||||
| import org.apache.poi.ss.usermodel.CellStyle; | |||||
| import org.apache.poi.ss.usermodel.Color; | |||||
| import org.apache.poi.ss.usermodel.Font; | |||||
| import org.apache.poi.ss.usermodel.Row; | |||||
| import org.apache.poi.ss.usermodel.Sheet; | |||||
| import org.apache.poi.ss.usermodel.Workbook; | |||||
| import org.apache.poi.xssf.usermodel.XSSFCellStyle; | |||||
| import org.apache.poi.xssf.usermodel.XSSFColor; | |||||
| import org.apache.poi.xssf.usermodel.XSSFFont; | |||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||||
| import org.jeecgframework.poi.util.PoiPublicUtil; | |||||
| /** | |||||
| * 样式帮助类 | |||||
| * @author JueYue | |||||
| * @date 2015年5月9日 下午4:04:24 | |||||
| */ | |||||
| public class StylerHelper { | |||||
| private static String DEFAULTS_CLASS_CSS; | |||||
| private static final String DEFAULTS_CLASS = "excelDefaults"; | |||||
| private static final Map<Short, String> ALIGN = PoiPublicUtil.mapFor(ALIGN_LEFT, | |||||
| "left", ALIGN_CENTER, "center", | |||||
| ALIGN_RIGHT, "right", ALIGN_FILL, | |||||
| "left", ALIGN_JUSTIFY, "left", | |||||
| ALIGN_CENTER_SELECTION, "center"); | |||||
| private static final Map<Short, String> VERTICAL_ALIGN = PoiPublicUtil.mapFor(VERTICAL_BOTTOM, | |||||
| "bottom", VERTICAL_CENTER, "middle", | |||||
| VERTICAL_TOP, "top"); | |||||
| private Formatter out; | |||||
| private Sheet sheet; | |||||
| private HtmlHelper helper; | |||||
| private int sheetNum; | |||||
| private int cssRandom; | |||||
| public StylerHelper(Workbook wb, Formatter out, int sheetNum, int cssRandom) { | |||||
| this.out = out; | |||||
| this.sheetNum = sheetNum; | |||||
| this.cssRandom = cssRandom; | |||||
| if (wb instanceof HSSFWorkbook) | |||||
| helper = new HSSFHtmlHelper((HSSFWorkbook) wb); | |||||
| else if (wb instanceof XSSFWorkbook) | |||||
| helper = new XSSFHtmlHelper((XSSFWorkbook) wb); | |||||
| else | |||||
| throw new IllegalArgumentException("unknown workbook type: " | |||||
| + wb.getClass().getSimpleName()); | |||||
| printInlineStyle(wb); | |||||
| } | |||||
| private void printInlineStyle(Workbook wb) { | |||||
| out.format("<style type=\"text/css\">%n"); | |||||
| printStyles(wb); | |||||
| prontFonts(wb); | |||||
| out.format("</style>%n"); | |||||
| } | |||||
| private void prontFonts(Workbook wb) { | |||||
| for (short i = 0, le = wb.getNumberOfFonts(); i < le; i++) { | |||||
| Font font = wb.getFontAt(i); | |||||
| out.format(".%s .%s {%n", DEFAULTS_CLASS, "font_" + i + "_" + cssRandom); | |||||
| fontStyle(font); | |||||
| out.format("}%n"); | |||||
| } | |||||
| } | |||||
| public void printStyles(Workbook wb) { | |||||
| if (DEFAULTS_CLASS_CSS == null) { | |||||
| DEFAULTS_CLASS_CSS = getDefaultsClassCss(); | |||||
| } | |||||
| out.format(DEFAULTS_CLASS_CSS); | |||||
| Set<CellStyle> seen = new HashSet<CellStyle>(); | |||||
| sheet = wb.getSheetAt(sheetNum); | |||||
| Iterator<Row> rows = sheet.rowIterator(); | |||||
| while (rows.hasNext()) { | |||||
| Row row = rows.next(); | |||||
| for (Cell cell : row) { | |||||
| CellStyle style = cell.getCellStyle(); | |||||
| if (!seen.contains(style)) { | |||||
| printStyle(style); | |||||
| seen.add(style); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @SuppressWarnings("resource") | |||||
| private String getDefaultsClassCss() { | |||||
| BufferedReader in = null; | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| Formatter formatter = new Formatter(sb); | |||||
| try { | |||||
| in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream( | |||||
| "excelStyle.css"))); | |||||
| String line; | |||||
| while ((line = in.readLine()) != null) { | |||||
| formatter.format("%s%n", line); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| throw new IllegalStateException("Reading standard css", e); | |||||
| } finally { | |||||
| if (in != null) { | |||||
| try { | |||||
| in.close(); | |||||
| } catch (IOException e) { | |||||
| throw new IllegalStateException("Reading standard css", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| return formatter.toString(); | |||||
| } | |||||
| private void printStyle(CellStyle style) { | |||||
| out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style)); | |||||
| styleContents(style); | |||||
| out.format("}%n"); | |||||
| } | |||||
| private void styleContents(CellStyle style) { | |||||
| if (style.getAlignment() != 2) { | |||||
| styleOut("text-align", style.getAlignment(), ALIGN); | |||||
| styleOut("vertical-align", style.getAlignment(), VERTICAL_ALIGN); | |||||
| } | |||||
| helper.colorStyles(style, out); | |||||
| } | |||||
| private void fontStyle(Font font) { | |||||
| if (font.getBoldweight() >= Font.BOLDWEIGHT_BOLD) | |||||
| out.format(" font-weight: bold;%n"); | |||||
| if (font.getItalic()) | |||||
| out.format(" font-style: italic;%n"); | |||||
| out.format(" font-family: %s;%n", font.getFontName()); | |||||
| int fontheight = font.getFontHeightInPoints(); | |||||
| if (fontheight == 9) { | |||||
| fontheight = 10; | |||||
| } | |||||
| out.format(" font-size: %dpt;%n", fontheight); | |||||
| helper.styleColor(out, "color", getColor(font)); | |||||
| } | |||||
| private Color getColor(Font font) { | |||||
| if (helper instanceof HSSFHtmlHelper) { | |||||
| return ((HSSFWorkbook) sheet.getWorkbook()).getCustomPalette() | |||||
| .getColor(font.getColor()); | |||||
| } else { | |||||
| return ((XSSFFont) font).getXSSFColor(); | |||||
| } | |||||
| } | |||||
| private String styleName(CellStyle style) { | |||||
| if (style == null) | |||||
| return ""; | |||||
| return String.format("style_%02x_%s", style.getIndex(), cssRandom); | |||||
| } | |||||
| private <K> void styleOut(String attr, K key, Map<K, String> mapping) { | |||||
| String value = mapping.get(key); | |||||
| if (value != null) { | |||||
| out.format(" %s: %s;%n", attr, value); | |||||
| } | |||||
| } | |||||
| private interface HtmlHelper { | |||||
| /** | |||||
| * Outputs the appropriate CSS style for the given cell style. | |||||
| * | |||||
| * @param style The cell style. | |||||
| * @param out The place to write the output. | |||||
| */ | |||||
| void colorStyles(CellStyle style, Formatter out); | |||||
| void styleColor(Formatter out, String attr, Color color); | |||||
| } | |||||
| private class HSSFHtmlHelper implements HtmlHelper { | |||||
| private final HSSFWorkbook wb; | |||||
| private final HSSFPalette colors; | |||||
| private HSSFColor HSSF_AUTO = new HSSFColor.AUTOMATIC(); | |||||
| public HSSFHtmlHelper(HSSFWorkbook wb) { | |||||
| this.wb = wb; | |||||
| colors = wb.getCustomPalette(); | |||||
| } | |||||
| public void colorStyles(CellStyle style, Formatter out) { | |||||
| HSSFCellStyle cs = (HSSFCellStyle) style; | |||||
| out.format(" /* fill pattern = %d */%n", cs.getFillPattern()); | |||||
| styleColor(out, "background-color", cs.getFillForegroundColor()); | |||||
| styleColor(out, "color", colors.getColor(cs.getFont(wb).getColor())); | |||||
| } | |||||
| private void styleColor(Formatter out, String attr, short index) { | |||||
| HSSFColor color = colors.getColor(index); | |||||
| if (index == HSSF_AUTO.getIndex() || color == null) { | |||||
| out.format(" /* %s: index = %d */%n", attr, index); | |||||
| } else { | |||||
| short[] rgb = color.getTriplet(); | |||||
| out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0], rgb[1], rgb[2], | |||||
| index); | |||||
| } | |||||
| } | |||||
| public void styleColor(Formatter out, String attr, Color color) { | |||||
| if (color == null) { | |||||
| return; | |||||
| } | |||||
| HSSFColor hSSFColor = (HSSFColor) color; | |||||
| short[] rgb = hSSFColor.getTriplet(); | |||||
| out.format(" %s: #%02x%02x%02x; %n", attr, rgb[0], rgb[1], rgb[2]); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Implementation of {@link HtmlHelper} for XSSF files. | |||||
| * | |||||
| * @author Ken Arnold, Industrious Media LLC | |||||
| */ | |||||
| private class XSSFHtmlHelper implements HtmlHelper { | |||||
| public XSSFHtmlHelper(XSSFWorkbook wb) { | |||||
| } | |||||
| public void colorStyles(CellStyle style, Formatter out) { | |||||
| XSSFCellStyle cs = (XSSFCellStyle) style; | |||||
| styleColor(out, "background-color", cs.getFillForegroundXSSFColor()); | |||||
| styleColor(out, "color", cs.getFont().getXSSFColor()); | |||||
| } | |||||
| public void styleColor(Formatter out, String attr, Color color) { | |||||
| XSSFColor xSSFColor = (XSSFColor) color; | |||||
| if (color == null || xSSFColor.isAuto()) | |||||
| return; | |||||
| byte[] rgb = xSSFColor.getRgb(); | |||||
| if (rgb == null) { | |||||
| return; | |||||
| } | |||||
| out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| .excelDefaults { | |||||
| background-color: white; | |||||
| color: black; | |||||
| text-decoration: none; | |||||
| direction: ltr; | |||||
| text-transform: none; | |||||
| text-indent: 0; | |||||
| letter-spacing: 0; | |||||
| word-spacing: 0; | |||||
| white-space: normal; | |||||
| unicode-bidi: normal; | |||||
| vertical-align: 0; | |||||
| text-shadow: none; | |||||
| padding: 0; | |||||
| margin: 0; | |||||
| border-collapse: collapse; | |||||
| white-space: pre-wrap; | |||||
| word-wrap: break-word; | |||||
| word-break: break-all; | |||||
| } | |||||
| .excelDefaults td { | |||||
| padding: 1px 5px; | |||||
| border: 1px solid silver; | |||||
| border-color: #000000; | |||||
| text-align: center; | |||||
| vertical-align: middle; | |||||
| font-size: 12pt; | |||||
| } | |||||
| .excelDefaults .colHeader { | |||||
| background-color: silver; | |||||
| font-weight: bold; | |||||
| border: 1px solid black; | |||||
| text-align: center; | |||||
| padding: 1px 5px; | |||||
| } | |||||
| .excelDefaults .rowHeader { | |||||
| background-color: silver; | |||||
| font-weight: bold; | |||||
| border: 1px solid black; | |||||
| text-align: right; | |||||
| padding: 1px 5px; | |||||
| } | |||||
| @@ -68,6 +68,15 @@ public final class PoiPublicUtil { | |||||
| } | } | ||||
| @SuppressWarnings({ "unchecked" }) | |||||
| public static <K, V> Map<K, V> mapFor(Object... mapping) { | |||||
| Map<K, V> map = new HashMap<K, V>(); | |||||
| for (int i = 0; i < mapping.length; i += 2) { | |||||
| map.put((K) mapping[i], (V) mapping[i + 1]); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | /** | ||||
| * 彻底创建一个对象 | * 彻底创建一个对象 | ||||
| * | * | ||||
| @@ -4,7 +4,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi</artifactId> | <artifactId>easypoi</artifactId> | ||||
| <version>2.1.1-SNAPSHOT</version> | |||||
| <version>2.1.2-SNAPSHOT</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>easypoi-test</artifactId> | <artifactId>easypoi-test</artifactId> | ||||
| <dependencies> | <dependencies> | ||||
| @@ -4,7 +4,7 @@ | |||||
| <parent> | <parent> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi</artifactId> | <artifactId>easypoi</artifactId> | ||||
| <version>2.1.1-SNAPSHOT</version> | |||||
| <version>2.1.2-SNAPSHOT</version> | |||||
| </parent> | </parent> | ||||
| <artifactId>easypoi-web</artifactId> | <artifactId>easypoi-web</artifactId> | ||||
| <dependencies> | <dependencies> | ||||
| @@ -0,0 +1,54 @@ | |||||
| package org.jeecgframework.poi.excel.html.convert; | |||||
| import java.util.Iterator; | |||||
| import org.apache.poi.ss.usermodel.Cell; | |||||
| import org.apache.poi.ss.usermodel.Row; | |||||
| import org.apache.poi.ss.usermodel.Sheet; | |||||
| import org.apache.poi.ss.usermodel.Workbook; | |||||
| /** | |||||
| * Excel 转换成为Html | |||||
| * @author JueYue | |||||
| * @date 2015年5月7日 下午10:06:51 | |||||
| */ | |||||
| public final class ExcelConverHtmlUtil { | |||||
| private static final String STARTHTML = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"><html><head>"; | |||||
| private static final String HTML_TR_S = "<tr>"; | |||||
| private static final String HTML_TR_E = "</tr>"; | |||||
| private static final String HTML_TD_S = "<td>"; | |||||
| private static final String HTML_TD_E = "</td>"; | |||||
| private ExcelConverHtmlUtil() { | |||||
| } | |||||
| public String convert(Workbook workbook, int... sheets) { | |||||
| StringBuilder html = new StringBuilder(STARTHTML); | |||||
| StringBuilder css = new StringBuilder(); | |||||
| StringBuilder body = new StringBuilder(); | |||||
| sheetConverToHtml(workbook.getSheetAt(sheets[0]), css, body); | |||||
| html.append(css); | |||||
| html.append(body); | |||||
| return html.toString(); | |||||
| } | |||||
| private void sheetConverToHtml(Sheet sheet, StringBuilder css, StringBuilder body) { | |||||
| Iterator<Row> rows = sheet.rowIterator(); | |||||
| Iterator<Cell> cells = null; | |||||
| while (rows.hasNext()) { | |||||
| Row row = rows.next(); | |||||
| cells = row.cellIterator(); | |||||
| body.append(HTML_TR_S); | |||||
| while (cells.hasNext()) { | |||||
| Cell cell = cells.next(); | |||||
| body.append(HTML_TD_S); | |||||
| body.append(cell.toString()); | |||||
| body.append(HTML_TD_E); | |||||
| } | |||||
| body.append(HTML_TR_E); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -3,7 +3,7 @@ | |||||
| <modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
| <groupId>org.jeecgframework</groupId> | <groupId>org.jeecgframework</groupId> | ||||
| <artifactId>easypoi</artifactId> | <artifactId>easypoi</artifactId> | ||||
| <version>2.1.1-SNAPSHOT</version> | |||||
| <version>2.1.2-SNAPSHOT</version> | |||||
| <packaging>pom</packaging> | <packaging>pom</packaging> | ||||
| <name>easypoi</name> | <name>easypoi</name> | ||||
| <modules> | <modules> | ||||
| @@ -24,7 +24,7 @@ | |||||
| </developers> | </developers> | ||||
| <properties> | <properties> | ||||
| <sub.version>2.1.1-SNAPSHOT</sub.version> | |||||
| <sub.version>2.1.2-SNAPSHOT</sub.version> | |||||
| <poi.version>3.9</poi.version> | <poi.version>3.9</poi.version> | ||||
| <xerces.version>2.9.1</xerces.version> | <xerces.version>2.9.1</xerces.version> | ||||
| <guava.version>16.0.1</guava.version> | <guava.version>16.0.1</guava.version> | ||||