├── .classpath ├── .gitattributes ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── README _cn.md ├── README.md ├── pom.xml ├── src └── main │ └── java │ └── com │ └── codecraft │ └── excel2html │ ├── config │ └── ConvertConfig.java │ ├── cons │ └── ExcelConstant.java │ ├── entity │ ├── ExcelHeader.java │ ├── ExcelPicture.java │ ├── ExcelTable.java │ ├── ExcelTableTd.java │ ├── ExcelTableTdStyle.java │ ├── ExcelTableTr.java │ ├── ExcelWidget.java │ ├── PictureStyle.java │ ├── RowColumnSpan.java │ └── WrapperStringBuffer.java │ ├── facade │ └── Excel2Html.java │ ├── generator │ └── HtmlGenerator.java │ ├── htmlPrint │ ├── ConsolePrint.java │ ├── FilePrint.java │ └── IHtmlPrint.java │ ├── parse │ ├── ExcelCellStyleParse4Hssf.java │ ├── ExcelContentParse.java │ ├── ExcelParse4HSSF.java │ ├── ExcelPicParse4HSSF.java │ ├── IExcelCellStyleParse.java │ ├── IExcelContentParse.java │ ├── IExcelParse.java │ └── IExcelPicParse.java │ ├── picUpload │ └── IExcelPicUpload.java │ ├── utils │ ├── ExcelUtils.java │ ├── StringsUtils.java │ └── WidgeUtils.java │ └── widget │ ├── AbsWidget.java │ ├── IWidget.java │ ├── basic │ ├── CheckWidget.java │ ├── DateWidget.java │ ├── EditorWidget.java │ ├── InputWidget.java │ ├── PicWidget.java │ └── TextareaWidget.java │ └── calc │ ├── CalcNumWidget.java │ └── CalcRltWidget.java └── target └── classes └── META-INF ├── MANIFEST.MF └── maven └── com.codecraft └── Excel2Html ├── pom.properties └── pom.xml /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | # ========================= 15 | # Operating System Files 16 | # ========================= 17 | 18 | # OSX 19 | # ========================= 20 | 21 | .DS_Store 22 | .AppleDouble 23 | .LSOverride 24 | 25 | # Thumbnails 26 | ._* 27 | 28 | # Files that might appear on external disk 29 | .Spotlight-V100 30 | .Trashes 31 | 32 | # Directories potentially created on remote AFP share 33 | .AppleDB 34 | .AppleDesktop 35 | Network Trash Folder 36 | Temporary Items 37 | .apdisk 38 | 39 | # Windows 40 | # ========================= 41 | 42 | # Windows image file caches 43 | Thumbs.db 44 | ehthumbs.db 45 | 46 | # Folder config file 47 | Desktop.ini 48 | 49 | # Recycle Bin used on file shares 50 | $RECYCLE.BIN/ 51 | 52 | # Windows Installer files 53 | *.cab 54 | *.msi 55 | *.msm 56 | *.msp 57 | 58 | # Windows shortcuts 59 | *.lnk 60 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Excel2Html 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README _cn.md: -------------------------------------------------------------------------------- 1 | # excel2html 2 | 3 | 4 | Excel2Html顾名思义将Excel转换为html.(注意:部分代码参照于别人.) 5 | 目前仅支持Excel2003格式. 6 | 7 | 如果表格的样式不对,那么请注意以下两点: 8 | 1.hssf默认字体为10px宋体. 9 | sheet.getColumnWidthInPixels : 10 | Please note, that this method works correctly only for workbooks with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). 11 | 2.excel中的内容不要充满整个单元格.(单元格内容过大会将table撑大) 12 | 13 | //测试代码 14 | public static void main(String[] args) throws Exception{ 15 | File file = new File("C:/Temp/1.xls"); 16 | ConvertConfig config = new ConvertConfig(); 17 | config.setHtmlPrint(new FilePrint("test")); 18 | config.setMaxRowNum(500).setMaxCellNum(500).setExcelType("HSSF"); 19 | Excel2Html excel2Html = new Excel2Html(config); 20 | FileInputStream fis = new FileInputStream(file); 21 | excel2Html.conver(fis, 0); 22 | fis.close(); 23 |   }  24 | 25 | html文件默认输出在c:/Temp目录. 26 | 27 | 最终目标:保证Excel与HTML相同度达到95%. 28 | 29 | 扩展:支持input textarea date checkbox calc控件,并且可以对数据持久化. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # excel2html 2 | 3 | 4 | //main test 5 | public static void main(String[] args) throws Exception{ 6 | File file = new File("C:/Temp/1.xls"); 7 | ConvertConfig config = new ConvertConfig(); 8 | config.setHtmlPrint(new FilePrint("test")); 9 | config.setMaxRowNum(500).setMaxCellNum(500).setExcelType("HSSF"); 10 | Excel2Html excel2Html = new Excel2Html(config); 11 | FileInputStream fis = new FileInputStream(file); 12 | excel2Html.conver(fis, 0); 13 | fis.close();//try catch finally 14 |   }  15 | 16 | The HTML file stored in C:/Temp. 17 | 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.codecraft 6 | Excel2Html 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Excel2Html 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 3.8.1 22 | test 23 | 24 | 25 | 26 | org.apache.poi 27 | poi 28 | 3.12 29 | 30 | 31 | 32 | org.apache.poi 33 | poi-examples 34 | 3.12 35 | 36 | 37 | 38 | org.apache.poi 39 | poi-ooxml 40 | 3.12 41 | 42 | 43 | 44 | org.apache.poi 45 | poi-ooxml-schemas 46 | 3.12 47 | 48 | 49 | 50 | org.apache.poi 51 | poi-scratchpad 52 | 3.12 53 | 54 | 55 | 56 | org.apache.xmlbeans 57 | xmlbeans 58 | 2.3.0 59 | 60 | 61 | 62 | org.json 63 | json 64 | 20080701 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/config/ConvertConfig.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.config; 2 | 3 | import java.text.SimpleDateFormat; 4 | 5 | import java.util.Collection; 6 | import java.util.Date; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | import com.codecraft.excel2html.cons.ExcelConstant; 11 | import com.codecraft.excel2html.htmlPrint.FilePrint; 12 | import com.codecraft.excel2html.htmlPrint.IHtmlPrint; 13 | import com.codecraft.excel2html.parse.ExcelCellStyleParse4Hssf; 14 | import com.codecraft.excel2html.parse.ExcelContentParse; 15 | import com.codecraft.excel2html.parse.ExcelParse4HSSF; 16 | import com.codecraft.excel2html.parse.ExcelPicParse4HSSF; 17 | import com.codecraft.excel2html.parse.IExcelCellStyleParse; 18 | import com.codecraft.excel2html.parse.IExcelContentParse; 19 | import com.codecraft.excel2html.parse.IExcelParse; 20 | import com.codecraft.excel2html.parse.IExcelPicParse; 21 | import com.codecraft.excel2html.picUpload.IExcelPicUpload; 22 | import com.codecraft.excel2html.widget.IWidget; 23 | import com.codecraft.excel2html.widget.basic.CheckWidget; 24 | import com.codecraft.excel2html.widget.basic.DateWidget; 25 | import com.codecraft.excel2html.widget.basic.EditorWidget; 26 | import com.codecraft.excel2html.widget.basic.InputWidget; 27 | import com.codecraft.excel2html.widget.basic.TextareaWidget; 28 | import com.codecraft.excel2html.widget.calc.CalcNumWidget; 29 | import com.codecraft.excel2html.widget.calc.CalcRltWidget; 30 | 31 | /** 32 | * Excel解析的设置 33 | * @author zoro 34 | * 35 | */ 36 | public class ConvertConfig { 37 | //Excel解析器 38 | private IExcelParse excelParse; 39 | 40 | //pic解析器 41 | private IExcelPicParse excelPicParse; 42 | 43 | //样式解析器 44 | private IExcelCellStyleParse excelStyleParse; 45 | 46 | //内容解析器 47 | private IExcelContentParse excelContentParse; 48 | 49 | //图片上传 50 | private IExcelPicUpload picUpload; 51 | 52 | //HTML 输出 53 | private IHtmlPrint htmlPrint; 54 | 55 | //excel 格式 56 | private String excelType = ExcelConstant.EXCEL_TYPE_4_HSSF; 57 | 58 | //html domian 59 | private String htmlDomain = ""; 60 | 61 | //js domain 62 | private String htmlJsVsersion = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); 63 | 64 | //prefix path 65 | private String prefixPath = "http://163.com"; 66 | 67 | //excel最大行数 68 | private int maxRowNum = 300; 69 | 70 | //excel最大列数 71 | private int maxCellNum = 300; 72 | 73 | //测试宽度(testWidth为true时,会在控制台打印宽度) 74 | private boolean testWidth = false; 75 | 76 | //页面模式 77 | private boolean htmlView = true; 78 | 79 | //页面默认控件 80 | private Set defaultRegWidget = null; 81 | 82 | //默认的是HSSF 83 | public ConvertConfig(){ 84 | init(); 85 | } 86 | 87 | /** 88 | * 初始化 89 | */ 90 | @SuppressWarnings("serial") 91 | private void init(){ 92 | excelParse = new ExcelParse4HSSF(); 93 | excelPicParse = new ExcelPicParse4HSSF(); 94 | excelStyleParse = new ExcelCellStyleParse4Hssf(); 95 | excelContentParse = new ExcelContentParse(); 96 | htmlPrint = new FilePrint(); 97 | defaultRegWidget = new HashSet(){ 98 | { 99 | //basic 100 | add(new InputWidget()); 101 | add(new TextareaWidget()); 102 | add(new EditorWidget()); 103 | add(new CheckWidget()); 104 | add(new DateWidget()); 105 | 106 | //calc 107 | add(new CalcNumWidget()); 108 | add(new CalcRltWidget()); 109 | } 110 | }; 111 | 112 | } 113 | 114 | public IExcelParse getExcelParse() { 115 | return excelParse; 116 | } 117 | 118 | public ConvertConfig setExcelParse(IExcelParse excelParse) { 119 | this.excelParse = excelParse; 120 | return this; 121 | } 122 | 123 | public IExcelPicParse getExcelPicParse() { 124 | return excelPicParse; 125 | } 126 | 127 | public ConvertConfig setExcelPicParse(IExcelPicParse excelPicParse) { 128 | this.excelPicParse = excelPicParse; 129 | return this; 130 | } 131 | 132 | public IExcelCellStyleParse getExcelStyleParse() { 133 | return excelStyleParse; 134 | } 135 | 136 | public ConvertConfig setExcelStyleParse(IExcelCellStyleParse excelStyleParse) { 137 | this.excelStyleParse = excelStyleParse; 138 | return this; 139 | } 140 | 141 | public IExcelContentParse getExcelContentParse() { 142 | return excelContentParse; 143 | } 144 | 145 | public ConvertConfig setExcelContentParse(IExcelContentParse excelContentParse) { 146 | this.excelContentParse = excelContentParse; 147 | return this; 148 | } 149 | 150 | public IExcelPicUpload getPicUpload() { 151 | return picUpload; 152 | } 153 | 154 | public ConvertConfig setPicUpload(IExcelPicUpload picUpload) { 155 | this.picUpload = picUpload; 156 | return this; 157 | } 158 | 159 | public IHtmlPrint getHtmlPrint() { 160 | return htmlPrint; 161 | } 162 | 163 | public ConvertConfig setHtmlPrint(IHtmlPrint htmlPrint) { 164 | this.htmlPrint = htmlPrint; 165 | return this; 166 | } 167 | 168 | public String getHtmlDomain() { 169 | return htmlDomain; 170 | } 171 | 172 | public ConvertConfig setHtmlDomain(String htmlDomain) { 173 | this.htmlDomain = htmlDomain; 174 | return this; 175 | } 176 | 177 | public String getHtmlJsVsersion() { 178 | return htmlJsVsersion; 179 | } 180 | 181 | public ConvertConfig setHtmlJsVsersion(String htmlJsVsersion) { 182 | this.htmlJsVsersion = htmlJsVsersion; 183 | return this; 184 | } 185 | 186 | public String getPrefixPath() { 187 | return prefixPath; 188 | } 189 | 190 | public ConvertConfig setPrefixPath(String prefixPath) { 191 | this.prefixPath = prefixPath; 192 | return this; 193 | } 194 | 195 | public int getMaxRowNum() { 196 | return maxRowNum; 197 | } 198 | 199 | public ConvertConfig setMaxRowNum(int maxRowNum) { 200 | this.maxRowNum = maxRowNum; 201 | return this; 202 | } 203 | 204 | public int getMaxCellNum() { 205 | return maxCellNum; 206 | } 207 | 208 | public ConvertConfig setMaxCellNum(int maxCellNum) { 209 | this.maxCellNum = maxCellNum; 210 | return this; 211 | } 212 | 213 | public String getExcelType() { 214 | return excelType; 215 | } 216 | 217 | public ConvertConfig setExcelType(String excelType) { 218 | this.excelType = excelType; 219 | return this; 220 | } 221 | 222 | public boolean getTestWidth() { 223 | return testWidth; 224 | } 225 | 226 | public ConvertConfig setTestWidth(boolean testWidth) { 227 | this.testWidth = testWidth; 228 | return this; 229 | } 230 | 231 | public ConvertConfig registerWidget(IWidget widget){ 232 | if(widget != null){ 233 | defaultRegWidget.add(widget); 234 | } 235 | return this; 236 | } 237 | 238 | public ConvertConfig registerWidgetAll(Collection colle){ 239 | if(colle != null && colle.size() > 0){ 240 | defaultRegWidget.addAll(colle); 241 | } 242 | return this; 243 | } 244 | 245 | public Set getDefaultRegWidget() { 246 | return defaultRegWidget; 247 | } 248 | 249 | public boolean getHtmlView() { 250 | return htmlView; 251 | } 252 | 253 | public ConvertConfig setHtmlView(boolean htmlView) { 254 | this.htmlView = htmlView; 255 | return this; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/cons/ExcelConstant.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.cons; 2 | 3 | /** 4 | * 常量 5 | * @author zoro 6 | */ 7 | public class ExcelConstant { 8 | public final static String WIDGET_BACKGROUND_COLOR = "#F2DCC8"; 9 | public final static String EXCEL_TYPE_4_HSSF = "HSSF"; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelHeader.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | /** 3 | * excel header or footer 4 | * @author zoro 5 | */ 6 | public class ExcelHeader { 7 | private String headerType;//类型: header footer 8 | 9 | private String leftContent = "";//居左 10 | 11 | private String centerContent = "";//居中 12 | 13 | private String rightContent = "";//居右 14 | 15 | public String getHeaderType() { 16 | return headerType; 17 | } 18 | 19 | public void setHeaderType(String headerType) { 20 | this.headerType = headerType; 21 | } 22 | 23 | public String getLeftContent() { 24 | return leftContent; 25 | } 26 | 27 | public void setLeftContent(String leftContent) { 28 | this.leftContent = leftContent; 29 | } 30 | 31 | public String getCenterContent() { 32 | return centerContent; 33 | } 34 | 35 | public void setCenterContent(String centerContent) { 36 | this.centerContent = centerContent; 37 | } 38 | 39 | public String getRightContent() { 40 | return rightContent; 41 | } 42 | 43 | public void setRightContent(String rightContent) { 44 | this.rightContent = rightContent; 45 | } 46 | 47 | public String getContent(){ 48 | if(!"".equals(leftContent)){ 49 | return leftContent; 50 | }else if(!"".equals(centerContent)){ 51 | return centerContent; 52 | }else if(!"".equals(rightContent)){ 53 | return rightContent; 54 | } 55 | return ""; 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelPicture.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | import org.apache.poi.ddf.EscherClientAnchorRecord; 4 | import org.apache.poi.hssf.usermodel.HSSFCell; 5 | import org.apache.poi.hssf.usermodel.HSSFPictureData; 6 | import org.apache.poi.hssf.usermodel.HSSFRow; 7 | import org.apache.poi.hssf.usermodel.HSSFSheet; 8 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 9 | 10 | 11 | /** 12 | * excel2003 picture 13 | * @author zoro 14 | * 15 | */ 16 | public class ExcelPicture { 17 | private String url;//图片url 18 | private final HSSFWorkbook workbook; 19 | private final HSSFSheet sheet; 20 | private final HSSFPictureData pictureData; 21 | private final EscherClientAnchorRecord clientAnchor; 22 | private int sheetIndex;//所属sheet index 23 | private PictureStyle picStyleBo;//图片样式 24 | 25 | public ExcelPicture(HSSFWorkbook workbook, HSSFSheet sheet, 26 | HSSFPictureData pictureData, EscherClientAnchorRecord clientAnchor,int sheetIndex) { 27 | this.workbook = workbook; 28 | this.sheet = sheet; 29 | this.pictureData = pictureData; 30 | this.clientAnchor = clientAnchor; 31 | this.sheetIndex = sheetIndex; 32 | } 33 | 34 | public String getUrl() { 35 | return url; 36 | } 37 | 38 | public void setUrl(String url) { 39 | this.url = url; 40 | } 41 | 42 | public HSSFWorkbook getWorkbook() { 43 | return workbook; 44 | } 45 | 46 | public HSSFSheet getSheet() { 47 | return sheet; 48 | } 49 | 50 | public EscherClientAnchorRecord getClientAnchor() { 51 | return clientAnchor; 52 | } 53 | 54 | public HSSFPictureData getPictureData() { 55 | return pictureData; 56 | } 57 | 58 | public byte[] getData() { 59 | return pictureData.getData(); 60 | } 61 | 62 | public String suggestFileExtension() { 63 | return pictureData.suggestFileExtension(); 64 | } 65 | 66 | public int getSheetIndex() { 67 | return sheetIndex; 68 | } 69 | 70 | public void setSheetIndex(int sheetIndex) { 71 | this.sheetIndex = sheetIndex; 72 | } 73 | 74 | /** 75 | * 推测图片中心所覆盖的单元格,这个值不一定准确,但通常有效 76 | * 77 | * @return the row0 78 | */ 79 | public short getRow0() { 80 | int row1 = getRow1(); 81 | int row2 = getRow2(); 82 | if (row1 == row2) { 83 | return (short) row1; 84 | } 85 | 86 | int heights[] = new int[row2 - row1 + 1]; 87 | for (int i = 0; i < heights.length; i++) { 88 | heights[i] = getRowHeight(row1 + i); 89 | } 90 | 91 | // HSSFClientAnchor 中 dx 只能在 0-1023 之间,dy 只能在 0-255 之间 92 | // 表示相对位置的比率,不是绝对值 93 | int dy1 = getDy1() * heights[0] / 255; 94 | int dy2 = getDy2() * heights[heights.length - 1] / 255; 95 | return (short) (getCenter(heights, dy1, dy2) + row1); 96 | } 97 | 98 | private short getRowHeight(int rowIndex) { 99 | HSSFRow row = sheet.getRow(rowIndex); 100 | short h = row == null ? sheet.getDefaultRowHeight() : row.getHeight(); 101 | return h; 102 | } 103 | 104 | /** 105 | * 获得单元格高度 106 | */ 107 | public double getHeight(int startIndex, int endIndex){ 108 | double height = 0; 109 | if(startIndex > endIndex){ 110 | return height; 111 | } 112 | for(int i = startIndex; i <= endIndex ; i++){ 113 | HSSFRow row = sheet.getRow(i); 114 | if(row == null){ 115 | continue; 116 | } 117 | double h = row.getHeightInPoints()* 1.35; 118 | height += h; 119 | } 120 | return height; 121 | } 122 | 123 | /** 124 | * 获得单元格宽度 125 | */ 126 | public double getWidth(int startIndex, int endIndex){ 127 | double width = 0; 128 | if(startIndex > endIndex){ 129 | return width; 130 | } 131 | //HSSFRow firstRow = sheet.getRow(0); 132 | //这里取0有问题,所以取1 133 | HSSFRow firstRow = sheet.getRow(1); 134 | for(int i = startIndex; i <= endIndex ; i++){ 135 | HSSFCell cell = firstRow.getCell(i); 136 | if(cell == null){ 137 | continue; 138 | } 139 | double h = sheet.getColumnWidthInPixels(i); //像素 140 | width += h; 141 | } 142 | return width; 143 | } 144 | 145 | /** 146 | * 获得顶端偏移量 147 | */ 148 | public int getTop(short startIndex) { 149 | int top = 0; 150 | if(startIndex == 0){ 151 | return top; 152 | } 153 | for(int i = 0; i < startIndex ; i++){ 154 | HSSFRow row = sheet.getRow(i); 155 | if(row == null){ 156 | continue; 157 | } 158 | double h = row.getHeightInPoints(); 159 | top += h; 160 | } 161 | double sum = top * 1.35; 162 | return (int)sum; 163 | } 164 | 165 | /** 166 | * 获得左边偏移量 167 | */ 168 | public int getLeft(short startIndex) { 169 | int left = 0; 170 | if(startIndex == 0){ 171 | return left; 172 | } 173 | //HSSFRow firstRow = sheet.getRow(0); 174 | //这里取0有问题,所以取1 175 | HSSFRow firstRow = sheet.getRow(1); 176 | for(int i = 0; i < startIndex ; i++){ 177 | HSSFCell cell = firstRow.getCell(i); 178 | if(cell == null){ 179 | continue; 180 | } 181 | double h = sheet.getColumnWidth(i) / 32 *0.89; 182 | left += h; 183 | } 184 | return left; 185 | } 186 | 187 | /** 188 | * 推测图片中心所覆盖的单元格,这个值不一定准确,但通常有效 189 | * 190 | * @return the col0 191 | */ 192 | @SuppressWarnings("deprecation") 193 | public short getCol0() { 194 | short col1 = getCol1(); 195 | short col2 = getCol2(); 196 | 197 | if (col1 == col2) { 198 | return col1; 199 | } 200 | 201 | int widths[] = new int[col2 - col1 + 1]; 202 | for (int i = 0; i < widths.length; i++) { 203 | widths[i] = sheet.getColumnWidth(col1); 204 | } 205 | // HSSFClientAnchor 中 dx 只能在 0-1023 之间,dy 只能在 0-255 之间 206 | // 表示相对位置的比率,不是绝对值 207 | int dx1 = getDx1() * widths[0] / 1023; 208 | int dx2 = getDx2() * widths[widths.length - 1] / 1023; 209 | 210 | return (short) (getCenter(widths, dx1, dx2) + col1); 211 | } 212 | 213 | /** 214 | * 给定各线段的长度,以及起点相对于起点段的偏移量,终点相对于终点段的偏移量, 求中心点所在的线段 215 | * 216 | * @param a 217 | * the a 各线段的长度 218 | * @param d1 219 | * the d1 起点相对于起点段 220 | * @param d2 221 | * the d2 终点相对于终点段的偏移量 222 | * 223 | * @return the center 224 | */ 225 | protected static int getCenter(int[] a, int d1, int d2) { 226 | // 线段长度 227 | int width = a[0] - d1 + d2; 228 | for (int i = 1; i < a.length - 1; i++) { 229 | width += a[i]; 230 | } 231 | 232 | // 中心点位置 233 | int c = width / 2 + d1; 234 | int x = a[0]; 235 | int cno = 0; 236 | 237 | while (c > x) { 238 | x += a[cno]; 239 | cno++; 240 | } 241 | 242 | return cno; 243 | } 244 | 245 | /** 246 | * 左上角所在列 247 | * 248 | * @return the col1 249 | */ 250 | public short getCol1() { 251 | return clientAnchor.getCol1(); 252 | } 253 | 254 | /** 255 | * 右下角所在的列 256 | * 257 | * @return the col2 258 | */ 259 | public short getCol2() { 260 | return clientAnchor.getCol2(); 261 | } 262 | 263 | /** 264 | * 左上角的相对偏移量 265 | * 266 | * @return the dx1 267 | */ 268 | public short getDx1() { 269 | return clientAnchor.getDx1(); 270 | } 271 | 272 | /** 273 | * 右下角的相对偏移量 274 | * 275 | * @return the dx2 276 | */ 277 | public short getDx2() { 278 | return clientAnchor.getDx2(); 279 | } 280 | 281 | /** 282 | * 左上角的相对偏移量 283 | * 284 | * @return the dy1 285 | */ 286 | public short getDy1() { 287 | return clientAnchor.getDy1(); 288 | } 289 | 290 | /** 291 | * 右下角的相对偏移量 292 | * 293 | * @return the dy2 294 | */ 295 | public short getDy2() { 296 | return clientAnchor.getDy2(); 297 | } 298 | 299 | /** 300 | * 左上角所在的行 301 | * 302 | * @return the row1 303 | */ 304 | public short getRow1() { 305 | return clientAnchor.getRow1(); 306 | } 307 | 308 | /** 309 | * 右下角所在的行 310 | * 311 | * @return the row2 312 | */ 313 | public short getRow2() { 314 | return clientAnchor.getRow2(); 315 | } 316 | 317 | public PictureStyle getPicStyleBo() { 318 | return picStyleBo; 319 | } 320 | 321 | public void setPicStyleBo(PictureStyle picStyleBo) { 322 | this.picStyleBo = picStyleBo; 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelTable.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import org.json.JSONObject; 9 | 10 | import com.codecraft.excel2html.config.ConvertConfig; 11 | 12 | /** 13 | * excel table 14 | * @author zoro 15 | * 16 | */ 17 | public class ExcelTable { 18 | private ExcelHeader header;//页眉 19 | 20 | private ExcelHeader footer;//页脚 21 | 22 | private boolean hasEditor = false;//是否有编辑器 23 | 24 | private int firstRowNum = -1;//起始行(sheet.getFirstRowNum()) 25 | 26 | private int lastRowNum = -1;//结束行(sheet.getLastRowNum();) 27 | 28 | private int widthRowNum = -1;//width行(此行是程序自动添加) 29 | 30 | private int cellSize;//列数(firstRow.getLastCellNum() - firstRow.getFirstCellNum()) 31 | 32 | private int startIdValue = 0;//多个sheet时控件id的初始值 (第一个sheet为0,第二个sheet初始值从上个sheet累加) 33 | 34 | private JSONObject excelIdMap = new JSONObject();//Excel id与 tag id的关联关系 35 | 36 | private JSONObject tagIdMap = new JSONObject();//tag id与Excel id的关联关系 37 | 38 | private Map trMap = new HashMap();//tr map 39 | 40 | private List picList = new ArrayList();//图片列表 41 | 42 | private List picStyleList = new ArrayList();//图片样式 43 | 44 | private List widgetList = new ArrayList();//控件列表 45 | 46 | private RowColumnSpan rowColumnSpan;//行列跨行信息 47 | 48 | private ConvertConfig config;//转换配置 49 | 50 | private int usedPicIndex = 0;//图片被使用的index 51 | 52 | public ExcelHeader getHeader() { 53 | return header; 54 | } 55 | 56 | public void setHeader(ExcelHeader header) { 57 | this.header = header; 58 | } 59 | 60 | public ExcelHeader getFooter() { 61 | return footer; 62 | } 63 | 64 | public void setFooter(ExcelHeader footer) { 65 | this.footer = footer; 66 | } 67 | 68 | public boolean isHasEditor() { 69 | return hasEditor; 70 | } 71 | 72 | public void setHasEditor(boolean hasEditor) { 73 | this.hasEditor = hasEditor; 74 | } 75 | 76 | public int getFirstRowNum() { 77 | return firstRowNum; 78 | } 79 | 80 | public void setFirstRowNum(int firstRowNum) { 81 | this.firstRowNum = firstRowNum; 82 | } 83 | 84 | public int getLastRowNum() { 85 | return lastRowNum; 86 | } 87 | 88 | public void setLastRowNum(int lastRowNum) { 89 | this.lastRowNum = lastRowNum; 90 | } 91 | 92 | public int getCellSize() { 93 | return cellSize; 94 | } 95 | 96 | public void setCellSize(int cellSize) { 97 | this.cellSize = cellSize; 98 | } 99 | 100 | public int getStartIdValue() { 101 | return startIdValue; 102 | } 103 | 104 | public void setStartIdValue(int startIdValue) { 105 | this.startIdValue = startIdValue; 106 | } 107 | 108 | public JSONObject getExcelIdMap() { 109 | return excelIdMap; 110 | } 111 | 112 | public void setExcelIdMap(JSONObject excelIdMap) { 113 | this.excelIdMap = excelIdMap; 114 | } 115 | 116 | public JSONObject getTagIdMap() { 117 | return tagIdMap; 118 | } 119 | 120 | public void setTagIdMap(JSONObject tagIdMap) { 121 | this.tagIdMap = tagIdMap; 122 | } 123 | 124 | public Map getTrMap() { 125 | return trMap; 126 | } 127 | 128 | public void setTrMap(Map trMap) { 129 | this.trMap = trMap; 130 | } 131 | 132 | public List getPicList() { 133 | return picList; 134 | } 135 | 136 | public void setPicList(List picList) { 137 | this.picList = picList; 138 | } 139 | 140 | public List getWidgetList() { 141 | return widgetList; 142 | } 143 | 144 | public void setWidgetList(List widgetList) { 145 | this.widgetList = widgetList; 146 | } 147 | 148 | public ConvertConfig getConfig() { 149 | return config; 150 | } 151 | 152 | public void setConfig(ConvertConfig config) { 153 | this.config = config; 154 | } 155 | 156 | public List getPicStyleList() { 157 | return picStyleList; 158 | } 159 | 160 | public void setPicStyleList(List picStyleList) { 161 | this.picStyleList = picStyleList; 162 | } 163 | 164 | public RowColumnSpan getRowColumnSpan() { 165 | return rowColumnSpan; 166 | } 167 | 168 | public void setRowColumnSpan(RowColumnSpan rowColumnSpan) { 169 | this.rowColumnSpan = rowColumnSpan; 170 | } 171 | 172 | public int getWidthRowNum() { 173 | return widthRowNum; 174 | } 175 | 176 | public void setWidthRowNum(int widthRowNum) { 177 | this.widthRowNum = widthRowNum; 178 | } 179 | 180 | public int getUsedPicIndex() { 181 | return usedPicIndex; 182 | } 183 | 184 | public void setUsedPicIndex(int usedPicIndex) { 185 | this.usedPicIndex = usedPicIndex; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelTableTd.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | 4 | /** 5 | * 注意:width是sheet.getColumnWidthInPixels方法取得的,而此方法只能在xls格式默认字体为宋体10pt时才会正确使用.(重要) 6 | * 7 | * getColumnWidthInPixels: 8 | * Please note, that this method works correctly only for workbooks with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). 9 | * 10 | * 11 | * excel table td 12 | * @author zoro 13 | * 14 | */ 15 | public class ExcelTableTd { 16 | private int colNum = -1;//所属第几列 17 | 18 | private String width = "";//宽度(带单位) 19 | 20 | private double widthNum = -1;//width - 单位 = widthNum 21 | 22 | private String height="";//控件的高度(带单位),不是td的高度 23 | 24 | private double heightNum = -1;//height - 单位 = heightNum 25 | 26 | private String colspan = "";//横跨的列数 27 | 28 | private String rowspan = "1";//横跨的行数 29 | 30 | private String tdAlign = ""; //td的align 31 | 32 | private String textAlign = "";//text的水平align(left center right) 33 | 34 | private String verAlign = "";//text的垂直align(bottom center top) 35 | 36 | private int fontSize = 0;//字体大小 37 | 38 | private boolean isEditor = false;//是否是编辑器,如果包含就把 align 去掉 39 | 40 | private boolean isComponet = false;//是否包含控件 (包括inut span div editor) 41 | 42 | private String content = "";//td内容 43 | 44 | private ExcelTableTdStyle tdStyle = new ExcelTableTdStyle();//td样式 45 | 46 | public String getContent() { 47 | return content; 48 | } 49 | 50 | public void setContent(String content) { 51 | this.content = content; 52 | } 53 | 54 | public String getWidth() { 55 | return width; 56 | } 57 | 58 | public void setWidth(String width) { 59 | this.width = width; 60 | } 61 | 62 | public String getColspan() { 63 | return colspan; 64 | } 65 | 66 | public void setColspan(String colspan) { 67 | this.colspan = colspan; 68 | } 69 | 70 | public String getRowspan() { 71 | return rowspan; 72 | } 73 | 74 | public void setRowspan(String rowspan) { 75 | this.rowspan = rowspan; 76 | } 77 | 78 | public String getTdAlign() { 79 | return tdAlign; 80 | } 81 | 82 | public void setTdAlign(String tdAlign) { 83 | this.tdAlign = tdAlign; 84 | } 85 | 86 | public int getColNum() { 87 | return colNum; 88 | } 89 | 90 | public void setColNum(int colNum) { 91 | this.colNum = colNum; 92 | } 93 | 94 | public int getFontSize() { 95 | return fontSize; 96 | } 97 | 98 | public void setFontSize(int fontSize) { 99 | this.fontSize = fontSize; 100 | } 101 | 102 | public boolean isEditor() { 103 | return isEditor; 104 | } 105 | 106 | public void setEditor(boolean isEditor) { 107 | this.isEditor = isEditor; 108 | } 109 | 110 | public String getTextAlign() { 111 | return textAlign; 112 | } 113 | 114 | public void setTextAlign(String textAlign) { 115 | this.textAlign = textAlign; 116 | } 117 | 118 | public boolean isComponet() { 119 | return isComponet; 120 | } 121 | 122 | public void setComponet(boolean isComponet) { 123 | this.isComponet = isComponet; 124 | } 125 | 126 | public String getVerAlign() { 127 | return verAlign; 128 | } 129 | 130 | public void setVerAlign(String verAlign) { 131 | this.verAlign = verAlign; 132 | } 133 | 134 | public String getHeight() { 135 | return height; 136 | } 137 | 138 | public void setHeight(String height) { 139 | this.height = height; 140 | } 141 | 142 | public double getWidthNum() { 143 | return widthNum; 144 | } 145 | 146 | public void setWidthNum(double widthNum) { 147 | this.widthNum = widthNum; 148 | } 149 | 150 | public double getHeightNum() { 151 | return heightNum; 152 | } 153 | 154 | public void setHeightNum(double heightNum) { 155 | this.heightNum = heightNum; 156 | } 157 | 158 | public ExcelTableTdStyle getTdStyle() { 159 | return tdStyle; 160 | } 161 | 162 | public void setTdStyle(ExcelTableTdStyle tdStyle) { 163 | this.tdStyle = tdStyle; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelTableTdStyle.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | 4 | /** 5 | * excel table td style 6 | * @author zoro 7 | * 8 | */ 9 | public class ExcelTableTdStyle { 10 | private String font = "";//字体设置 (font-size,font-family,font-weight,font-style,color) 11 | private String color = "";//背景色 12 | private String borderTop = "";//上边框 13 | private String borderLeft = "";//左边框 14 | private String borderBottom = "";//下边框 15 | private String borderRight = "";//有边框 16 | private String fontHeight;//字体大小 17 | private String fontName;//字体样式(宋体,黑体) 18 | private String fontItalic;//是否斜体 19 | private String fontColor;//字体颜色 20 | 21 | public String getFont() { 22 | return font; 23 | } 24 | 25 | public void setFont(String font) { 26 | this.font = font; 27 | } 28 | 29 | public String getColor() { 30 | return color; 31 | } 32 | 33 | public void setColor(String color) { 34 | this.color = color; 35 | } 36 | 37 | public String getBorderTop() { 38 | return borderTop; 39 | } 40 | 41 | public void setBorderTop(String borderTop) { 42 | this.borderTop = borderTop; 43 | } 44 | 45 | public String getBorderLeft() { 46 | return borderLeft; 47 | } 48 | 49 | public void setBorderLeft(String borderLeft) { 50 | this.borderLeft = borderLeft; 51 | } 52 | 53 | public String getBorderBottom() { 54 | return borderBottom; 55 | } 56 | 57 | public void setBorderBottom(String borderBottom) { 58 | this.borderBottom = borderBottom; 59 | } 60 | 61 | public String getBorderRight() { 62 | return borderRight; 63 | } 64 | 65 | public void setBorderRight(String borderRight) { 66 | this.borderRight = borderRight; 67 | } 68 | 69 | public String getFontHeight() { 70 | return fontHeight; 71 | } 72 | 73 | public void setFontHeight(String fontHeight) { 74 | this.fontHeight = fontHeight; 75 | } 76 | 77 | public String getFontName() { 78 | return fontName; 79 | } 80 | 81 | public void setFontName(String fontName) { 82 | this.fontName = fontName; 83 | } 84 | 85 | public String getFontItalic() { 86 | return fontItalic; 87 | } 88 | 89 | public void setFontItalic(String fontItalic) { 90 | this.fontItalic = fontItalic; 91 | } 92 | 93 | public String getFontColor() { 94 | return fontColor; 95 | } 96 | 97 | public void setFontColor(String fontColor) { 98 | this.fontColor = fontColor; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelTableTr.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | /** 6 | * excel table tr 7 | * @author zoro 8 | * 9 | */ 10 | public class ExcelTableTr { 11 | private int rowNum = -1;//tr所属列 12 | private String height = "";//tr的height 13 | private int lastColNum = -1;//tr的结束列 14 | private Map tdMap = new HashMap();//td map 15 | 16 | public Map getTdMap() { 17 | return tdMap; 18 | } 19 | 20 | public void setTdMap(Map tdMap) { 21 | this.tdMap = tdMap; 22 | } 23 | 24 | public int getRowNum() { 25 | return rowNum; 26 | } 27 | 28 | public void setRowNum(int rowNum) { 29 | this.rowNum = rowNum; 30 | } 31 | 32 | public int getLastColNum() { 33 | return lastColNum; 34 | } 35 | 36 | public void setLastColNum(int lastColNum) { 37 | this.lastColNum = lastColNum; 38 | } 39 | 40 | public String getHeight() { 41 | return height; 42 | } 43 | 44 | public void setHeight(String height) { 45 | this.height = height; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/ExcelWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | /** 4 | * 5 | * @author zoro 6 | * 7 | */ 8 | public class ExcelWidget{ 9 | public String tagId;//控件id 10 | 11 | public String widgetType;//控件类型 12 | 13 | public String getTagId() { 14 | return tagId; 15 | } 16 | 17 | public void setTagId(String tagId) { 18 | this.tagId = tagId; 19 | } 20 | 21 | public String getWidgetType() { 22 | return widgetType; 23 | } 24 | 25 | public void setWidgetType(String widgetType) { 26 | this.widgetType = widgetType; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/PictureStyle.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | 4 | /** 5 | * 图片样式(可排序) 6 | * @author zoro 7 | * 8 | */ 9 | public class PictureStyle implements Comparable{ 10 | private int sheetIndex = 0;//sheet index 11 | 12 | private String url;//图片url 13 | 14 | private int top;//上偏移量 15 | 16 | private int left;//左偏移量 17 | 18 | private double width;//宽度 19 | 20 | private double height;//高度 21 | 22 | public PictureStyle() { 23 | 24 | } 25 | 26 | public String getUrl() { 27 | return url; 28 | } 29 | 30 | public void setUrl(String url) { 31 | this.url = url; 32 | } 33 | 34 | public int getTop() { 35 | return top; 36 | } 37 | 38 | public void setTop(int top) { 39 | this.top = top; 40 | } 41 | 42 | public int getLeft() { 43 | return left; 44 | } 45 | 46 | public void setLeft(int left) { 47 | this.left = left; 48 | } 49 | 50 | public double getWidth() { 51 | return width; 52 | } 53 | 54 | public void setWidth(double width) { 55 | this.width = width; 56 | } 57 | 58 | public double getHeight() { 59 | return height; 60 | } 61 | 62 | public void setHeight(double height) { 63 | this.height = height; 64 | } 65 | 66 | public int getSheetIndex() { 67 | return sheetIndex; 68 | } 69 | 70 | public void setSheetIndex(int sheetIndex) { 71 | this.sheetIndex = sheetIndex; 72 | } 73 | 74 | @Override 75 | public int compareTo(PictureStyle obj) { 76 | if(obj.getSheetIndex() < this.getSheetIndex()){ 77 | return 1; 78 | }else if(obj.getSheetIndex() > this.getSheetIndex()){ 79 | return -1; 80 | }else{ 81 | if(obj.getSheetIndex() < this.getSheetIndex()){ 82 | return 1; 83 | }else if(obj.getSheetIndex() > this.getSheetIndex()){ 84 | return -1; 85 | }else{ 86 | if(obj.getTop() < this.getTop()){ 87 | return 1; 88 | }else if(obj.getTop() > this.getTop()){ 89 | return -1; 90 | }else{ 91 | if(obj.getLeft() < this.getLeft()){ 92 | return 1; 93 | }else if(obj.getLeft() > this.getLeft()){ 94 | return -1; 95 | }else{ 96 | return 0; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/RowColumnSpan.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * 10 | * 跨行 跨列信息 11 | * @author zoro 12 | * 13 | */ 14 | public class RowColumnSpan { 15 | /* 16 | * 记录跨行与跨列信息,key为 topRow + topCol ,value为 topCol + bottomRow 17 | * 18 | * topRow 19 | * ________ 20 | * | | 21 | * topCol| |bottomRow 22 | * |________| 23 | * 24 | * bottomRow 25 | */ 26 | private Map rowColunmSpanMap = new HashMap();//跨行与跨列的对象 27 | 28 | /* 29 | * 30 | * 31 | * 32 | * ----->需要把此td过滤掉,rowColunmSpanFilter就是这个作用. 33 | * 34 | * 35 | * 36 | * 37 | * 38 | * 39 | * 40 | * 41 | *
42 | * 43 | */ 44 | private Set rowColunmSpanFilter = new HashSet(); 45 | 46 | public Map getRowColunmSpanMap() { 47 | return rowColunmSpanMap; 48 | } 49 | 50 | public void setRowColunmSpanMap(Map rowColunmSpanMap) { 51 | this.rowColunmSpanMap = rowColunmSpanMap; 52 | } 53 | 54 | public Set getRowColunmSpanFilter() { 55 | return rowColunmSpanFilter; 56 | } 57 | 58 | public void setRowColunmSpanFilter(Set rowColunmSpanFilter) { 59 | this.rowColunmSpanFilter = rowColunmSpanFilter; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/entity/WrapperStringBuffer.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.entity; 2 | 3 | /** 4 | * 增加\r\n 增加script的阅读性 5 | * 6 | * @author zoro 7 | * 8 | */ 9 | public class WrapperStringBuffer{ 10 | private StringBuffer sb = null; 11 | private static final String NEW_LINE = "\r\n"; 12 | 13 | public WrapperStringBuffer(StringBuffer sb){ 14 | this.sb = sb; 15 | } 16 | 17 | public void append(String str){ 18 | sb.append(str); 19 | //##########################提交代码需要注释掉 20 | sb.append(NEW_LINE); 21 | } 22 | 23 | public StringBuffer getStringBuffer(){ 24 | return sb; 25 | } 26 | 27 | public String toString(){ 28 | return sb.toString(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/facade/Excel2Html.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.facade; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.InputStream; 6 | 7 | import com.codecraft.excel2html.config.ConvertConfig; 8 | import com.codecraft.excel2html.cons.ExcelConstant; 9 | import com.codecraft.excel2html.entity.ExcelTable; 10 | import com.codecraft.excel2html.generator.HtmlGenerator; 11 | import com.codecraft.excel2html.htmlPrint.FilePrint; 12 | import com.codecraft.excel2html.htmlPrint.IHtmlPrint; 13 | import com.codecraft.excel2html.parse.IExcelParse; 14 | import com.codecraft.excel2html.utils.ExcelUtils; 15 | 16 | /** 17 | * 用户只需调用conver方法即可 18 | * @author zoro 19 | * 20 | */ 21 | public class Excel2Html{ 22 | //转换配置 23 | private ConvertConfig config = null; 24 | 25 | public Excel2Html(){ 26 | this.config = new ConvertConfig(); 27 | } 28 | 29 | public Excel2Html(ConvertConfig config){ 30 | this.config = config; 31 | } 32 | 33 | /** 34 | * 转换所有的sheet 35 | * @param is 36 | * @throws Exception 37 | */ 38 | public void conver(InputStream is) throws Exception{ 39 | IExcelParse excelParse = config.getExcelParse(); 40 | //解析excel(用户可自定义) 41 | ExcelTable table = excelParse.parse(is, config); 42 | table.setConfig(config); 43 | 44 | //生成html页面 45 | HtmlGenerator htmlGener = new HtmlGenerator(); 46 | String html = htmlGener.toHtml(table); 47 | 48 | //输出html(用户可自定义) 49 | IHtmlPrint print = config.getHtmlPrint(); 50 | print.print(html); 51 | } 52 | 53 | /** 54 | * 转换指定sheet 55 | * @param is 56 | * @param sheetIndex 57 | * @throws Exception 58 | */ 59 | public void conver(InputStream is,int sheetIndex) throws Exception{ 60 | if(!config.getExcelType().equalsIgnoreCase(ExcelConstant.EXCEL_TYPE_4_HSSF)){ 61 | throw new Exception("目前不支持'" + config.getExcelType() + "'类型!"); 62 | } 63 | 64 | IExcelParse excelParse = config.getExcelParse(); 65 | //解析excel(用户可自定义) 66 | ExcelTable excelTable = excelParse.parse(is, sheetIndex, config); 67 | //生成html页面 68 | HtmlGenerator htmlGener = new HtmlGenerator(); 69 | String html = htmlGener.toHtml(excelTable); 70 | 71 | //输出html(用户可自定义) 72 | IHtmlPrint print = config.getHtmlPrint(); 73 | print.print(html); 74 | } 75 | 76 | public ConvertConfig getConfig() { 77 | return config; 78 | } 79 | 80 | public void setConfig(ConvertConfig config) { 81 | this.config = config; 82 | } 83 | 84 | //main test 85 | public static void main(String[] args) throws Exception{ 86 | //one convert 87 | File file = new File("C:/Temp/1.xls"); 88 | ConvertConfig config = new ConvertConfig(); 89 | config.setHtmlPrint(new FilePrint("test")); 90 | 91 | config.setMaxRowNum(500).setMaxCellNum(500).setExcelType("HSSF"); 92 | Excel2Html excel2Html = new Excel2Html(config); 93 | FileInputStream fis = new FileInputStream(file); 94 | excel2Html.conver(fis, 0); 95 | fis.close(); 96 | 97 | //batch convert 98 | // File dir = new File("C:/Temp"); 99 | // File[] listFiles = dir.listFiles(new FilenameFilter() { 100 | // @Override 101 | // public boolean accept(File dir, String name) { 102 | // if(name.endsWith(".xls")){ 103 | // return true; 104 | // } 105 | // return false; 106 | // } 107 | // }); 108 | // 109 | // ConvertConfig config = new ConvertConfig(); 110 | // for(File file : listFiles){ 111 | // String fileName = file.getName(); 112 | // if(fileName.indexOf(".") != -1){ 113 | // fileName = fileName.substring(0, fileName.indexOf(".")); 114 | // } 115 | // config.setHtmlPrint(new FilePrint(fileName)); 116 | // 117 | // config.setMaxRowNum(500).setMaxCellNum(500).setExcelType("HSSF"); 118 | // Excel2Html excel2Html = new Excel2Html(config); 119 | // FileInputStream fis = new FileInputStream(file); 120 | // excel2Html.conver(fis, 0); 121 | // fis.close(); 122 | // } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/generator/HtmlGenerator.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.generator; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import com.codecraft.excel2html.config.ConvertConfig; 9 | import com.codecraft.excel2html.entity.ExcelHeader; 10 | import com.codecraft.excel2html.entity.ExcelPicture; 11 | import com.codecraft.excel2html.entity.ExcelTable; 12 | import com.codecraft.excel2html.entity.ExcelTableTd; 13 | import com.codecraft.excel2html.entity.ExcelTableTdStyle; 14 | import com.codecraft.excel2html.entity.ExcelTableTr; 15 | import com.codecraft.excel2html.entity.PictureStyle; 16 | import com.codecraft.excel2html.entity.WrapperStringBuffer; 17 | import com.codecraft.excel2html.parse.IExcelContentParse; 18 | import com.codecraft.excel2html.picUpload.IExcelPicUpload; 19 | import com.codecraft.excel2html.utils.StringsUtils; 20 | 21 | /** 22 | * html生成器,注意每个页面都会在第一行创建一个空白行.(此空白行的目的是固定宽度) 23 | * @author zoro 24 | * 25 | */ 26 | public class HtmlGenerator { 27 | private ConvertConfig config; 28 | 29 | /** 30 | * 返回html 31 | * @param excelEntity 32 | * @return 33 | * @throws Exception 34 | */ 35 | public String toHtml(ExcelTable table) throws Exception{ 36 | this.config = table.getConfig(); 37 | StringBuffer sb = new StringBuffer(); 38 | sb.append(htmlStart());//html start 39 | sb.append(headHtml());//head html 40 | sb.append(bodyHtml(table));//body html 41 | sb.append(htmlEnd());//html end 42 | return sb.toString(); 43 | } 44 | 45 | /** 46 | * html start 47 | * @return 48 | */ 49 | private String htmlStart() { 50 | StringBuffer sb = new StringBuffer(""); 51 | sb.append(""); 52 | sb.append(""); 53 | return sb.toString(); 54 | } 55 | 56 | /** 57 | * header html 58 | * @return 59 | * @throws Exception 60 | */ 61 | private StringBuffer headHtml() throws Exception { 62 | StringBuffer sb = new StringBuffer(""); 63 | sb.append(""); 64 | sb.append(""); 65 | sb.append(" "); 66 | sb.append(""); 67 | sb.append(""); 68 | sb.append(""); 69 | sb.append(""); 70 | 71 | String jsVersion = config.getHtmlJsVsersion(); 72 | String prefixPath = config.getPrefixPath(); 73 | sb.append(String.format("", prefixPath, jsVersion)); 74 | sb.append(String.format("", prefixPath, jsVersion)); 75 | sb.append("www.excel2html.com"); 76 | 77 | //scriptHtml(sb); 78 | //scriptBodyHtml(sb); 79 | sb.append(""); 80 | return sb; 81 | } 82 | 83 | private void scriptHtml(StringBuffer sb) { 84 | String domain = config.getHtmlDomain(); 85 | String jsVersion = config.getHtmlJsVsersion(); 86 | String prefixPath = config.getPrefixPath(); 87 | if(!StringsUtils.isEmpty(domain)){ 88 | sb.append(String.format("",domain)); 89 | } 90 | sb.append(String.format("", prefixPath, jsVersion)); 91 | sb.append(String.format("", prefixPath, jsVersion)); 92 | sb.append(String.format("", prefixPath, jsVersion)); 93 | sb.append(String.format("", prefixPath, jsVersion)); 94 | sb.append(String.format("", prefixPath, jsVersion)); 95 | sb.append(String.format("", prefixPath, jsVersion)); 96 | sb.append(String.format("", prefixPath, jsVersion)); 97 | sb.append(String.format("", prefixPath, jsVersion)); 98 | sb.append(String.format("", prefixPath, jsVersion)); 99 | sb.append(String.format("", prefixPath, jsVersion)); 100 | sb.append(String.format("", prefixPath, jsVersion)); 101 | sb.append(String.format("", prefixPath, jsVersion)); 102 | sb.append(String.format("", prefixPath, jsVersion)); 103 | sb.append(String.format("", prefixPath)); 104 | sb.append(String.format("", prefixPath)); 105 | } 106 | 107 | /** 108 | * body html 109 | * @param table 110 | * @return 111 | */ 112 | private String bodyHtml(ExcelTable table) throws Exception { 113 | StringBuffer sb = new StringBuffer(""); 114 | sb.append(""); 115 | sb.append("
"); 116 | //style='border-collapse:collapse;' 使用这个边框合并样式,会导致某些表单的边框变长很多,以后处理。 117 | sb.append(""); 118 | sb.append(hiddenHtml(table));//隐藏域信息 119 | theadHtml(table,sb);//table页眉 120 | tfootHtml(table,sb);//table页脚 121 | tbodyHtml(table, sb);//table正文 122 | sb.append("
"); 123 | sb.append("
"); 124 | sb.append(""); 125 | //多页模板时,第二页不会重新解析 126 | if(table.getPicList().size() ==0){ 127 | List parsePic = parsePic(table.getPicList()); 128 | table.setPicStyleList(parsePic); 129 | } 130 | return sb.toString(); 131 | } 132 | 133 | /** 134 | * script htlml 135 | * @param sb 136 | * @return 137 | * @throws Exception 138 | */ 139 | private String scriptBodyHtml(StringBuffer sb) throws Exception { 140 | WrapperStringBuffer wsb = new WrapperStringBuffer(sb); 141 | wsb.append(" "); 402 | return wsb.toString(); 403 | } 404 | 405 | /** 406 | * 隐藏域html 407 | * @param table 408 | * @return 409 | */ 410 | private String hiddenHtml(ExcelTable table) { 411 | StringBuffer sb = new StringBuffer(""); 412 | sb.append(""); 413 | sb.append(""); 414 | sb.append("");//前台传递的参数信息 415 | sb.append(String.format("", table.getExcelIdMap().toString()));//excelId与tagId的对应关系(计算时会使用) 416 | sb.append(String.format("", table.getTagIdMap().toString()));//tagId与excelId的对应关系 417 | return sb.toString(); 418 | } 419 | 420 | /** 421 | * 页眉 html 422 | */ 423 | private void theadHtml(ExcelTable table, StringBuffer sb) { 424 | ExcelHeader header = table.getHeader(); 425 | if(header != null){ 426 | String align = ""; 427 | String content = ""; 428 | if(!"".equals(header.getLeftContent())){ 429 | align = "left"; 430 | content = header.getLeftContent(); 431 | }else if(!"".equals(header.getCenterContent())){ 432 | align = "center"; 433 | content = header.getCenterContent(); 434 | }else if(!"".equals(header.getRightContent())){ 435 | align = "right"; 436 | content = header.getRightContent(); 437 | } 438 | if(!"".equals(content)){ 439 | int cellNum = table.getCellSize(); 440 | sb.append(""); 441 | sb.append(""); 442 | sb.append(String.format("%s", align, cellNum, content)); 443 | sb.append(""); 444 | sb.append(""); 445 | sb.append(""); 446 | } 447 | } 448 | } 449 | 450 | /** 451 | * 页脚转化为theader 452 | */ 453 | private void tfootHtml(ExcelTable table, StringBuffer sb) { 454 | ExcelHeader footer = table.getFooter(); 455 | if(footer != null){ 456 | String align = ""; 457 | String content = ""; 458 | if(!"".equals(footer.getLeftContent())){ 459 | align = "left"; 460 | content = footer.getLeftContent(); 461 | }else if(!"".equals(footer.getCenterContent())){ 462 | align = "center"; 463 | content = footer.getCenterContent(); 464 | }else if(!"".equals(footer.getRightContent())){ 465 | align = "right"; 466 | content = footer.getRightContent(); 467 | } 468 | if(!"".equals(content)){ 469 | int cellNum = table.getCellSize(); 470 | sb.append(""); 471 | sb.append(""); 472 | sb.append(String.format("%s", align, cellNum, content)); 473 | 474 | sb.append(""); 475 | sb.append(""); 476 | sb.append(""); 477 | } 478 | } 479 | } 480 | 481 | /** 482 | * 表格内容 转化为tbody 483 | */ 484 | private void tbodyHtml(ExcelTable table, StringBuffer sb) 485 | throws Exception { 486 | sb.append(""); 487 | 488 | //设置宽度td 489 | String blankTrHtml = createBlankRow(table); 490 | sb.append(blankTrHtml); 491 | for (int rowNum = table.getFirstRowNum(); rowNum <= table.getLastRowNum(); rowNum++) { 492 | ExcelTableTr tr = table.getTrMap().get(rowNum); 493 | if (tr != null) { 494 | tr.setRowNum(rowNum);//设置rownum 计算合并单元格高度时用到 495 | 496 | 497 | String trHtml = tr2Html(table, tr); 498 | sb.append(trHtml); 499 | } 500 | } 501 | sb.append(""); 502 | } 503 | 504 | /** 505 | * html end 506 | * @return 507 | */ 508 | private String htmlEnd() { 509 | return ""; 510 | } 511 | 512 | /** 513 | * tr to html 514 | * @param table 515 | * @param tr 516 | * @return 517 | * @throws Exception 518 | */ 519 | private String tr2Html(ExcelTable table, ExcelTableTr tr) 520 | throws Exception { 521 | Set filter = table.getRowColumnSpan().getRowColunmSpanFilter(); 522 | StringBuffer sb = new StringBuffer(); 523 | sb.append("", tr.getHeight())); 525 | int lastColNum = tr.getLastColNum(); 526 | int rowNum = tr.getRowNum(); 527 | for (int colNum = 0; colNum < lastColNum; colNum++) { 528 | ExcelTableTd td = tr.getTdMap().get(colNum); 529 | if(td != null && !filter.contains(rowNum + "," + colNum)){ 530 | String tdHtml = td2Html(table, tr, td); 531 | sb.append(tdHtml); 532 | } 533 | } 534 | sb.append(""); 535 | return sb.toString(); 536 | } 537 | 538 | /** 539 | * 创建一个空白行(此行的目的是固定宽度)*** 540 | * @param table 541 | * @param tr 542 | * @return 543 | */ 544 | private String createBlankRow(ExcelTable table) { 545 | boolean testWidth = table.getConfig().getTestWidth(); 546 | int rowNum = table.getWidthRowNum(); 547 | ExcelTableTr tr = table.getTrMap().get(rowNum); 548 | if(tr == null){ 549 | return ""; 550 | } 551 | StringBuffer sb = new StringBuffer(); 552 | sb.append("", tr.getHeight())); 554 | int lastColNum = tr.getLastColNum(); 555 | 556 | for (int colNum = 0; colNum < lastColNum; colNum++) { 557 | ExcelTableTd td = tr.getTdMap().get(colNum); 558 | if(td != null){ 559 | sb.append(" "); 570 | sb.append(""); 571 | } 572 | } 573 | sb.append(""); 574 | return sb.toString(); 575 | } 576 | 577 | /** 578 | * td to html 579 | * @param table 580 | * @param tr 581 | * @param td 582 | * @return 583 | * @throws Exception 584 | */ 585 | private String td2Html(ExcelTable table, ExcelTableTr tr, 586 | ExcelTableTd td) throws Exception { 587 | StringBuffer sb = new StringBuffer(); 588 | sb.append(""); 610 | 611 | String content = ""; 612 | if (!StringsUtils.isEmpty(td.getContent())) { 613 | IExcelContentParse contentParse = table.getConfig().getExcelContentParse(); 614 | content = contentParse.parseConten(table, tr, td); 615 | } 616 | sb.append(content); 617 | sb.append(""); 618 | return sb.toString(); 619 | } 620 | 621 | //获得td样式 622 | private String tdStyle2Html(ExcelTable table, ExcelTableTr tr, 623 | ExcelTableTd td, ExcelTableTdStyle tdStyle) throws Exception { 624 | StringBuffer sb = new StringBuffer(); 625 | sb.append(String.format(" style='")); 626 | sb.append(tdStyle.getFont()); 627 | sb.append(tdStyle.getColor()); 628 | sb.append(tdStyle.getBorderBottom()); 629 | sb.append(tdStyle.getBorderLeft()); 630 | sb.append(tdStyle.getBorderRight()); 631 | sb.append(tdStyle.getBorderTop()); 632 | sb.append(String.format("'")); 633 | return sb.toString(); 634 | } 635 | 636 | /* 637 | ** 解析图片样式 638 | */ 639 | private List parsePic(List listPic) throws Exception { 640 | List pbList = new ArrayList(); 641 | for(ExcelPicture pic : listPic ){ 642 | int top = pic.getTop(pic.getRow1()); 643 | int left = pic.getLeft(pic.getCol1()); 644 | double width = pic.getWidth(pic.getCol1(), pic.getCol2()); 645 | double height = pic.getHeight(pic.getRow1(), pic.getRow2()); 646 | PictureStyle pb = new PictureStyle(); 647 | pb.setTop(top); 648 | pb.setLeft(left); 649 | pb.setWidth(width); 650 | pb.setHeight(height); 651 | if(pic.getSheet() != null){ 652 | pb.setSheetIndex(pic.getSheetIndex()); 653 | } 654 | String url = uploadPic(pic); 655 | pic.setUrl(url); 656 | pb.setUrl(url); 657 | pbList.add(pb); 658 | } 659 | Collections.sort(pbList); 660 | return pbList; 661 | } 662 | 663 | //上传Excel图片 664 | private String uploadPic(ExcelPicture picBo) throws Exception { 665 | byte[] data = picBo.getData(); 666 | IExcelPicUpload picLoad = config.getPicUpload(); 667 | if(picLoad != null){ 668 | return picLoad.loadPic(data); 669 | } 670 | return ""; 671 | } 672 | } 673 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/htmlPrint/ConsolePrint.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.htmlPrint; 2 | 3 | /** 4 | * 控制台输出 5 | * @author zoro 6 | * 7 | */ 8 | public class ConsolePrint implements IHtmlPrint { 9 | 10 | @Override 11 | public void print(String htmlContent) throws Exception { 12 | System.out.println(htmlContent); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/htmlPrint/FilePrint.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.htmlPrint; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.OutputStreamWriter; 7 | import java.text.SimpleDateFormat; 8 | import java.util.Date; 9 | 10 | /** 11 | * 文件输出 12 | * @author zoro 13 | * 14 | */ 15 | public class FilePrint implements IHtmlPrint { 16 | 17 | private String dirPath = "c:/temp"; 18 | 19 | private String fileName = "excel2html"; 20 | 21 | private static final String FILE_TYPE = ".html"; 22 | 23 | public FilePrint(){ 24 | 25 | } 26 | 27 | public FilePrint(String fileName){ 28 | this.fileName = fileName; 29 | } 30 | 31 | public FilePrint(String fileName, String dirPath){ 32 | this.fileName = fileName; 33 | this.dirPath = dirPath; 34 | } 35 | 36 | @Override 37 | public void print(String htmlContent) throws Exception { 38 | File dir = new File(dirPath); 39 | if(!dir.exists()){ 40 | dir.mkdirs(); 41 | } 42 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); 43 | String dateStr = sdf.format(new Date()); 44 | 45 | File printFile = new File(dir + File.separator + fileName + "-" + dateStr + FILE_TYPE ); 46 | 47 | FileOutputStream fos = null; 48 | OutputStreamWriter osw = null; 49 | BufferedWriter bw = null; 50 | try{ 51 | fos = new FileOutputStream(printFile); 52 | osw = new OutputStreamWriter(fos); 53 | bw = new BufferedWriter(osw); 54 | bw.write(htmlContent); 55 | bw.flush(); 56 | }catch(Exception e){ 57 | e.printStackTrace(); 58 | }finally{ 59 | if(bw != null){ 60 | bw.close(); 61 | } 62 | if(osw != null){ 63 | osw.close(); 64 | } 65 | if(fos != null){ 66 | fos.close(); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/htmlPrint/IHtmlPrint.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.htmlPrint; 2 | 3 | /** 4 | * html页面的持久化 5 | * @author zoro 6 | * 7 | */ 8 | public interface IHtmlPrint { 9 | 10 | public void print(String htmlContent) throws Exception; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/ExcelCellStyleParse4Hssf.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import org.apache.poi.hssf.usermodel.HSSFCell; 4 | import org.apache.poi.hssf.usermodel.HSSFCellStyle; 5 | import org.apache.poi.hssf.usermodel.HSSFPalette; 6 | import org.apache.poi.hssf.usermodel.HSSFRow; 7 | import org.apache.poi.hssf.usermodel.HSSFSheet; 8 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 9 | import org.apache.poi.hssf.util.HSSFColor; 10 | import org.apache.poi.ss.usermodel.Cell; 11 | import org.apache.poi.ss.usermodel.CellStyle; 12 | import org.apache.poi.ss.usermodel.Row; 13 | import org.apache.poi.ss.usermodel.Sheet; 14 | import org.apache.poi.ss.usermodel.Workbook; 15 | 16 | import com.codecraft.excel2html.entity.ExcelTable; 17 | import com.codecraft.excel2html.entity.ExcelTableTd; 18 | import com.codecraft.excel2html.entity.ExcelTableTdStyle; 19 | import com.codecraft.excel2html.entity.ExcelTableTr; 20 | import com.codecraft.excel2html.utils.ExcelUtils; 21 | import com.codecraft.excel2html.utils.StringsUtils; 22 | 23 | /** 24 | * 解析字体样式 表格样式 25 | * @author zoro 26 | * 27 | */ 28 | public class ExcelCellStyleParse4Hssf implements IExcelCellStyleParse { 29 | 30 | /** 31 | * 解析样式,外部调用此方法 32 | */ 33 | @Override 34 | public void parseStyle(Workbook wb, Sheet s, Row r, 35 | Cell c, int bottomRow, int bottomCell, CellStyle cs, ExcelTable table, 36 | ExcelTableTr tr, ExcelTableTd td, 37 | ExcelTableTdStyle styleBo) throws Exception { 38 | HSSFWorkbook workbook = (HSSFWorkbook) wb; 39 | HSSFSheet sheet = (HSSFSheet) s; 40 | HSSFRow row = (HSSFRow) r; 41 | HSSFCell cell = (HSSFCell) c; 42 | HSSFRow bottomeRow = bottomRow == -1 ? null : (HSSFRow) sheet.getRow(bottomRow); 43 | HSSFCell bottomeCol = bottomeRow == null ? null : bottomeRow 44 | .getCell(bottomCell); 45 | HSSFCellStyle cellStyle = (HSSFCellStyle) cs; 46 | HSSFPalette palette = workbook.getCustomPalette(); // 类HSSFPalette用于求的颜色的国际标准形式 47 | 48 | 49 | 50 | short bgColor = cellStyle.getFillForegroundColor(); 51 | HSSFColor hc = palette.getColor(bgColor); 52 | String bgColorStr = ExcelUtils.convertToStardColor(hc); 53 | 54 | if (!StringsUtils.isEmpty(bgColorStr)) { 55 | styleBo.setColor("background-color:" + bgColorStr + ";"); // 背景颜色 56 | } 57 | parseBorder(row, cell, bottomeRow, bottomeCol, 58 | cellStyle, palette, table, tr, td, styleBo); 59 | } 60 | 61 | /** 62 | * 解析边框样式 63 | * @param bo 64 | * @param s 65 | * @param row 66 | * @param cell 67 | * @param bottomeRow 68 | * @param bottome 69 | * @param cellStyle 70 | * @param palette 71 | * @param table 72 | * @param tr 73 | * @param td 74 | * @param styleBo 75 | * @throws Exception 76 | */ 77 | private void parseBorder( HSSFRow row, HSSFCell cell, HSSFRow bottomeRow, 78 | HSSFCell bottome, HSSFCellStyle cellStyle, HSSFPalette palette, 79 | ExcelTable table, ExcelTableTr tr, ExcelTableTd td, 80 | ExcelTableTdStyle styleBo) throws Exception { 81 | parseBorderTop(cellStyle,styleBo); 82 | parseBorderLeft(cellStyle,styleBo); 83 | parseBorderBottom(cell, row, bottomeRow, bottome, cellStyle, styleBo); 84 | parseBorderRight(cell, row, bottomeRow, bottome, cellStyle, styleBo); 85 | } 86 | 87 | private void parseBorderTop(HSSFCellStyle cellStyle, 88 | ExcelTableTdStyle styleBo) throws Exception { 89 | short bordertop = cellStyle.getBorderTop(); 90 | if (bordertop > 0) { 91 | short colortop = cellStyle.getTopBorderColor(); 92 | String boderstyler = ExcelUtils.getBorderStyle(bordertop, 93 | colortop); 94 | if (!StringsUtils.isEmpty(boderstyler)) { 95 | styleBo.setBorderTop("border-top:" + boderstyler + ";"); 96 | } 97 | } 98 | } 99 | 100 | private void parseBorderLeft(HSSFCellStyle cellStyle, 101 | ExcelTableTdStyle styleBo) throws Exception { 102 | short borderleft = cellStyle.getBorderLeft(); 103 | if (borderleft > 0) { 104 | short colorleft = cellStyle.getLeftBorderColor(); 105 | String boderstyler = ExcelUtils.getBorderStyle(borderleft, 106 | colorleft); 107 | if (!StringsUtils.isEmpty(boderstyler)) { 108 | styleBo.setBorderLeft("border-left:" + boderstyler + ";"); 109 | } 110 | } 111 | } 112 | 113 | private void parseBorderRight(HSSFCell cell, HSSFRow row, HSSFRow bottomeRow, Cell bottomCell, 114 | HSSFCellStyle cellStyle, ExcelTableTdStyle styleBo) throws Exception { 115 | if (bottomCell != null) { 116 | //跨行或跨列td 117 | CellStyle cs = bottomCell.getCellStyle(); 118 | if (cs != null) { 119 | short borderRight = cs.getBorderRight(); 120 | short colorRight = cs.getRightBorderColor(); 121 | String boderStyler = ExcelUtils.getBorderStyle(borderRight, 122 | colorRight); 123 | if (!StringsUtils.isEmpty(boderStyler)) { 124 | styleBo.setBorderRight("border-right:" + boderStyler + ";"); 125 | } 126 | } 127 | } else { 128 | //非跨行跨列td 129 | short borderRight = cellStyle.getBorderRight();//边框 130 | if (borderRight > 0) { 131 | short colorRight = cellStyle.getRightBorderColor();//边框颜色 132 | String boderStyler = ExcelUtils.getBorderStyle(borderRight, 133 | colorRight); 134 | if (!StringsUtils.isEmpty(boderStyler)) { 135 | styleBo.setBorderRight("border-right:" + boderStyler + ";"); 136 | } 137 | } 138 | } 139 | } 140 | 141 | private void parseBorderBottom(HSSFCell c, HSSFRow row, HSSFRow bottomeRow, HSSFCell bottomCell, 142 | HSSFCellStyle cellStyle, ExcelTableTdStyle styleBo) throws Exception { 143 | if (bottomCell != null) { 144 | //跨行或跨列td 145 | CellStyle cs = bottomCell.getCellStyle(); 146 | if (cs != null) { 147 | short borderbottom = cs.getBorderBottom(); 148 | short colorbottom = cs.getBottomBorderColor(); 149 | String boderstyler = ExcelUtils.getBorderStyle(borderbottom, 150 | colorbottom); 151 | if (!StringsUtils.isEmpty(boderstyler)) { 152 | styleBo.setBorderBottom("border-bottom:" + boderstyler 153 | + ";"); 154 | } 155 | } 156 | } else { 157 | //非跨行跨列td 158 | short borderbottom = cellStyle.getBorderBottom(); 159 | if (borderbottom > 0) { 160 | short colorbottom = cellStyle.getBottomBorderColor(); 161 | String boderstyler = ExcelUtils.getBorderStyle(borderbottom, 162 | colorbottom); 163 | if (!StringsUtils.isEmpty(boderstyler)) { 164 | styleBo.setBorderBottom("border-bottom:" + boderstyler 165 | + ";"); 166 | } 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/ExcelContentParse.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import java.util.Set; 4 | 5 | import com.codecraft.excel2html.config.ConvertConfig; 6 | import com.codecraft.excel2html.entity.ExcelTable; 7 | import com.codecraft.excel2html.entity.ExcelTableTd; 8 | import com.codecraft.excel2html.entity.ExcelTableTr; 9 | import com.codecraft.excel2html.utils.StringsUtils; 10 | import com.codecraft.excel2html.widget.IWidget; 11 | 12 | /** 13 | * excel内容解析器 14 | * @author zoro 15 | * 16 | */ 17 | public class ExcelContentParse implements IExcelContentParse{ 18 | /** 19 | * 解析html内容 (包含控件) 20 | */ 21 | @Override 22 | public String parseConten(ExcelTable table, ExcelTableTr tr, ExcelTableTd td) 23 | throws Exception { 24 | ConvertConfig config = table.getConfig(); 25 | Set allRegWidget = config.getDefaultRegWidget(); 26 | boolean view = config.getHtmlView(); 27 | String content = td.getContent().trim(); 28 | StringBuilder sb = new StringBuilder(); 29 | String widgetType = parseWidgetType(content); 30 | if(!StringsUtils.isEmpty(widgetType)){ 31 | for(IWidget widget : allRegWidget){ 32 | String result = ""; 33 | if(view){ 34 | result = widget.parseHtml4Edit(widgetType, sb, table, td); 35 | }else{ 36 | result = widget.parseHtml4View(widgetType, sb, table, td); 37 | } 38 | if(!"".equals(result)){ 39 | return result; 40 | }else{ 41 | return ""; 42 | } 43 | } 44 | } 45 | return content; 46 | } 47 | 48 | private String parseWidgetType(String content){ 49 | if(StringsUtils.isEmpty(content)){ 50 | return ""; 51 | } 52 | int startIndex = content.indexOf("${"); 53 | int endIndex = content.indexOf("}",startIndex); 54 | if(startIndex != -1 && endIndex != -1) { 55 | String widgetType = content.substring(startIndex + 2, endIndex); 56 | return widgetType; 57 | } 58 | return ""; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/ExcelParse4HSSF.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.InputStream; 6 | import java.text.DecimalFormat; 7 | import java.util.Set; 8 | 9 | import org.apache.poi.hssf.usermodel.HSSFCellStyle; 10 | import org.apache.poi.hssf.usermodel.HSSFFont; 11 | import org.apache.poi.hssf.usermodel.HSSFPalette; 12 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 13 | import org.apache.poi.hssf.util.HSSFColor; 14 | import org.apache.poi.ss.usermodel.Cell; 15 | import org.apache.poi.ss.usermodel.CellStyle; 16 | import org.apache.poi.ss.usermodel.Font; 17 | import org.apache.poi.ss.usermodel.Row; 18 | import org.apache.poi.ss.usermodel.Sheet; 19 | import org.apache.poi.ss.usermodel.Workbook; 20 | import org.apache.poi.ss.util.CellRangeAddress; 21 | 22 | import com.codecraft.excel2html.config.ConvertConfig; 23 | import com.codecraft.excel2html.entity.ExcelTable; 24 | import com.codecraft.excel2html.entity.ExcelTableTd; 25 | import com.codecraft.excel2html.entity.ExcelTableTdStyle; 26 | import com.codecraft.excel2html.entity.ExcelTableTr; 27 | import com.codecraft.excel2html.entity.RowColumnSpan; 28 | import com.codecraft.excel2html.utils.ExcelUtils; 29 | import com.codecraft.excel2html.utils.StringsUtils; 30 | 31 | /** 32 | * hssf excel的解析器 33 | * @author zoro 34 | * 35 | */ 36 | public class ExcelParse4HSSF implements IExcelParse { 37 | 38 | private ConvertConfig config = null; 39 | 40 | @Override 41 | public ExcelTable parse(InputStream input, ConvertConfig config) throws Exception{ 42 | this.config = config; 43 | return parse(input, 0, config); 44 | } 45 | 46 | @Override 47 | public ExcelTable parse(InputStream input, int sheetIndex, ConvertConfig config) throws Exception{ 48 | this.config = config; 49 | ExcelTable table = parseTable(input, sheetIndex); 50 | table.setConfig(config); 51 | return table; 52 | } 53 | 54 | /** 55 | * 解析table 56 | * @param input 57 | * @param sheetIndex 58 | * @return 59 | * @throws Exception 60 | */ 61 | public ExcelTable parseTable(InputStream input, int sheetIndex) throws Exception{ 62 | Workbook wk = ExcelUtils.getExcelWorkBook(input); 63 | HSSFWorkbook workbook = null; 64 | if(wk instanceof HSSFWorkbook){ 65 | workbook = (HSSFWorkbook)wk; 66 | }else{ 67 | throw new Exception("目前只支持HSSF格式!"); 68 | } 69 | Sheet sheet = workbook.getSheetAt(sheetIndex); 70 | int firstRowNum = sheet.getFirstRowNum(); 71 | int lastRowNum = sheet.getLastRowNum(); 72 | if (lastRowNum-firstRowNum > config.getMaxRowNum()) { 73 | // 行数不允许多于300 74 | Exception e = new Exception("行数不能超过" + config.getMaxRowNum() + "行!"); 75 | throw e; 76 | } 77 | ExcelTable table = new ExcelTable(); 78 | table.setFirstRowNum(firstRowNum);//设置起始行 79 | table.setLastRowNum(lastRowNum);//设置结束行 80 | 81 | parseTableTr(workbook, table, sheet);//解析table tr 82 | return table; 83 | } 84 | 85 | /** 86 | * 解析tr 87 | * @param workbook 88 | * @param table 89 | * @param sheet 90 | * @throws Exception 91 | */ 92 | private void parseTableTr(HSSFWorkbook workbook, ExcelTable table, 93 | Sheet sheet) throws Exception{ 94 | //解析跨行 跨列信息 95 | RowColumnSpan rowColumnSpan = parseRowColumnSpan(sheet); 96 | table.setRowColumnSpan(rowColumnSpan); 97 | int firstRow = sheet.getFirstRowNum(); 98 | int lastRowNum = sheet.getLastRowNum(); 99 | for (int rowNum = firstRow ; rowNum <= lastRowNum; rowNum++) { 100 | Row row = sheet.getRow(rowNum); 101 | ExcelTableTr tr = new ExcelTableTr(); 102 | if (row == null) { 103 | tr.setRowNum(rowNum); 104 | tr.setHeight("0px"); 105 | tr.setLastColNum(-1); 106 | tr.getTdMap().put(0, new ExcelTableTd()); 107 | table.getTrMap().put(rowNum, tr); 108 | }else{ 109 | //空白行会出现lastCellNum为-1 110 | if(row.getLastCellNum() == -1){ 111 | continue; 112 | } 113 | //设置实际的有效行 114 | if(row != null && table.getWidthRowNum() == -1){ 115 | table.setWidthRowNum(rowNum); 116 | } 117 | tr.setHeight((int)(row.getHeightInPoints() * 1.35) + "px"); 118 | parseTableTd(workbook, sheet, row, table, tr, rowColumnSpan); 119 | table.getTrMap().put(rowNum, tr); 120 | } 121 | } 122 | } 123 | 124 | /** 125 | * 解析td 126 | * @param workbook 127 | * @param sheet 128 | * @param row 129 | * @param table 130 | * @param tr 131 | * @param rowColumnSpanBo 132 | * @throws Exception 133 | */ 134 | private void parseTableTd(HSSFWorkbook workbook, Sheet sheet, Row row, 135 | ExcelTable table, ExcelTableTr tr, 136 | RowColumnSpan rowColumnSpanBo) throws Exception{ 137 | int rowNum = row.getRowNum(); 138 | int firstColNum = row.getFirstCellNum(); 139 | int lastColNum = row.getLastCellNum(); 140 | if (lastColNum - firstColNum > config.getMaxCellNum()) { 141 | // 列数不允许多于300 142 | Exception e = new Exception("excel列数不能超过" + config.getMaxCellNum() + "行!"); 143 | throw e; 144 | } 145 | Cell cell = null; 146 | tr.setLastColNum(lastColNum); 147 | for (int colNum = 0; colNum <= lastColNum; colNum++) { 148 | ExcelTableTd td = new ExcelTableTd(); 149 | td.setColNum(colNum); 150 | cell = row.getCell(colNum); 151 | if (cell == null) { 152 | td.setContent(" "); 153 | tr.getTdMap().put(colNum, td); 154 | continue; 155 | } 156 | int bottomeCol = -1; 157 | int bottomeRow = -1; 158 | //当前td是否跨行跨列 159 | if (rowColumnSpanBo.getRowColunmSpanMap().containsKey(rowNum + "," + colNum)) { 160 | String pointString = rowColumnSpanBo.getRowColunmSpanMap().get(rowNum + "," + colNum); 161 | rowColumnSpanBo.getRowColunmSpanMap().remove(rowNum + "," + colNum); 162 | bottomeRow = Integer.valueOf(pointString.split(",")[0]); 163 | bottomeCol = Integer.valueOf(pointString.split(",")[1]); 164 | 165 | int colSpan = bottomeCol - colNum + 1; 166 | //Please note, that this method works correctly only for workbooks with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). 167 | //If the default font is changed the column width can be streched 168 | double tdWidth = sheet.getColumnWidthInPixels(colNum); 169 | 170 | td.setWidth(tdWidth + "px"); 171 | td.setWidthNum(tdWidth); 172 | int rowSpan = bottomeRow - rowNum + 1; 173 | if (rowSpan != 1) { 174 | td.setRowspan(rowSpan + ""); 175 | } 176 | if (colSpan != 1) { 177 | td.setColspan(colSpan + ""); 178 | } 179 | }else { 180 | //如果输出的宽度有问题,那么肯定是设置的默认字体大小的问题 181 | double tdwidth = sheet.getColumnWidthInPixels(colNum); 182 | td.setWidth(tdwidth + "px"); 183 | } 184 | parseTdStyle(workbook, sheet, row, cell, bottomeRow, bottomeCol, 185 | table, tr, td); 186 | //解析内容 187 | String content =getCellContent(cell); 188 | td.setContent(content); 189 | tr.getTdMap().put(colNum, td); 190 | } 191 | } 192 | 193 | /** 194 | * 获得cell内容 195 | * @param cell 196 | * @return 197 | * @throws Exception 198 | */ 199 | private String getCellContent(Cell cell) throws Exception { 200 | switch (cell.getCellType()) { 201 | case Cell.CELL_TYPE_STRING://string 202 | String str = cell.getStringCellValue(); 203 | if (str==null || "".equals(str)) { 204 | return " "; 205 | } else { 206 | str = str.replaceAll(String.valueOf(' ')," "); 207 | str = str.replaceAll(String.valueOf('<'), "<"); 208 | str = str.replaceAll(String.valueOf('>'), ">"); 209 | str = str.replaceAll(String.valueOf('\n'), "
"); 210 | return str; 211 | } 212 | case Cell.CELL_TYPE_NUMERIC://numeric 213 | //去掉整数后的'.0' 214 | DecimalFormat format = new DecimalFormat("#0.##"); 215 | String result = format.format(cell.getNumericCellValue()); 216 | return result; 217 | case Cell.CELL_TYPE_BOOLEAN://boolean 218 | return cell.getBooleanCellValue() +""; 219 | case Cell.CELL_TYPE_FORMULA: // 公式 220 | return "FORMULA"; 221 | case Cell.CELL_TYPE_BLANK://blank 222 | return ""; 223 | case Cell.CELL_TYPE_ERROR: //error 224 | return "ERROR"; 225 | default: 226 | return ""; 227 | } 228 | } 229 | 230 | /** 231 | * 解析td样式 232 | * @param workbook 233 | * @param sheet 234 | * @param row 235 | * @param cell 236 | * @param bottomeRow 237 | * @param bottomeCol 238 | * @param table 239 | * @param tr 240 | * @param td 241 | * @throws Exception 242 | */ 243 | private void parseTdStyle(HSSFWorkbook workbook, Sheet sheet, Row row, Cell cell, int bottomeRow, 244 | int bottomeCol, ExcelTable table, ExcelTableTr tr, 245 | ExcelTableTd td) throws Exception{ 246 | ExcelTableTdStyle styleBo = new ExcelTableTdStyle(); 247 | CellStyle cellStyle = cell.getCellStyle(); 248 | cellStyle.setWrapText(true); 249 | //解析字体 250 | parseFontStyle(workbook, td, styleBo, cellStyle); 251 | //解析对齐方式 252 | parseTdAlign(workbook, sheet, row, cell, td, cellStyle); 253 | //解析边框样式 254 | config.getExcelStyleParse().parseStyle(workbook, sheet, row, cell, bottomeRow, bottomeCol, cellStyle, table, tr, td, styleBo); 255 | td.setTdStyle(styleBo); 256 | } 257 | 258 | /** 259 | * 解析字体样式(fontColor,fontHeight,fontName,fontItalic) 260 | * @param workbook 261 | * @param td 262 | * @param styleBo 263 | * @param cellStyle 264 | */ 265 | private void parseFontStyle(HSSFWorkbook workbook, ExcelTableTd td, 266 | ExcelTableTdStyle styleBo, CellStyle cellStyle) { 267 | short fontIndex = cellStyle.getFontIndex(); 268 | Font font = workbook.getFontAt(fontIndex); 269 | HSSFPalette palette = ((HSSFWorkbook)workbook).getCustomPalette(); 270 | HSSFColor hc = palette.getColor(font.getColor()); 271 | String fontColorStr = ExcelUtils.convertToStardColor(hc); 272 | styleBo.setFontColor(fontColorStr) ;//字体颜色 273 | styleBo.setFontHeight(String.valueOf(font.getFontHeightInPoints()+"pt;"));//字体大小 274 | styleBo.setFontName(font.getFontName());//字体 (宋体,黑体) 275 | styleBo.setFontItalic(String.valueOf(font.getItalic()));//是否斜体 276 | 277 | String fontStr = parseFont(workbook,(HSSFCellStyle)cellStyle,palette,td); 278 | styleBo.setFont(fontStr); 279 | } 280 | 281 | /** 282 | * 解析字体样式(font-size,font-family,font-weight,font-style,color) 283 | * @param workbook 284 | * @param row 285 | * @param c 286 | * @param cellStyle 287 | * @param palette 288 | * @param td 289 | * @return 290 | * @throws Exception 291 | */ 292 | private String parseFont(HSSFWorkbook workbook, HSSFCellStyle cellStyle, 293 | HSSFPalette palette, ExcelTableTd td){ 294 | StringBuilder sb = new StringBuilder(); 295 | HSSFFont hf = cellStyle.getFont(workbook); 296 | short fontColor = hf.getColor(); 297 | HSSFColor hc = palette.getColor(fontColor); 298 | if (hf.getFontHeightInPoints() > 0) { 299 | sb.append("font-size: " + hf.getFontHeightInPoints() + "pt;"); 300 | td.setFontSize(hf.getFontHeightInPoints()); 301 | } 302 | if (!StringsUtils.isEmpty(hf.getFontName())) { 303 | sb.append("font-family:" + hf.getFontName() + ";"); 304 | } 305 | if (hf.getBoldweight() > 0) { 306 | sb.append("font-weight:" + hf.getBoldweight() + ";"); 307 | } 308 | if (hf.getItalic()) { 309 | sb.append("font-style:italic;"); 310 | } 311 | String fontColorStr = ExcelUtils.convertToStardColor(hc); 312 | if (fontColorStr != null && !"".equals(fontColorStr.trim())) { 313 | sb.append("color:" + fontColorStr + ";"); // 字体颜色 314 | } 315 | return sb.toString(); 316 | } 317 | 318 | /** 319 | * 解析对齐方式 320 | * @param workbook 321 | * @param sheet 322 | * @param row 323 | * @param cell 324 | * @param td 325 | * @param cellStyle 326 | * @throws Exception 327 | */ 328 | private void parseTdAlign(HSSFWorkbook workbook, Sheet sheet, Row row, 329 | Cell cell, ExcelTableTd td, CellStyle cellStyle) throws Exception { 330 | if (cellStyle != null) { 331 | //td align 332 | String tdAlign = alignment2Html( workbook, sheet, row, cell, cellStyle); 333 | td.setTdAlign(tdAlign); 334 | //text align 335 | String textAlign = getTextAlign2Html(workbook, sheet, row, cell, cellStyle); 336 | td.setTextAlign(textAlign); 337 | //ver Align 338 | String vAlign = getVerAlign2Html(workbook, sheet, row, cell, cellStyle); 339 | td.setVerAlign(vAlign); 340 | } 341 | } 342 | /** 343 | * 获取垂直对齐方式 344 | * @param workbook 345 | * @param sheet 346 | * @param row 347 | * @param cell 348 | * @param cellStyle 349 | * @return 350 | */ 351 | private String getVerAlign2Html(Workbook workbook, Sheet sheet, Row row, Cell cell, 352 | CellStyle cellStyle) { 353 | String vAlign = "right"; 354 | short verticalAlignment = cellStyle.getVerticalAlignment(); 355 | if (verticalAlignment > 0) { 356 | vAlign = ExcelUtils.convertVerticalAlignToHtml(verticalAlignment); 357 | } 358 | return vAlign; 359 | } 360 | 361 | /** 362 | * 获取文本对齐方式 363 | * @param workbook 364 | * @param sheet 365 | * @param row 366 | * @param cell 367 | * @param cellStyle 368 | * @return 369 | */ 370 | private String getTextAlign2Html(Workbook workbook, Sheet sheet, Row row, Cell cell, 371 | CellStyle cellStyle) { 372 | String textAlign = "right"; 373 | if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { 374 | short alignment = cellStyle.getAlignment(); 375 | if (cellStyle.getAlignment() > 0) { 376 | textAlign = ExcelUtils.convertAlignToHtml(alignment); 377 | } 378 | } else { 379 | short alignment = cellStyle.getAlignment(); 380 | if (cellStyle.getAlignment() > 0) { 381 | textAlign = ExcelUtils.convertAlignToHtml(alignment); 382 | } 383 | } 384 | return textAlign; 385 | } 386 | 387 | /** 388 | * 获取水平对齐方式 389 | * @param workbook 390 | * @param sheet 391 | * @param row 392 | * @param cell 393 | * @param cellStyle 394 | * @return 395 | * @throws Exception 396 | */ 397 | private String alignment2Html(Workbook workbook, 398 | Sheet sheet, Row row, Cell cell, CellStyle cellStyle) 399 | throws Exception { 400 | StringBuffer sb = new StringBuffer(); 401 | if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { 402 | short alignment = cellStyle.getAlignment(); 403 | if (cellStyle.getAlignment() > 0) { 404 | sb.append(" align='" + ExcelUtils.convertAlignToHtml(alignment) + "'"); 405 | } else { 406 | sb.append(" align='right'"); 407 | } 408 | } else { 409 | short alignment = cellStyle.getAlignment(); 410 | if (cellStyle.getAlignment() > 0) { 411 | sb.append(" align='" + ExcelUtils.convertAlignToHtml(alignment) + "'"); 412 | } 413 | } 414 | short verticalAlignment = cellStyle.getVerticalAlignment(); 415 | //垂直居中居上时,verticalAlignment为0 416 | if (verticalAlignment > -1) { 417 | sb.append(" valign='" 418 | + ExcelUtils.convertVerticalAlignToHtml(verticalAlignment) + "' "); 419 | } 420 | return sb.toString(); 421 | } 422 | 423 | /** 424 | * 解析跨行 跨列信息 425 | * @param sheet 426 | * @return 427 | */ 428 | private RowColumnSpan parseRowColumnSpan(Sheet sheet) { 429 | RowColumnSpan bo = new RowColumnSpan(); 430 | int mergedRegions = sheet.getNumMergedRegions(); 431 | for (int i = 0; i < mergedRegions; i++) { 432 | CellRangeAddress range = sheet.getMergedRegion(i); 433 | int topRow = range.getFirstRow(); 434 | int topCol = range.getFirstColumn(); 435 | int bottomRow = range.getLastRow(); 436 | int bottomCol = range.getLastColumn(); 437 | bo.getRowColunmSpanMap().put(topRow + "," + topCol, bottomRow + "," + bottomCol); 438 | 439 | Set filter = bo.getRowColunmSpanFilter(); 440 | for(int m = topRow; m <= bottomRow; m++){ 441 | for(int n = topCol; n <= bottomCol; n++){ 442 | if(m == topRow && n == topCol){ 443 | continue; 444 | }else{ 445 | filter.add(m + "," + n); 446 | } 447 | } 448 | } 449 | } 450 | return bo; 451 | } 452 | 453 | //test excel width 454 | public static void main(String[] args) throws Exception { 455 | FileInputStream fis = new FileInputStream(new File("C:/Temp/test.xls")); 456 | HSSFWorkbook workbook = (HSSFWorkbook)ExcelUtils.getExcelWorkBook(fis); 457 | Sheet sheet = workbook.getSheetAt(0); 458 | 459 | int firstNum = sheet.getFirstRowNum(); 460 | int lastNum = sheet.getLastRowNum(); 461 | 462 | for(int i = firstNum; i <= lastNum; i++ ){ 463 | Row row = sheet.getRow(i); 464 | 465 | int firstCellNum = row.getFirstCellNum(); 466 | int lastCellNum = row.getLastCellNum(); 467 | 468 | for(int j = firstCellNum; j <= lastCellNum; j++){ 469 | float width = sheet.getColumnWidthInPixels(j); 470 | System.out.println("第" + i + "行,第" + j + "列宽度:" + width); 471 | } 472 | } 473 | workbook.close(); 474 | } 475 | } 476 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/ExcelPicParse4HSSF.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import java.util.ArrayList; 4 | 5 | import java.util.Iterator; 6 | import java.util.List; 7 | 8 | import org.apache.poi.ddf.EscherClientAnchorRecord; 9 | import org.apache.poi.ddf.EscherRecord; 10 | import org.apache.poi.hssf.record.EscherAggregate; 11 | import org.apache.poi.hssf.usermodel.HSSFPictureData; 12 | import org.apache.poi.hssf.usermodel.HSSFSheet; 13 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 14 | 15 | import com.codecraft.excel2html.entity.ExcelPicture; 16 | import com.codecraft.excel2html.entity.ExcelTable; 17 | 18 | /** 19 | * 图片解析器 20 | * @author zoro 21 | * 22 | */ 23 | public class ExcelPicParse4HSSF implements IExcelPicParse { 24 | 25 | private static class ClientAnchorInfo { 26 | public HSSFSheet sheet; 27 | public EscherClientAnchorRecord clientAnchorRecord; 28 | 29 | public ClientAnchorInfo(HSSFSheet sheet, EscherClientAnchorRecord clientAnchorRecord) { 30 | super(); 31 | this.sheet = sheet; 32 | this.clientAnchorRecord = clientAnchorRecord; 33 | } 34 | } 35 | 36 | @Override 37 | public void parsePic(HSSFWorkbook workbook, ExcelTable table) throws Exception { 38 | //处理图片 39 | List list = new ArrayList(); 40 | 41 | HSSFWorkbook hssfWorkbook = (HSSFWorkbook)workbook; 42 | List pictureList = hssfWorkbook.getAllPictures(); 43 | List clientAnchorRecords = getClientAnchorRecords((HSSFWorkbook)workbook); 44 | 45 | if (pictureList.size() != clientAnchorRecords.size()) { 46 | throw new Exception("图片数量不一致!"); 47 | } 48 | 49 | for (int i = 0; i < pictureList.size(); i++) { 50 | HSSFPictureData pictureData = pictureList.get(i); 51 | 52 | ClientAnchorInfo anchor = clientAnchorRecords.get(i); 53 | HSSFSheet she = anchor.sheet; 54 | //获得图片sheet号,以便图片排序 55 | int curSheetIndex = workbook.getSheetIndex(she); 56 | EscherClientAnchorRecord clientAnchorRecord = anchor.clientAnchorRecord; 57 | list.add(new ExcelPicture((HSSFWorkbook)workbook, she, pictureData, clientAnchorRecord,curSheetIndex)); 58 | } 59 | if(list.size()!=0){ 60 | table.setPicList(list); 61 | } 62 | } 63 | 64 | private static List getClientAnchorRecords(HSSFWorkbook workbook) { 65 | List list = new ArrayList(); 66 | EscherAggregate drawingAggregate = null; 67 | HSSFSheet sheet = null; 68 | List recordList = null; 69 | Iterator recordIter = null; 70 | int numSheets = workbook.getNumberOfSheets(); 71 | for(int i = 0; i < numSheets; i++) { 72 | sheet = workbook.getSheetAt(i); 73 | drawingAggregate = sheet.getDrawingEscherAggregate(); 74 | if(drawingAggregate != null) { 75 | recordList = drawingAggregate.getEscherRecords(); 76 | recordIter = recordList.iterator(); 77 | while(recordIter.hasNext()) { 78 | getClientAnchorRecords(sheet, recordIter.next(), 1, list); 79 | } 80 | } 81 | } 82 | return list; 83 | } 84 | 85 | private static void getClientAnchorRecords(HSSFSheet sheet, EscherRecord escherRecord, int level, List list) { 86 | List recordList = null; 87 | Iterator recordIter = null; 88 | EscherRecord childRecord = null; 89 | recordList = escherRecord.getChildRecords(); 90 | recordIter = recordList.iterator(); 91 | while(recordIter.hasNext()) { 92 | childRecord = recordIter.next(); 93 | if(childRecord instanceof EscherClientAnchorRecord) { 94 | ClientAnchorInfo e = new ClientAnchorInfo(sheet, (EscherClientAnchorRecord) childRecord); 95 | list.add(e); 96 | } 97 | if(childRecord.getChildRecords().size() > 0) { 98 | getClientAnchorRecords(sheet, childRecord, level+1, list); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/IExcelCellStyleParse.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import org.apache.poi.ss.usermodel.Cell; 4 | import org.apache.poi.ss.usermodel.CellStyle; 5 | import org.apache.poi.ss.usermodel.Row; 6 | import org.apache.poi.ss.usermodel.Sheet; 7 | import org.apache.poi.ss.usermodel.Workbook; 8 | 9 | import com.codecraft.excel2html.entity.ExcelTable; 10 | import com.codecraft.excel2html.entity.ExcelTableTd; 11 | import com.codecraft.excel2html.entity.ExcelTableTdStyle; 12 | import com.codecraft.excel2html.entity.ExcelTableTr; 13 | /** 14 | * excel样式解析器(字体,颜色,边框,对齐方式) 15 | * @author zoro 16 | * 17 | */ 18 | public interface IExcelCellStyleParse { 19 | public void parseStyle(Workbook workbook, Sheet sheet, Row row, Cell cell, 20 | int bottomeRow, int bottomeCol, CellStyle cellStyle, 21 | ExcelTable table, ExcelTableTr tr, ExcelTableTd td, ExcelTableTdStyle styleBo) 22 | throws Exception; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/IExcelContentParse.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | import com.codecraft.excel2html.entity.ExcelTableTr; 6 | 7 | public interface IExcelContentParse { 8 | public String parseConten(ExcelTable table, ExcelTableTr tr, 9 | ExcelTableTd td) throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/IExcelParse.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import java.io.InputStream; 4 | 5 | import com.codecraft.excel2html.config.ConvertConfig; 6 | import com.codecraft.excel2html.entity.ExcelTable; 7 | /** 8 | * excel解析器 9 | * @author zoro 10 | * 11 | */ 12 | public interface IExcelParse { 13 | public ExcelTable parse(InputStream input, ConvertConfig config) throws Exception; 14 | 15 | public ExcelTable parse(InputStream input,int sheetIndex, ConvertConfig config) throws Exception; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/parse/IExcelPicParse.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.parse; 2 | 3 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 4 | 5 | import com.codecraft.excel2html.entity.ExcelTable; 6 | 7 | /** 8 | * excel图片解析器 9 | * @author zoro 10 | * 11 | */ 12 | public interface IExcelPicParse { 13 | public void parsePic(HSSFWorkbook workbook, ExcelTable table) throws Exception; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/picUpload/IExcelPicUpload.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.picUpload; 2 | 3 | /** 4 | * excel图片上传 5 | * @author zoro 6 | * 7 | */ 8 | public interface IExcelPicUpload { 9 | public String loadPic(byte[] data) throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/utils/ExcelUtils.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.utils; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 7 | import org.apache.poi.hssf.util.HSSFColor; 8 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 9 | import org.apache.poi.ss.usermodel.CellStyle; 10 | import org.apache.poi.ss.usermodel.Sheet; 11 | import org.apache.poi.ss.usermodel.Workbook; 12 | import org.apache.poi.ss.usermodel.WorkbookFactory; 13 | 14 | import com.codecraft.excel2html.entity.ExcelTable; 15 | import com.codecraft.excel2html.entity.ExcelTableTd; 16 | import com.codecraft.excel2html.entity.ExcelTableTr; 17 | 18 | /** 19 | * excel工具类 20 | * @author zoro 21 | * 22 | */ 23 | public class ExcelUtils { 24 | /* 25 | * 用于将excel表格中列索引转成列号字母,从A对应1开始 26 | */ 27 | public static String indexToColumn(int index) { 28 | if(index <= 0){ 29 | try{ 30 | throw new Exception("Invalid parameter"); 31 | }catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | index--; 36 | String column = ""; 37 | do{ 38 | if(column.length() > 0) { 39 | index--; 40 | } 41 | column = ((char) (index % 26 + (int) 'A')) + column; 42 | index = (int) ((index - index % 26) / 26); 43 | }while(index>0); 44 | return column; 45 | } 46 | 47 | /* 48 | * 计算合并列的宽度度(单位为px) 49 | */ 50 | public static double getTdSpanWidth(Sheet sheet, int startCol, int endCol) { 51 | double tdwidth = 0; 52 | for (int i = startCol; i <= endCol; i++) { 53 | double tempwidth = sheet.getColumnWidthInPixels(i);//获得px像素 54 | tdwidth = tdwidth + tempwidth; 55 | 56 | } 57 | return tdwidth; 58 | } 59 | 60 | /* 61 | * 计算合并列的高度 62 | */ 63 | public static int getTdSpanHeight(Sheet sheet, int startRow, int endRow) { 64 | int tdHeight = 0; 65 | for (int i = startRow; i <= endRow; i++) { 66 | int tempHeight = sheet.getRow(i).getHeight() / 32; 67 | tdHeight = tdHeight + tempHeight; 68 | } 69 | return tdHeight; 70 | } 71 | 72 | /* 73 | * 计算合并列的高度 74 | */ 75 | public static String getTdSpanHeight(ExcelTable table, ExcelTableTr tr, 76 | ExcelTableTd td) { 77 | int rowspan = 0; 78 | if(!"".equals(td.getRowspan())){ 79 | rowspan = Integer.parseInt(td.getRowspan()); 80 | } 81 | //计算合并单元格的高度 82 | int height = Integer.parseInt(tr.getHeight().substring(0, tr.getHeight().indexOf("px"))); 83 | if(rowspan > 1){ 84 | int thisIndex = tr.getRowNum(); 85 | for(int i=1; i < rowspan; i++){ 86 | ExcelTableTr trBo = table.getTrMap().get(thisIndex + i); 87 | if(trBo != null){ 88 | height+=Integer.parseInt(trBo.getHeight().substring(0, trBo.getHeight().indexOf("px"))); 89 | } 90 | } 91 | } 92 | return height + "px"; 93 | } 94 | 95 | /** 96 | * 根据文件的路径创建Workbook对象 97 | * 98 | * @param filePath 99 | * @throws IOException 100 | * @throws InvalidFormatException 101 | * @throws Exception 102 | */ 103 | public static Workbook getExcelWorkBook(InputStream ins) throws Exception { 104 | Workbook book = null; 105 | try { 106 | book = WorkbookFactory.create(ins); 107 | }catch(IllegalArgumentException e){ 108 | throw new Exception("Excel打开出错!"); 109 | } 110 | return book; 111 | } 112 | 113 | /** 114 | * 判断Excel版本 115 | * @param filePath 116 | * @return 117 | */ 118 | public static boolean isExcelHSSF(InputStream input) { 119 | Workbook workbook = null; 120 | try { 121 | workbook = new HSSFWorkbook(input); 122 | } catch (Exception e) { 123 | return false; 124 | } finally{ 125 | if(workbook != null){ 126 | try { 127 | workbook.close(); 128 | } catch (IOException e) { 129 | e.printStackTrace(); 130 | } 131 | } 132 | } 133 | return true; 134 | } 135 | 136 | /** 137 | * 转换为标准颜色 138 | * @param hc 139 | * @return 140 | */ 141 | public static String convertToStardColor(HSSFColor hc) { 142 | StringBuffer sb = new StringBuffer(""); 143 | if (hc != null) { 144 | if (HSSFColor.AUTOMATIC.index == hc.getIndex()) { 145 | return null; 146 | } 147 | sb.append("#"); 148 | for (int i = 0; i < hc.getTriplet().length; i++) { 149 | sb.append(fillWithZero(Integer.toHexString(hc 150 | .getTriplet()[i]))); 151 | } 152 | } 153 | return sb.toString(); 154 | } 155 | 156 | /** 157 | * 十六进制补0 158 | * @param str 159 | * @return 160 | */ 161 | public static String fillWithZero(String str) { 162 | if (str != null && str.length() < 2) { 163 | return "0" + str; 164 | } 165 | return str; 166 | } 167 | 168 | /** 169 | * 单元格水平对齐 170 | * @param alignment 171 | * @return 172 | */ 173 | public static String convertAlignToHtml(short alignment) { 174 | String align = ""; 175 | switch (alignment) { 176 | case CellStyle.ALIGN_LEFT: 177 | align = "left"; 178 | break; 179 | case CellStyle.ALIGN_CENTER: 180 | align = "center"; 181 | break; 182 | case CellStyle.ALIGN_RIGHT: 183 | align = "right"; 184 | break; 185 | default: 186 | break; 187 | } 188 | return align; 189 | } 190 | 191 | /** 192 | * 单元格垂直对齐 193 | * @param verticalAlignment 194 | * @return 195 | */ 196 | public static String convertVerticalAlignToHtml(short verticalAlignment) { 197 | String valign = ""; 198 | switch (verticalAlignment) { 199 | case CellStyle.VERTICAL_BOTTOM: 200 | valign = "bottom"; 201 | break; 202 | case CellStyle.VERTICAL_CENTER: 203 | valign = "middle"; 204 | break; 205 | case CellStyle.VERTICAL_TOP: 206 | valign = "top"; 207 | break; 208 | case CellStyle.VERTICAL_JUSTIFY: 209 | valign = "baseline"; 210 | break; 211 | default: 212 | break; 213 | } 214 | return valign; 215 | } 216 | 217 | /** 218 | * 获取border样式 219 | * @param borderType 220 | * @param colorType 221 | * @return 222 | */ 223 | public static String getBorderStyle(short borderType, short colorType) { 224 | String html = "none"; 225 | switch (borderType) { 226 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_NONE: 227 | html = "none"; 228 | break; 229 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_THIN: 230 | html = "1px solid " + getBorderColor(colorType); 231 | break; 232 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_MEDIUM: 233 | html = "2px solid " + getBorderColor(colorType); 234 | break; 235 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_DASHED: 236 | html = "1px dashed " + getBorderColor(colorType); 237 | break; 238 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_HAIR: 239 | html = "1px solid " + getBorderColor(colorType); 240 | break; 241 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_THICK: 242 | html = "5px solid " + getBorderColor(colorType); 243 | break; 244 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_DOUBLE: 245 | html = "double solid " + getBorderColor(colorType); 246 | break; 247 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_DOTTED: 248 | html = "1px dotted " + getBorderColor(colorType); 249 | break; 250 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_MEDIUM_DASHED: 251 | html = "3px dashed " + getBorderColor(colorType); 252 | break; 253 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_DASH_DOT: 254 | html = "1px solid " + getBorderColor(colorType); 255 | break; 256 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_MEDIUM_DASH_DOT: 257 | html = "3px solid " + getBorderColor(colorType); 258 | break; 259 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_DASH_DOT_DOT: 260 | html = "1px solid " + getBorderColor(colorType); 261 | break; 262 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_MEDIUM_DASH_DOT_DOT: 263 | html = "3px solid " + getBorderColor(colorType); 264 | break; 265 | case org.apache.poi.ss.usermodel.CellStyle.BORDER_SLANTED_DASH_DOT: 266 | html = "1px solid " + getBorderColor(colorType); 267 | break; 268 | default: 269 | break; 270 | } 271 | return html; 272 | } 273 | 274 | /** 275 | * 获取border颜色 276 | * @param bordercolor 277 | * @return 278 | */ 279 | public static String getBorderColor(short bordercolor) { 280 | String type = "black"; 281 | switch (bordercolor) { 282 | case org.apache.poi.hssf.util.HSSFColor.AUTOMATIC.index: 283 | type = "black"; 284 | break; 285 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_CORNFLOWER_BLUE.index: 286 | type = "black"; 287 | break; 288 | case org.apache.poi.hssf.util.HSSFColor.ROYAL_BLUE.index: 289 | type = "black"; 290 | break; 291 | case org.apache.poi.hssf.util.HSSFColor.CORAL.index: 292 | type = "coral"; 293 | break; 294 | case org.apache.poi.hssf.util.HSSFColor.ORCHID.index: 295 | type = "black"; 296 | break; 297 | case org.apache.poi.hssf.util.HSSFColor.MAROON.index: 298 | type = "black"; 299 | break; 300 | case org.apache.poi.hssf.util.HSSFColor.LEMON_CHIFFON.index: 301 | type = "black"; 302 | break; 303 | case org.apache.poi.hssf.util.HSSFColor.CORNFLOWER_BLUE.index: 304 | type = "black"; 305 | break; 306 | case org.apache.poi.hssf.util.HSSFColor.WHITE.index: 307 | type = "black"; 308 | break; 309 | case org.apache.poi.hssf.util.HSSFColor.LAVENDER.index: 310 | type = "black"; 311 | break; 312 | case org.apache.poi.hssf.util.HSSFColor.PALE_BLUE.index: 313 | type = "black"; 314 | break; 315 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_TURQUOISE.index: 316 | type = "black"; 317 | break; 318 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_GREEN.index: 319 | type = "black"; 320 | break; 321 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_YELLOW.index: 322 | type = "black"; 323 | break; 324 | case org.apache.poi.hssf.util.HSSFColor.TAN.index: 325 | type = "tan"; 326 | break; 327 | case org.apache.poi.hssf.util.HSSFColor.ROSE.index: 328 | type = "rose"; 329 | break; 330 | case org.apache.poi.hssf.util.HSSFColor.GREY_25_PERCENT.index: 331 | type = "black"; 332 | break; 333 | case org.apache.poi.hssf.util.HSSFColor.PLUM.index: 334 | type = "black"; 335 | break; 336 | case org.apache.poi.hssf.util.HSSFColor.SKY_BLUE.index: 337 | type = "blue"; 338 | break; 339 | case org.apache.poi.hssf.util.HSSFColor.TURQUOISE.index: 340 | type = "black"; 341 | break; 342 | case org.apache.poi.hssf.util.HSSFColor.BRIGHT_GREEN.index: 343 | type = "black"; 344 | break; 345 | case org.apache.poi.hssf.util.HSSFColor.YELLOW.index: 346 | type = "yellow"; 347 | break; 348 | case org.apache.poi.hssf.util.HSSFColor.GOLD.index: 349 | type = "gold"; 350 | break; 351 | case org.apache.poi.hssf.util.HSSFColor.PINK.index: 352 | type = "black"; 353 | break; 354 | case org.apache.poi.hssf.util.HSSFColor.GREY_40_PERCENT.index: 355 | type = "black"; 356 | break; 357 | case org.apache.poi.hssf.util.HSSFColor.VIOLET.index: 358 | type = "black"; 359 | break; 360 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_BLUE.index: 361 | type = "black"; 362 | break; 363 | case org.apache.poi.hssf.util.HSSFColor.AQUA.index: 364 | type = "black"; 365 | break; 366 | case org.apache.poi.hssf.util.HSSFColor.SEA_GREEN.index: 367 | type = "black"; 368 | break; 369 | case org.apache.poi.hssf.util.HSSFColor.LIME.index: 370 | type = "black"; 371 | break; 372 | case org.apache.poi.hssf.util.HSSFColor.LIGHT_ORANGE.index: 373 | type = "black"; 374 | break; 375 | case org.apache.poi.hssf.util.HSSFColor.RED.index: 376 | type = "red"; 377 | break; 378 | case org.apache.poi.hssf.util.HSSFColor.GREY_50_PERCENT.index: 379 | type = "black"; 380 | break; 381 | case org.apache.poi.hssf.util.HSSFColor.BLUE_GREY.index: 382 | type = "grey"; 383 | break; 384 | case org.apache.poi.hssf.util.HSSFColor.BLUE.index: 385 | type = "blue"; 386 | break; 387 | case org.apache.poi.hssf.util.HSSFColor.TEAL.index: 388 | type = "black"; 389 | break; 390 | case org.apache.poi.hssf.util.HSSFColor.GREEN.index: 391 | type = "green"; 392 | break; 393 | case org.apache.poi.hssf.util.HSSFColor.DARK_YELLOW.index: 394 | type = "black"; 395 | break; 396 | case org.apache.poi.hssf.util.HSSFColor.ORANGE.index: 397 | type = "orange"; 398 | break; 399 | case org.apache.poi.hssf.util.HSSFColor.DARK_RED.index: 400 | type = "black"; 401 | break; 402 | case org.apache.poi.hssf.util.HSSFColor.GREY_80_PERCENT.index: 403 | type = "black"; 404 | break; 405 | case org.apache.poi.hssf.util.HSSFColor.INDIGO.index: 406 | type = "black"; 407 | break; 408 | case org.apache.poi.hssf.util.HSSFColor.DARK_BLUE.index: 409 | type = "black"; 410 | break; 411 | case org.apache.poi.hssf.util.HSSFColor.DARK_TEAL.index: 412 | type = "black"; 413 | break; 414 | case org.apache.poi.hssf.util.HSSFColor.DARK_GREEN.index: 415 | type = "black"; 416 | break; 417 | case org.apache.poi.hssf.util.HSSFColor.OLIVE_GREEN.index: 418 | type = "black"; 419 | break; 420 | case org.apache.poi.hssf.util.HSSFColor.BROWN.index: 421 | type = "brown"; 422 | break; 423 | case org.apache.poi.hssf.util.HSSFColor.BLACK.index: 424 | type = "black"; 425 | break; 426 | default: 427 | break; 428 | } 429 | return type; 430 | } 431 | } 432 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/utils/StringsUtils.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | import org.omg.CORBA.SystemException; 13 | 14 | /** 15 | * 字符串工具 16 | * 17 | * @author xieshh 18 | * 19 | */ 20 | public class StringsUtils { 21 | 22 | /** 23 | * 字串是否为null 24 | * 25 | * @param str 26 | * @return 27 | */ 28 | public static final boolean isNull(String str) { 29 | String temStr = str; 30 | if (str != null) { 31 | temStr = str.trim(); 32 | if (!"NULL".equals(temStr.toUpperCase())) { 33 | return false; 34 | } 35 | } 36 | return true; 37 | } 38 | 39 | /** 40 | * 从字串中找一个字符的地址 41 | * 42 | * @param str 43 | * @return 44 | */ 45 | public static final int indexOf(String str, int offset, char c, 46 | boolean fromLeft) { 47 | if (fromLeft) { 48 | return str.indexOf(c, offset); 49 | } else { 50 | byte bytes[] = str.getBytes(); 51 | int i = offset - 1; 52 | for (; i >= 0; i--) { 53 | if (bytes[i] == c) { 54 | break; 55 | } 56 | } 57 | return i; 58 | 59 | } 60 | } 61 | 62 | /** 63 | * 把从start到end用desc替换掉 64 | * 65 | * @param src 66 | * @param start 67 | * @param end 68 | * @param desc 69 | * @return 70 | */ 71 | public static final String replaceAll(String src, int start, int end, 72 | String desc) { 73 | 74 | byte srcBytes[] = src.getBytes(); 75 | byte descBytes[] = desc.getBytes(); 76 | byte tBytes[] = new byte[srcBytes.length + descBytes.length 77 | - (end - start)]; 78 | for (int i = 0; i < start; i++) { 79 | tBytes[i] = srcBytes[i]; 80 | } 81 | for (int i = 0; i < descBytes.length; i++) { 82 | tBytes[i + start] = descBytes[i]; 83 | } 84 | for (int i = end; i < srcBytes.length; i++) { 85 | tBytes[i - end + start + descBytes.length] = srcBytes[i]; 86 | } 87 | return new String(tBytes); 88 | } 89 | 90 | /** 91 | * 把str从start到end的src用desc替换掉 92 | * 93 | * @param src 94 | * @param start 95 | * @param end 96 | * @param desc 97 | * @return 98 | */ 99 | public static final String replaceAll(String str, String src, int start, 100 | int end, String desc) { 101 | 102 | char srcBytes[] = src.toCharArray(); 103 | char descBytes[] = desc.toCharArray(); 104 | char strBytes[] = str.toCharArray(); 105 | StringBuilder sb = new StringBuilder(); 106 | for (int i = start; i < end && i < strBytes.length; i++) { 107 | char tempByte = strBytes[i]; 108 | // 如果符合条件,同替换处理 109 | if (equals(strBytes, i, srcBytes)) { 110 | i += srcBytes.length - 1; 111 | sb.append(descBytes); 112 | } else { 113 | sb.append(tempByte); 114 | } 115 | } 116 | return sb.toString(); 117 | } 118 | 119 | /** 120 | * 把str从start到end的src用desc替换掉 121 | * 122 | * @param src 123 | * @param start 124 | * @param end 125 | * @param desc 126 | * @return 127 | */ 128 | public static final String replaceAll(String str, String src, String desc) { 129 | if (isEmpty(str)) { 130 | return ""; 131 | } 132 | int start = 0; 133 | int end = str.length(); 134 | return replaceAll(str, src, start, end, desc); 135 | } 136 | 137 | 138 | 139 | /** 140 | * str字串,从START开始是否与desc相同 141 | * 142 | * @param src 143 | * @param start 144 | * @param desc 145 | * @return 146 | */ 147 | private static final boolean equals(char srcBytes[], int start, 148 | char descBytes[]) { 149 | for (int i = start; i < srcBytes.length && i - start < descBytes.length; i++) { 150 | char a = srcBytes[i]; 151 | char b = descBytes[i - start]; 152 | if (a != b) { 153 | return false; 154 | } 155 | 156 | } 157 | return true; 158 | } 159 | 160 | /** 161 | * str字串,从START开始是否与desc相同 162 | * 163 | * @param src 164 | * @param start 165 | * @param desc 166 | * @return 167 | */ 168 | public static final boolean equals(String src, int start, String desc) { 169 | char srcBytes[] = src.toCharArray(); 170 | char descBytes[] = desc.toCharArray(); 171 | return equals(srcBytes, start, descBytes); 172 | } 173 | 174 | public static final boolean isEmpty(String str) { 175 | String temStr = str; 176 | if (str != null) { 177 | temStr = str.trim(); 178 | if (temStr.length() != 0) { 179 | if (!"NULL".equals(temStr.toUpperCase())) { 180 | if (!"".equals(temStr)) { 181 | return false; 182 | } 183 | } 184 | } 185 | } 186 | return true; 187 | } 188 | 189 | /** 190 | * 一句话(line) 包括单词(subStr) aa 包含[aaaa aa] 191 | * 192 | * @param line 193 | * @param subStr 194 | * @return 195 | */ 196 | public static final boolean hasWord(String line, String subStr) { 197 | if (subStr == null || line == null) { 198 | return false; 199 | } 200 | byte lineBytes[] = line.getBytes(); 201 | byte subBytes[] = subStr.getBytes(); 202 | if (lineBytes.length < subBytes.length) { 203 | byte temp[] = lineBytes; 204 | lineBytes = subBytes; 205 | subBytes = temp; 206 | } 207 | for (int i = 0; i < lineBytes.length - subBytes.length; i++) { 208 | if (i != 0) { 209 | if (!isWordSeparator((char) lineBytes[i])) { 210 | continue; 211 | } else { 212 | i++; 213 | } 214 | } else { 215 | if (isWordSeparator((char) lineBytes[i])) { 216 | i++; 217 | } 218 | } 219 | int j = 0; 220 | for (j = 0; j < subBytes.length; j++) { 221 | if (lineBytes[i + j] != subBytes[j]) { 222 | break; 223 | } 224 | } 225 | if (j == subBytes.length) { 226 | if (i != lineBytes.length - subBytes.length) { 227 | if (!isWordSeparator((char) lineBytes[i + j])) { 228 | continue; 229 | } 230 | } 231 | return true; 232 | } 233 | } 234 | return false; 235 | } 236 | 237 | /** 238 | * 是否是单词分隔字符 239 | * 240 | * @param c 241 | * @return 242 | */ 243 | public static final boolean isWordSeparator(char c) { 244 | if (c == ' ' || c == '\t') { 245 | return true; 246 | } 247 | return false; 248 | } 249 | 250 | /** 251 | * 取出括号(...)的中间内容 252 | * 253 | * @param src 254 | * @param a 255 | * @param b 256 | * @return 257 | */ 258 | public static String betweenPair(char cs[], int offset, char a, char b) { 259 | // int ret[] = null; 260 | int i = offset; 261 | for (; i < cs.length; i++) { 262 | char c = cs[i]; 263 | if (c == a) { 264 | break; 265 | } 266 | } 267 | // System.out.println(cs[i]); 268 | long count = 0; 269 | for (int j = i; j < cs.length; j++) { 270 | char c = cs[j]; 271 | if (c == a) { 272 | count++; 273 | } else if (c == b) { 274 | count--; 275 | } 276 | if (count == 0) { 277 | return new String(cs, i + 1, j - i - 1); 278 | } 279 | 280 | } 281 | 282 | return ""; 283 | } 284 | 285 | /** 286 | * 取出括号(...)的中间内容 287 | * 288 | * @param src 289 | * @param a 290 | * @param b 291 | * @return 292 | */ 293 | public static int[] betweenPairIndex(String src, char a, char b) { 294 | int ret[] = null; 295 | byte bytes[] = src.getBytes(); 296 | int i = 0; 297 | for (i = 0; i < bytes.length; i++) { 298 | if (bytes[i] == a) { 299 | break; 300 | } 301 | } 302 | long count = 0; 303 | for (int j = i; j < bytes.length; j++) { 304 | // cout< between4Quote(String src, char a) { 363 | List ret = new ArrayList(); 364 | char bytes[] = src.toCharArray(); 365 | between4Quote(bytes, 0, a, ret); 366 | 367 | return ret; 368 | } 369 | 370 | private static void between4Quote(char bytes[], int offset, char a, 371 | List ret) { 372 | int i = between4Quote(bytes, offset, a); 373 | if (i != -1) { 374 | int index = between4Quote(bytes, i + 1, a); 375 | if (index != -1) { 376 | ret.add(new String(bytes, i + 1, index - i - 1)); 377 | between4Quote(bytes, index + 1, a, ret); 378 | } 379 | 380 | } 381 | } 382 | 383 | /** 384 | * 取出括号(...)的中间内容 385 | * 386 | * @param src 387 | * @param a 388 | * @param b 389 | * @return 390 | */ 391 | private static int between4Quote(char cs[], int offset, char a) { 392 | 393 | for (int i = offset; i < cs.length; i++) { 394 | if (cs[i] == a) { 395 | return i; 396 | } 397 | } 398 | return -1; 399 | 400 | } 401 | 402 | /** 403 | * 判断字串中,a与b成对的出现 404 | * 405 | * @param src 406 | * @param a 407 | * @param b 408 | * @return 409 | */ 410 | public static boolean isAllInPair(String src, char a, char b) { 411 | long count = 0; 412 | byte bytes[] = src.getBytes(); 413 | for (int i = 0; i < bytes.length; i++) { 414 | 415 | if (bytes[i] == a) { 416 | count++; 417 | } else if (bytes[i] == b) { 418 | count--; 419 | } 420 | 421 | } 422 | if (count == 0) { 423 | return true; 424 | } else { 425 | return false; 426 | } 427 | } 428 | 429 | /** 430 | * 从src中取出包括str任意字符串的开始地址 431 | * 432 | * @param src 433 | * @param str 434 | * @return 435 | */ 436 | public static int indexInclude(String src, String str) { 437 | int ret = -1; 438 | byte bytes[] = src.getBytes(); 439 | byte iBytes[] = str.getBytes(); 440 | 441 | for (int i = 0; i < bytes.length; i++) { 442 | 443 | for (int j = 0; j < iBytes.length; j++) { 444 | 445 | if (bytes[i] == iBytes[j]) { 446 | return i; 447 | } 448 | 449 | } 450 | 451 | } 452 | 453 | return ret; 454 | } 455 | 456 | /*************************************************************************** 457 | * 判断字串是否是数字字串 458 | **************************************************************************/ 459 | public static final boolean isNumber(String str) { 460 | String tempStr = str.trim(); 461 | if (tempStr.startsWith("-")) { 462 | tempStr = tempStr.substring(1, tempStr.length()); 463 | } 464 | if (tempStr.startsWith("+")) { 465 | tempStr = tempStr.substring(1, tempStr.length()); 466 | } 467 | byte bytes[] = tempStr.getBytes(); 468 | int count = 0; 469 | for (int i = 0; i < bytes.length; i++) { 470 | if (".".indexOf(bytes[i]) != -1) { 471 | if (count > 0) { 472 | return false; 473 | } else { 474 | count++; 475 | continue; 476 | } 477 | } 478 | if ("1234567890".indexOf(bytes[i]) == -1) { 479 | return false; 480 | } 481 | 482 | } 483 | if (bytes.length == 0) { 484 | return false; 485 | } else { 486 | return true; 487 | } 488 | } 489 | 490 | /** 491 | * 判断是否是布尔值 492 | * 493 | * @param str 494 | * @return 495 | */ 496 | public static final boolean isBoolean(String str) { 497 | if (isEmpty(str)) { 498 | return false; 499 | } 500 | if ("true".equals(str.toLowerCase())) { 501 | return true; 502 | } else if ("false".equals(str.toLowerCase())) { 503 | return true; 504 | } else { 505 | return false; 506 | } 507 | } 508 | 509 | /** 510 | * 取第一个字 511 | * 512 | * @param src 513 | * 514 | * @return 515 | */ 516 | public static String firstWord(String src) { 517 | String ret = ""; 518 | byte bytes[] = src.getBytes(); 519 | for (int i = 0; i < bytes.length; i++) { 520 | 521 | if (bytes[i] == ' ' || bytes[i] == '\n' || bytes[i] == '\t') { 522 | return new String(bytes, 0, i); 523 | } 524 | 525 | } 526 | return ret; 527 | } 528 | 529 | /** 530 | * 第一个字的结束地址 531 | * 532 | * @param src 533 | * 534 | * @return 535 | */ 536 | public static int firstWordAt(String src) { 537 | int ret = -1; 538 | byte bytes[] = src.getBytes(); 539 | for (int i = 0; i < bytes.length; i++) { 540 | 541 | if (bytes[i] == ' ' || bytes[i] == '\n' || bytes[i] == '\t') { 542 | return i; 543 | } 544 | 545 | } 546 | return ret; 547 | } 548 | 549 | public static List getListFromListString(String listString) { 550 | List list = new ArrayList(); 551 | String temp = ""; 552 | temp = betweenPair(listString, '[', ']'); 553 | if (!"".equals(temp)) { 554 | long mIndex = temp.indexOf('{'); 555 | 556 | if (mIndex != -1) { 557 | int index[] = betweenPairIndex(temp, '{', '}'); 558 | String subStr = temp.substring(index[0] - 1, index[1] + 1); 559 | // Map subParam = getMapFromMapString(subStr); 560 | int keyStart = indexOf(temp, index[0], ',', false); 561 | if (keyStart == -1) { 562 | keyStart = 0; 563 | } 564 | list.add(subStr); 565 | // temp = temp.replace(subStr, ""); 566 | temp = replaceAll(temp, keyStart, index[1] + 1, ""); 567 | list.addAll(getListFromListString("[" + temp + "]")); 568 | return list; 569 | } 570 | 571 | String valuesString[] = temp.split(","); 572 | 573 | for (int i = 0; i < valuesString.length; i++) { 574 | list.add(valuesString[i]); 575 | // log.debug(key); 576 | } 577 | 578 | } 579 | return list; 580 | } 581 | 582 | public static String[] getArrayFromListString(String arrayString) { 583 | 584 | String temp = ""; 585 | temp = betweenPair(arrayString, '[', ']'); 586 | if (!"".equals(temp)) { 587 | 588 | return temp.split(","); 589 | 590 | } 591 | return null; 592 | } 593 | 594 | /** 595 | * 把以desc结尾的去掉: 596 | * 597 | * @param src 598 | * @return 599 | */ 600 | public static String cust(String src, String desc) { 601 | 602 | long index = src.lastIndexOf(desc); 603 | if (index == -1) { 604 | return src; 605 | } else { 606 | return src.substring(0, src.length() - desc.length()); 607 | } 608 | 609 | } 610 | 611 | /** 612 | * 把字串变为指定长度,用指定值填补空位 613 | * 614 | * @param line 615 | * @return 616 | * @throws Exception 617 | */ 618 | public static String fixStringToLength(String numStr, int length, 619 | char addChar) { 620 | if (length <= 0) { 621 | return ""; 622 | } 623 | if (numStr.length() == length) { 624 | return numStr; 625 | } else if (numStr.length() > length) { 626 | return numStr.substring(0, length); 627 | } 628 | char bytes[] = new char[length]; 629 | char cs[] = numStr.toCharArray(); 630 | int fromId = length - cs.length; 631 | 632 | for (int i = 0; i < fromId; i++) { 633 | bytes[i] = addChar; 634 | } 635 | for (int i = 0; i < cs.length; i++) { 636 | bytes[fromId] = cs[i]; 637 | fromId++; 638 | } 639 | 640 | return new String(bytes, 0, fromId); 641 | } 642 | 643 | /** 644 | * newObject=StringUtil.fixStringToHttpHeadKey(obj, '-'); 645 | * 646 | * @param numStr 647 | * @param addChar 648 | * @return 649 | */ 650 | public static String fixStringToHttpHeadKey(String numStr, char addChar) { 651 | 652 | char bytes[] = numStr.toCharArray(); 653 | char newBytes[] = new char[bytes.length]; 654 | for (int i = 0; i < newBytes.length; i++) { 655 | char c = bytes[i]; 656 | 657 | if (i == 0) { 658 | if (c > 'Z') { 659 | newBytes[i] = (char) (c - 32); 660 | } else { 661 | newBytes[i] = c; 662 | } 663 | continue; 664 | } else { 665 | char bc = bytes[i - 1]; 666 | if (bc == addChar) { 667 | if (c > 'Z') { 668 | newBytes[i] = (char) (c - 32); 669 | } else { 670 | newBytes[i] = c; 671 | } 672 | continue; 673 | } else { 674 | newBytes[i] = c; 675 | } 676 | } 677 | 678 | } 679 | return new String(newBytes); 680 | } 681 | 682 | /** 683 | * 当字串大于指定值时,把多出的字串截掉,并以...结尾 684 | * 685 | * @param line 686 | * @return 687 | * @throws Exception 688 | */ 689 | public static String custStringBigByLength(String numStr, int length) { 690 | 691 | if (length <= 0) { 692 | return ""; 693 | } else if (length == 1) { 694 | return "."; 695 | } else if (length == 2) { 696 | return ".."; 697 | } else if (length == 3) { 698 | return "..."; 699 | } else { 700 | if (numStr.length() <= length) { 701 | return numStr; 702 | } else { 703 | StringBuilder sb = new StringBuilder(numStr.substring(0, 704 | length - 3)); 705 | sb.append("..."); 706 | return sb.toString(); 707 | } 708 | } 709 | } 710 | 711 | /** 712 | * 取得 lc到rc之间的字串 713 | * 714 | * @param str 715 | * @param lc 716 | * @param rc 717 | * @return 718 | */ 719 | public static String getInnerString(String str, char lc, char rc) { 720 | if (str == null || str.length() == 0) { 721 | return ""; 722 | } 723 | char cs[] = str.toCharArray(); 724 | int i = 0; 725 | for (i = 0; i < cs.length; i++) { 726 | char c = cs[i]; 727 | if (c == lc) { 728 | break; 729 | } 730 | } 731 | int lId = i; 732 | for (i = cs.length - 1; i >= lId; i--) { 733 | char c = cs[i]; 734 | if (c == rc) { 735 | break; 736 | } 737 | } 738 | int rId = i; 739 | if (lId >= rId) { 740 | return ""; 741 | } 742 | return new String(cs, lId + 1, rId - lId - 1); 743 | } 744 | 745 | 746 | 747 | private static final int[] allChineseScope = { 1601, 1637, 1833, 2078, 748 | 2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 749 | 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600, 750 | Integer.MAX_VALUE }; 751 | 752 | public static final char unknowChar = '*'; 753 | 754 | private static final char[] allEnglishLetter = { 'A', 'B', 'C', 'D', 'E', 755 | 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 756 | 'T', 'W', 'X', 'Y', 'Z', unknowChar }; 757 | 758 | /** 759 | * 取中文拼音首字符 760 | * 761 | * @param str 762 | * @return 763 | */ 764 | public static char getFirstLetterFromChinessWord(String str) { 765 | char result = '*'; 766 | String temp = str.toUpperCase(); 767 | try { 768 | 769 | byte[] bytes = temp.getBytes("gbk"); 770 | if ((bytes[0] & 0x0FF) < 128 && (bytes[0] & 0x0FF) > 0) { 771 | return (char) bytes[0]; 772 | } 773 | 774 | int gbkIndex = 0; 775 | 776 | for (int i = 0; i < bytes.length; i++) { 777 | bytes[i] -= 160; 778 | } 779 | gbkIndex = bytes[0] * 100 + bytes[1]; 780 | for (int i = 0; i < allEnglishLetter.length; i++) { 781 | if (i == 22) { 782 | // System.out.println(allEnglishLetter.length 783 | // +" "+allChineseScope.length); 784 | } 785 | if (gbkIndex >= allChineseScope[i] 786 | && gbkIndex < allChineseScope[i + 1]) { 787 | result = allEnglishLetter[i]; 788 | break; 789 | } 790 | } 791 | 792 | } catch (Exception e) { 793 | 794 | } 795 | return result; 796 | } 797 | 798 | 799 | 800 | /** 801 | * 从char[]缓冲中取一行 802 | * 803 | * @param cs 804 | * @param startId 805 | * @return 806 | * @throws Exception 807 | */ 808 | public static int getLine(char cs[], int count, int offset) 809 | throws Exception { 810 | if (cs == null || cs.length == 0) { 811 | return -1; 812 | 813 | } 814 | if (count < 1) { 815 | return -1; 816 | 817 | } 818 | if (count > cs.length) { 819 | count = cs.length; 820 | 821 | } 822 | 823 | for (int i = offset; i < count; i++) { 824 | int b = cs[i]; 825 | // if (b == -1) { 826 | // ExceptionFactory.throwSystemException("", "读取行失败", 827 | // new Object[] {}); 828 | // } 829 | if (b == '\r') { 830 | if (i + 1 < count) { 831 | int a = cs[i + 1]; 832 | if (a == '\n') { 833 | return i + 1; 834 | } else { 835 | i++; 836 | } 837 | } 838 | 839 | } else { 840 | if (b == '\n') { 841 | return i; 842 | } else { 843 | continue; 844 | } 845 | 846 | } 847 | } 848 | 849 | return -1; 850 | } 851 | 852 | /** 853 | * 从char[]缓冲中取一行 854 | * 855 | * @param cs 856 | * @param startId 857 | * @return 858 | * @throws Exception 859 | */ 860 | public static int getLine(byte cs[], int count, int offset) 861 | throws Exception { 862 | if (cs == null || cs.length == 0) { 863 | return -1; 864 | 865 | } 866 | if (count < 1) { 867 | return -1; 868 | 869 | } 870 | if (count > cs.length) { 871 | count = cs.length; 872 | 873 | } 874 | 875 | for (int i = offset; i < count; i++) { 876 | int b = cs[i]; 877 | // if (b == -1) { 878 | // ExceptionFactory.throwSystemException("", "读取行失败", 879 | // new Object[] {}); 880 | // } 881 | if (b == '\r') { 882 | if (i + 1 < count) { 883 | int a = cs[i + 1]; 884 | if (a == '\n') { 885 | return i + 1; 886 | } else { 887 | i++; 888 | } 889 | } 890 | 891 | } else { 892 | if (b == '\n') { 893 | return i; 894 | } else { 895 | continue; 896 | } 897 | 898 | } 899 | } 900 | 901 | return -1; 902 | } 903 | 904 | /** 905 | * 把字串变为double 906 | * 907 | * @param str 908 | * @param defaultValue 909 | * @return 910 | */ 911 | public static double getDouble(String str) { 912 | double defaultValue = 0; 913 | return getDouble(str, defaultValue); 914 | } 915 | 916 | /** 917 | * 把字串变为double 918 | * 919 | * @param str 920 | * @param defaultValue 921 | * @return 922 | */ 923 | public static double getDouble(String str, double defaultValue) { 924 | if (isEmpty(str)) { 925 | return defaultValue; 926 | } else { 927 | if (isNumber(str)) { 928 | return Double.parseDouble(str); 929 | } else { 930 | return defaultValue; 931 | } 932 | 933 | } 934 | } 935 | 936 | /** 937 | * 把字串变为long 938 | * 939 | * @param str 940 | * @param defaultValue 941 | * @return 942 | */ 943 | public static long getLong(String str, long defaultValue) { 944 | try { 945 | if (isEmpty(str)) { 946 | return defaultValue; 947 | } else { 948 | if (isNumber(str)) { 949 | return Long.parseLong(str); 950 | } else { 951 | return defaultValue; 952 | } 953 | 954 | } 955 | } catch (java.lang.NumberFormatException e) { 956 | throw new RuntimeException("字符格式太长了"); 957 | } 958 | 959 | } 960 | 961 | /** 962 | * 把字串变为long 963 | * 964 | * @param str 965 | * @param defaultValue 966 | * @return 967 | */ 968 | public static long getLong(String str) { 969 | return getLong(str, 0); 970 | } 971 | 972 | /** 973 | * 把字串变为boolean 974 | * 975 | * @param str 976 | * @param defaultValue 977 | * @return 978 | */ 979 | public static boolean getBoolean(String str, boolean defaultValue) { 980 | if (isEmpty(str)) { 981 | return defaultValue; 982 | } else { 983 | if (isBoolean(str)) { 984 | return Boolean.parseBoolean(str); 985 | } else { 986 | return defaultValue; 987 | } 988 | 989 | } 990 | } 991 | 992 | /** 993 | * 把字串变为boolean 994 | * 995 | * @param str 996 | * @param defaultValue 997 | * @return 998 | */ 999 | public static boolean getBoolean(String str) { 1000 | return getBoolean(str, false); 1001 | } 1002 | 1003 | /** 1004 | * 把字串变为int 1005 | * 1006 | * @param str 1007 | * @param defaultValue 1008 | * @return 1009 | */ 1010 | public static int getInteger(String str, int defaultValue) { 1011 | if (isEmpty(str)) { 1012 | return defaultValue; 1013 | } else { 1014 | if (isNumber(str)) { 1015 | return Integer.parseInt(str); 1016 | } else { 1017 | return defaultValue; 1018 | } 1019 | 1020 | } 1021 | } 1022 | 1023 | /** 1024 | * 把字串变为int 1025 | * 1026 | * @param str 1027 | * @param defaultValue 1028 | * @return 1029 | */ 1030 | public static int getInteger(String str) { 1031 | return getInteger(str, 0); 1032 | } 1033 | 1034 | /** 1035 | * 把字串变为String 1036 | * 1037 | * @param str 1038 | * @param defaultValue 1039 | * @return 1040 | */ 1041 | public static String getString(String str, String defaultValue) { 1042 | if (isEmpty(str)) { 1043 | return defaultValue; 1044 | } else { 1045 | return str; 1046 | } 1047 | } 1048 | 1049 | /** 1050 | * 把字串变为String 1051 | * 1052 | * @param str 1053 | * @param defaultValue 1054 | * @return 1055 | */ 1056 | public static String getString(String str) { 1057 | return getString(str, ""); 1058 | } 1059 | 1060 | /** 1061 | * 从文件全路径中取文名 1062 | * 1063 | * @param str 1064 | * @return 1065 | * 1066 | * @throws SystemException 1067 | */ 1068 | public static String getSimpleFileNameFromFullFileName(String fFileName) 1069 | throws SystemException { 1070 | if (isEmpty(fFileName)) { 1071 | return ""; 1072 | } 1073 | // log.info("--------------------"+fFileName); 1074 | char cs[] = fFileName.toCharArray(); 1075 | int startId = 0; 1076 | int retId = cs.length; 1077 | for (int i = cs.length - 1; i >= 0; i--) { 1078 | char c = cs[i]; 1079 | if (c == '.') { 1080 | 1081 | if (retId == cs.length) { 1082 | retId = i; 1083 | } 1084 | // else { 1085 | // ExceptionFactory.throwSystemException("参数${0}不是合法的文件路径", 1086 | // new String[] { fFileName }); 1087 | // } 1088 | } else if (c == '/') { 1089 | 1090 | if (startId == 0) { 1091 | startId = i; 1092 | break; 1093 | } 1094 | } else if (c == '\\') { 1095 | if (startId == 0) { 1096 | startId = i; 1097 | break; 1098 | } 1099 | } 1100 | 1101 | } 1102 | if (startId == 0) { 1103 | return new String(cs, startId, retId - startId); 1104 | } else { 1105 | return new String(cs, startId + 1, retId - startId - 1); 1106 | } 1107 | 1108 | } 1109 | 1110 | /** 1111 | * 从文件全路径中取文件后缀名 1112 | * 1113 | * @param str 1114 | * @return 1115 | * 1116 | * @throws SystemException 1117 | */ 1118 | public static String getFileSubNameFromFullFileName(String fFileName) 1119 | throws SystemException { 1120 | if (isEmpty(fFileName)) { 1121 | return ""; 1122 | } 1123 | char cs[] = fFileName.toCharArray(); 1124 | 1125 | for (int i = cs.length - 1; i >= 0; i--) { 1126 | char c = cs[i]; 1127 | if (c == '.') { 1128 | return new String(cs, i + 1, cs.length - i - 1); 1129 | } else if (c == '/') { 1130 | return ""; 1131 | } else if (c == '\\') { 1132 | return ""; 1133 | } 1134 | 1135 | } 1136 | 1137 | return ""; 1138 | } 1139 | 1140 | public static List split(String line, char c) { 1141 | List list = new ArrayList(); 1142 | if (isEmpty(line)) { 1143 | return list; 1144 | } 1145 | if (line.indexOf(c) == -1) { 1146 | list.add(line); 1147 | return list; 1148 | } 1149 | char cs[] = line.toCharArray(); 1150 | 1151 | int start = 0; 1152 | 1153 | for (int i = 0; i < cs.length; i++) { 1154 | char tc = cs[i]; 1155 | if (c == tc) { 1156 | list.add(new String(cs, start, i - start)); 1157 | start = i + 1; 1158 | } 1159 | } 1160 | list.add(new String(cs, start, line.length() - start)); 1161 | return list; 1162 | } 1163 | 1164 | public static String arrayToString(Object objs[]) { 1165 | StringBuilder ret = new StringBuilder(); 1166 | for (int i = 0; objs != null && i < objs.length; i++) { 1167 | Object obj = objs[i]; 1168 | if (ret.length() != 0) { 1169 | ret.append(","); 1170 | } 1171 | ret.append(obj); 1172 | } 1173 | return ret.toString(); 1174 | } 1175 | 1176 | /** 1177 | * 取得URL的路径,去?号之后的字串,去;号之后的数据字串 1178 | * 1179 | * @param curUrl 1180 | * @return 1181 | * @throws SystemException 1182 | */ 1183 | public static String getUrlForPath(String curUrl) { 1184 | 1185 | if (StringsUtils.isEmpty(curUrl)) { 1186 | return ""; 1187 | } 1188 | 1189 | int id = curUrl.indexOf(';'); 1190 | if (id != -1) { 1191 | curUrl = curUrl.substring(0, id); 1192 | } else { 1193 | id = curUrl.indexOf('?'); 1194 | if (id != -1) { 1195 | curUrl = curUrl.substring(0, id); 1196 | } 1197 | } 1198 | return curUrl; 1199 | } 1200 | 1201 | /** 1202 | * 判断字串是否包含中文 1203 | * 1204 | * @param str 1205 | * @return 1206 | */ 1207 | public static boolean isChinese(String str) { 1208 | Pattern p = Pattern.compile("[\u4e00-\u9fa5]"); 1209 | Matcher m = p.matcher(str); 1210 | if (m.find()) { 1211 | return true; 1212 | } 1213 | return false; 1214 | } 1215 | 1216 | public static Map getParameterFromQueryString( 1217 | String queryString) throws Exception { 1218 | if (isEmpty(queryString)) { 1219 | return new HashMap(); 1220 | } 1221 | if (queryString.startsWith("?")) { 1222 | queryString = queryString.substring(1, queryString.length()); 1223 | } 1224 | String items[] = queryString.split("&"); 1225 | 1226 | Map param = new HashMap(items.length); 1227 | for (String item : items) { 1228 | String keyvalue[] = item.split("="); 1229 | if (keyvalue.length == 2) { 1230 | param.put(keyvalue[0], keyvalue[1]); 1231 | } 1232 | } 1233 | return param; 1234 | } 1235 | 1236 | /** 1237 | * 将日期转化为指定格式[yyyy-MM-dd]字符串 1238 | */ 1239 | public static String formatDate(Date date) { 1240 | return formatDate(date, null); 1241 | } 1242 | 1243 | /** 1244 | * 将日期转化为指定格式字符串 1245 | */ 1246 | public static String formatDate(Date date, String pattern) { 1247 | if (date == null) { 1248 | return ""; 1249 | } 1250 | if (isEmpty(pattern)) { 1251 | pattern = "yyyy-MM-dd"; 1252 | } 1253 | return (new SimpleDateFormat(pattern)).format(date); 1254 | } 1255 | 1256 | private static String inj_str = "'|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|; |or|-|+|,|--"; 1257 | 1258 | /** 1259 | * 检查字串中是否包含SQL脚本,true=是SQL脚本,false=不是SQL脚本 1260 | * 1261 | * @param date 1262 | * @return 1263 | */ 1264 | public static boolean validateSql(String str1) { 1265 | if (isEmpty(str1)) { 1266 | return false; 1267 | } 1268 | String str = str1.trim(); 1269 | str = str.toUpperCase(); 1270 | String[] inj_stra = inj_str.toUpperCase().split("\\|"); 1271 | for (int i = 0; i < inj_stra.length; i++) { 1272 | if (str.indexOf(" " + inj_stra[i] + " ") >= 0 1273 | || str.indexOf(inj_stra[i] + " ") >= 0 1274 | || str.indexOf(" " + inj_stra[i]) >= 0 1275 | || str.indexOf(inj_stra[i] + ";") >= 0 1276 | || str.indexOf(";" + inj_stra[i]) >= 0 1277 | || str.indexOf(inj_stra[i] + "/**/") >= 0 1278 | || str.indexOf("/**/" + inj_stra[i]) >= 0 1279 | || str.indexOf(inj_stra[i] + "%") >= 0 1280 | || str.indexOf("%" + inj_stra[i]) >= 0) { 1281 | 1282 | return false; 1283 | } 1284 | if ("--".equals(inj_stra[i]) && str.indexOf(inj_stra[i]) >= 0) { 1285 | 1286 | return false; 1287 | } 1288 | } 1289 | return true; 1290 | } 1291 | 1292 | /** 1293 | * 将容易引起xss漏洞的半角字符直接替换成全角字符 1294 | * 1295 | * @param s 1296 | * @return 1297 | */ 1298 | public static String doXssEncode(String s) { 1299 | if (s == null || "".equals(s)) { 1300 | return s; 1301 | } 1302 | StringBuilder sb = new StringBuilder(s.length() + 16); 1303 | for (int i = 0; i < s.length(); i++) { 1304 | char c = s.charAt(i); 1305 | switch (c) { 1306 | case '>': 1307 | sb.append('>');// 全角大于号 1308 | break; 1309 | case '<': 1310 | sb.append('<');// 全角小于号 1311 | break; 1312 | case '\'': 1313 | sb.append('‘');// 全角单引号 1314 | break; 1315 | case '\"': 1316 | sb.append('“');// 全角双引号 1317 | break; 1318 | case '&': 1319 | sb.append('&');// 全角 1320 | break; 1321 | case '\\': 1322 | sb.append('\');// 全角斜线 1323 | break; 1324 | case '#': 1325 | sb.append('#');// 全角井号 1326 | break; 1327 | default: 1328 | sb.append(c); 1329 | break; 1330 | } 1331 | } 1332 | return sb.toString(); 1333 | } 1334 | 1335 | public static String getMsgByThrowable4Dialog(Throwable t) { 1336 | return getMsgByThrowable(t,512); 1337 | 1338 | } 1339 | protected static String getMsgByThrowable(Throwable t,int size) { 1340 | if(t==null){ 1341 | return ""; 1342 | } 1343 | if(size<256){ 1344 | size=256; 1345 | } 1346 | StringBuilder sb = new StringBuilder(size); 1347 | String temp = t.toString(); 1348 | if (temp != null) { 1349 | if (temp.length() > size) { 1350 | return temp.substring(0, size); 1351 | } 1352 | sb.append(t.toString()); 1353 | } 1354 | //sb.setLength(0); 1355 | StackTraceElement[] trace = t.getStackTrace(); 1356 | for (int i = 0; i < trace.length; i++) { 1357 | if(sb.length()>0){ 1358 | sb.append("\n"); 1359 | } 1360 | sb.append("\tat " + trace[i]); 1361 | if (sb.length() > size) { 1362 | return sb.toString().substring(0, size); 1363 | } 1364 | } 1365 | return sb.toString(); 1366 | 1367 | } 1368 | } 1369 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/utils/WidgeUtils.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class WidgeUtils { 7 | 8 | //解析控件属性 9 | public static Map parseAttr(String widgeType) { 10 | Map map = new HashMap(); 11 | 12 | String[] arrs = widgeType.split("[\\[\\]]"); 13 | for(String s : arrs){ 14 | if(!"".endsWith(s) && s.indexOf("=") != -1 ){ 15 | String key = s.substring(0, s.indexOf("=")); 16 | String value = s.substring(s.indexOf("=")+1); 17 | map.put(key.toLowerCase(), value); 18 | } 19 | } 20 | return map; 21 | } 22 | 23 | /* 24 | * 用于将Excel表格中列号字母转成列索引,从1对应A开始 25 | */ 26 | public static int columnToIndex(String column) { 27 | column = column.toUpperCase(); 28 | if (!column.matches("[A-Z]+")) { 29 | try { 30 | throw new Exception("Invalid parameter"); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | int index = 0; 36 | char[] chars = column.toUpperCase().toCharArray(); 37 | for (int i = 0; i < chars.length; i++) { 38 | index += ((int) chars[i] - (int) 'A' + 1) 39 | * (int) Math.pow(26, chars.length - i - 1); 40 | } 41 | return index; 42 | } 43 | 44 | /* 45 | * 用于将Excel表格中第几列转为字母,columnNum为1返回A 46 | */ 47 | public static String getColumnName(int columnNum) { 48 | int first; 49 | int last; 50 | String result = ""; 51 | if (columnNum > 256) 52 | columnNum = 256; 53 | first = columnNum / 27; 54 | last = columnNum - (first * 26); 55 | 56 | if (first > 0){ 57 | result = String.valueOf((char) (first + 64)); 58 | } 59 | if (last > 0){ 60 | result = result + String.valueOf((char) (last + 64)); 61 | } 62 | result = result.toLowerCase(); 63 | return result; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/AbsWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | import com.codecraft.excel2html.entity.ExcelTableTdStyle; 6 | import com.codecraft.excel2html.entity.ExcelWidget; 7 | import com.codecraft.excel2html.utils.StringsUtils; 8 | 9 | /** 10 | * 控件接口 11 | * @author zoro 12 | * 13 | */ 14 | public abstract class AbsWidget implements IWidget{ 15 | 16 | /** 17 | * 获得当前控件id 18 | * @param table 19 | * @return 20 | */ 21 | protected String getTagId(ExcelTable table,String widgetType){ 22 | int startIdValue = table.getStartIdValue(); 23 | String tagId = String.format("A%s", table.getWidgetList().size() + startIdValue); 24 | 25 | ExcelWidget widget = new ExcelWidget(); 26 | widget.setTagId(tagId); 27 | widget.setWidgetType(widgetType); 28 | table.getWidgetList().add(widget); 29 | return tagId; 30 | } 31 | 32 | /** 33 | * 获得td字体样式 34 | * @param td 35 | * @return 36 | */ 37 | protected String getFontStyle(ExcelTableTd td) { 38 | ExcelTableTdStyle bo = td.getTdStyle(); 39 | String fontSize = bo.getFontHeight();//字体大小 40 | String fontFamily = bo.getFontName(); 41 | StringBuffer sb = new StringBuffer(""); 42 | 43 | if(!StringsUtils.isEmpty(fontSize)){ 44 | sb.append(String.format("font-size:%s;", fontSize)); 45 | } 46 | if(!StringsUtils.isEmpty(fontFamily)){ 47 | sb.append(String.format("font-family:%s;", fontFamily)); 48 | } 49 | return sb.toString(); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/IWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | 6 | /** 7 | * 控件接口 8 | * @author zoro 9 | * 10 | */ 11 | public interface IWidget { 12 | 13 | // 编辑页面 14 | public String parseHtml4Edit(String widgetType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception; 15 | 16 | // 预览页面 17 | public String parseHtml4View(String widgetType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception; 18 | 19 | // 验证是否合法 20 | public void validate(String widgetType) throws Exception; 21 | 22 | // 判断是否是当前控件 23 | public boolean isCur(String widgetType); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/CheckWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import java.util.Map; 4 | 5 | import com.codecraft.excel2html.entity.ExcelTable; 6 | import com.codecraft.excel2html.entity.ExcelTableTd; 7 | import com.codecraft.excel2html.utils.WidgeUtils; 8 | import com.codecraft.excel2html.widget.AbsWidget; 9 | /** 10 | * 单选控件 11 | * @author zoro 12 | * 13 | */ 14 | public class CheckWidget extends AbsWidget { 15 | 16 | public static final String WIDGE_NAME = "chk".toLowerCase(); 17 | 18 | @Override 19 | public String parseHtml4Edit(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 20 | double width = td.getWidthNum(); 21 | String tagId = getTagId(table, WIDGE_NAME); 22 | String fontStyle = getFontStyle(td); 23 | if (isCur(widgeType)) { 24 | validate(widgeType); 25 | width = width-2-2;//表格长度-padding-边框 26 | 27 | String[] valueArray = null; 28 | Map attrs = WidgeUtils.parseAttr(widgeType); 29 | String value = attrs.get("value")!=null? attrs.get("value"):"";//属性值 30 | if("".equals(value)){//兼容以前的写法 31 | if(widgeType.indexOf("[") != -1 && widgeType.indexOf("]") != -1){ 32 | String values = widgeType.substring(widgeType.indexOf("[")+1,widgeType.indexOf("]")); 33 | valueArray = values.split(","); 34 | } 35 | }else{ 36 | valueArray = value.split(","); 37 | } 38 | sb.append("
"); 39 | String alias = tagId;//别名,不重复即可 40 | for(int i = 0; i < valueArray.length; i++ ){ 41 | String v = valueArray[i]; 42 | if(i != 0){ 43 | tagId = getTagId(table, WIDGE_NAME); 44 | } 45 | sb.append(String.format( 46 | "%s", 47 | tagId, tagId, alias, WIDGE_NAME, fontStyle, v, v)); 48 | } 49 | sb.append("
"); 50 | return WIDGE_NAME; 51 | } 52 | return ""; 53 | } 54 | 55 | @Override 56 | public String parseHtml4View(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 57 | double width = td.getWidthNum(); 58 | String tagId = getTagId(table, WIDGE_NAME); 59 | String fontStyle = getFontStyle(td); 60 | if (isCur(widgeType)) { 61 | validate(widgeType); 62 | width = width-2-2;//表格长度-padding-边框 63 | String[] valueArray = null; 64 | if(widgeType.indexOf("[") != -1 && widgeType.indexOf("]") != -1){ 65 | String values = widgeType.substring(widgeType.indexOf("[")+1,widgeType.indexOf("]")); 66 | valueArray = values.split(","); 67 | } 68 | sb.append("
"); 69 | String alias = tagId;//别名,不重复即可 70 | for(int i = 0; i < valueArray.length; i++ ){ 71 | String v = valueArray[i]; 72 | if(i != 0){ 73 | tagId = getTagId(table, WIDGE_NAME); 74 | } 75 | sb.append(String.format( 76 | "%s", 77 | tagId, tagId, alias, WIDGE_NAME, fontStyle, v, v)); 78 | } 79 | sb.append("
"); 80 | return WIDGE_NAME; 81 | } 82 | return ""; 83 | } 84 | 85 | @Override 86 | public void validate(String content){ 87 | 88 | } 89 | 90 | @Override 91 | public boolean isCur(String widgeType){ 92 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME + "[")){//必须是startWith 93 | return true; 94 | } 95 | return false; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/DateWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import java.util.Map; 4 | 5 | import com.codecraft.excel2html.cons.ExcelConstant; 6 | import com.codecraft.excel2html.entity.ExcelTable; 7 | import com.codecraft.excel2html.entity.ExcelTableTd; 8 | import com.codecraft.excel2html.utils.WidgeUtils; 9 | import com.codecraft.excel2html.widget.AbsWidget; 10 | /** 11 | * date--时间控件 12 | */ 13 | public class DateWidget extends AbsWidget { 14 | 15 | public String WIDGE_NAME = "date".toLowerCase(); 16 | 17 | @Override 18 | public String parseHtml4Edit(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 19 | double width = td.getWidthNum(); 20 | double height = td.getHeightNum(); 21 | String tagId = getTagId(table, WIDGE_NAME); 22 | String textAlign = td.getTextAlign(); 23 | String fontStyle = getFontStyle(td); 24 | if (isCur(widgeType)) { 25 | validate(widgeType); 26 | int length = 12; 27 | width = width-2-2;//表格长度-padding-边框 28 | Map attrs = WidgeUtils.parseAttr(widgeType); 29 | String format = attrs.get("format")!=null? attrs.get("format"):"";//格式化 30 | String auth = attrs.get("auth")!=null? attrs.get("auth").toLowerCase():"";//编写者(控件id需要转为小写) 31 | if("".equals(format)){ 32 | format = "yyyy年MM月dd日"; 33 | } 34 | sb.append(String 35 | .format( 36 | "
"+ 37 | "
", 39 | width, height, tagId, tagId, WIDGE_NAME, auth, width, height, textAlign, ExcelConstant.WIDGET_BACKGROUND_COLOR, fontStyle, format, length/2)); 40 | return WIDGE_NAME; 41 | } 42 | return ""; 43 | } 44 | 45 | @Override 46 | public String parseHtml4View(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 47 | double width = td.getWidthNum(); 48 | double height = td.getHeightNum(); 49 | String tagId = getTagId(table, WIDGE_NAME); 50 | String textAlign = td.getTextAlign(); 51 | String fontStyle = getFontStyle(td); 52 | if (isCur(widgeType)) { 53 | validate(widgeType); 54 | int length = 12;//时间 55 | Map attrs = WidgeUtils.parseAttr(widgeType); 56 | String auth = attrs.get("auth")!=null? attrs.get("auth"):"";//编写者 57 | width = width-2-2;//表格长度-padding-边框 58 | sb.append(String 59 | .format( 60 | "
"+ 61 | "
", 63 | width, height, tagId, tagId, WIDGE_NAME, auth, width, height, textAlign, fontStyle, length/2)); 64 | return WIDGE_NAME; 65 | } 66 | return ""; 67 | } 68 | 69 | @Override 70 | public void validate(String content){ 71 | } 72 | 73 | @Override 74 | public boolean isCur(String widgeType){ 75 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 76 | return true; 77 | } 78 | return false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/EditorWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | import com.codecraft.excel2html.widget.AbsWidget; 6 | 7 | public class EditorWidget extends AbsWidget { 8 | 9 | public static final String WIDGE_NAME = "editor".toLowerCase(); 10 | 11 | @Override 12 | public String parseHtml4Edit(String widgeType, StringBuilder sb, 13 | ExcelTable table, ExcelTableTd td) throws Exception { 14 | return ""; 15 | } 16 | 17 | @Override 18 | public String parseHtml4View(String widgeType, StringBuilder sb, 19 | ExcelTable table, ExcelTableTd td) throws Exception { 20 | return ""; 21 | } 22 | 23 | @Override 24 | public void validate(String widgeType) throws Exception { 25 | 26 | } 27 | 28 | @Override 29 | public boolean isCur(String widgeType) { 30 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 31 | return true; 32 | } 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/InputWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | import com.codecraft.excel2html.widget.AbsWidget; 6 | 7 | public class InputWidget extends AbsWidget { 8 | 9 | public static final String WIDGE_NAME = "input".toLowerCase(); 10 | 11 | @Override 12 | public String parseHtml4Edit(String widgeType, StringBuilder sb, 13 | ExcelTable table, ExcelTableTd td) throws Exception { 14 | 15 | return ""; 16 | } 17 | 18 | @Override 19 | public String parseHtml4View(String widgeType, StringBuilder sb, 20 | ExcelTable table, ExcelTableTd td) throws Exception { 21 | 22 | return ""; 23 | } 24 | 25 | @Override 26 | public void validate(String widgeType) throws Exception { 27 | 28 | } 29 | 30 | @Override 31 | public boolean isCur(String widgeType) { 32 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 33 | return true; 34 | } 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/PicWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import java.util.List; 4 | 5 | import com.codecraft.excel2html.entity.ExcelTable; 6 | import com.codecraft.excel2html.entity.ExcelTableTd; 7 | import com.codecraft.excel2html.entity.PictureStyle; 8 | import com.codecraft.excel2html.widget.AbsWidget; 9 | 10 | public class PicWidget extends AbsWidget { 11 | 12 | public static final String WIDGE_NAME = "pic".toLowerCase(); 13 | 14 | @Override 15 | public String parseHtml4Edit(String widgetType, StringBuilder sb, 16 | ExcelTable table, ExcelTableTd td) throws Exception { 17 | return parseContent(table); 18 | } 19 | 20 | @Override 21 | public String parseHtml4View(String widgetType, StringBuilder sb, 22 | ExcelTable table, ExcelTableTd td) throws Exception { 23 | return parseContent(table); 24 | } 25 | 26 | @Override 27 | public void validate(String widgetType) throws Exception { 28 | 29 | } 30 | 31 | @Override 32 | public boolean isCur(String widgetType) { 33 | if(widgetType.equalsIgnoreCase(WIDGE_NAME)){ 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | /** 40 | * 解析图片 41 | * @param table 42 | * @return 43 | */ 44 | public String parseContent(ExcelTable table){ 45 | List picStyleList = table.getPicStyleList(); 46 | if(picStyleList == null || picStyleList.size() == 0){ 47 | return ""; 48 | } 49 | int index = table.getUsedPicIndex(); 50 | PictureStyle picStyle = null; 51 | if(picStyleList.size() > index){ 52 | picStyle = picStyleList.get(index); 53 | table.setUsedPicIndex(index++); 54 | } 55 | if(picStyle == null){ 56 | return ""; 57 | } 58 | double width = picStyle.getWidth(); 59 | double height = picStyle.getHeight(); 60 | String picUrl = picStyle.getUrl(); 61 | String picHtml = String.format( 62 | "", picUrl, width-4,height);//减去4 表示左右两边2px的留白 63 | return picHtml; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/basic/TextareaWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.basic; 2 | 3 | import com.codecraft.excel2html.entity.ExcelTable; 4 | import com.codecraft.excel2html.entity.ExcelTableTd; 5 | import com.codecraft.excel2html.widget.AbsWidget; 6 | 7 | public class TextareaWidget extends AbsWidget { 8 | 9 | public static final String WIDGE_NAME = "textarea".toLowerCase(); 10 | 11 | @Override 12 | public String parseHtml4Edit(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 13 | 14 | return ""; 15 | } 16 | 17 | @Override 18 | public String parseHtml4View(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 19 | 20 | return ""; 21 | } 22 | 23 | @Override 24 | public void validate(String widgeType) throws Exception { 25 | 26 | } 27 | 28 | @Override 29 | public boolean isCur(String widgeType) { 30 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 31 | return true; 32 | } 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/calc/CalcNumWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.calc; 2 | 3 | import java.util.Map; 4 | 5 | import com.codecraft.excel2html.cons.ExcelConstant; 6 | import com.codecraft.excel2html.entity.ExcelTable; 7 | import com.codecraft.excel2html.entity.ExcelTableTd; 8 | import com.codecraft.excel2html.utils.StringsUtils; 9 | import com.codecraft.excel2html.utils.WidgeUtils; 10 | import com.codecraft.excel2html.widget.AbsWidget; 11 | 12 | /** 13 | * 计算数据来源 14 | */ 15 | public class CalcNumWidget extends AbsWidget { 16 | 17 | public static final String WIDGE_NAME = "numtext".toLowerCase(); 18 | 19 | @Override 20 | public String parseHtml4Edit(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 21 | double width = td.getWidthNum(); 22 | String tagId = getTagId(table, WIDGE_NAME); 23 | String textAlign = td.getTextAlign(); 24 | String fontStyle = getFontStyle(td); 25 | if (isCur(widgeType)) { 26 | validate(widgeType); 27 | Map attrs = WidgeUtils.parseAttr(widgeType); 28 | int length = 0; 29 | width = width-2-2;//表格长度-padding-边框 30 | String val = attrs.get("val")!=null ? attrs.get("val") : "";//计算值 31 | String text = attrs.get("text")!=null ? attrs.get("text") : "";//显示值 32 | 33 | //overflow:hidden;display:inline-block;white-space:nowrap; 预览时不溢出 34 | if(StringsUtils.isEmpty(val) && StringsUtils.isEmpty(text)){ 35 | sb.append(String.format( 36 | "", 37 | tagId, tagId, WIDGE_NAME, val, text, length, width, textAlign, ExcelConstant.WIDGET_BACKGROUND_COLOR, fontStyle)); 38 | }else{ 39 | sb.append(String.format( 40 | "%s", 41 | tagId, tagId, WIDGE_NAME, val, text, length, width, textAlign, fontStyle, text)); 42 | } 43 | return WIDGE_NAME; 44 | } 45 | return ""; 46 | } 47 | 48 | @Override 49 | public String parseHtml4View(String widgeType, StringBuilder sb, ExcelTable table, ExcelTableTd td) throws Exception { 50 | double width = td.getWidthNum(); 51 | String tagId = getTagId(table, WIDGE_NAME); 52 | String textAlign = td.getTextAlign(); 53 | String fontStyle = getFontStyle(td); 54 | if (isCur(widgeType)) { 55 | validate(widgeType); 56 | Map attrs = WidgeUtils.parseAttr(widgeType); 57 | int length = 0; 58 | width = width-2-2;//表格长度-padding-边框 59 | String val = attrs.get("val")!=null ? attrs.get("val") : "" ;//计算值 60 | String text = attrs.get("text")!=null ? attrs.get("text") : "";//显示值 61 | 62 | //overflow:hidden;display:inline-block;white-space:nowrap; 预览时不溢出 63 | sb.append(String.format( 64 | "%s", 65 | tagId, tagId, WIDGE_NAME, val, text, length, width, textAlign, fontStyle, text)); 66 | return WIDGE_NAME; 67 | } 68 | return ""; 69 | } 70 | 71 | @Override 72 | public void validate(String content)throws Exception { 73 | 74 | } 75 | 76 | @Override 77 | public boolean isCur(String widgeType){ 78 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 79 | return true; 80 | } 81 | return false; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/codecraft/excel2html/widget/calc/CalcRltWidget.java: -------------------------------------------------------------------------------- 1 | package com.codecraft.excel2html.widget.calc; 2 | 3 | import java.util.Map; 4 | 5 | import com.codecraft.excel2html.cons.ExcelConstant; 6 | import com.codecraft.excel2html.entity.ExcelTable; 7 | import com.codecraft.excel2html.entity.ExcelTableTd; 8 | import com.codecraft.excel2html.utils.WidgeUtils; 9 | import com.codecraft.excel2html.widget.AbsWidget; 10 | 11 | /** 12 | * 最终计算结果显示(也可以当做计算来源) 13 | * @description 14 | * exps 表达式 A*B 15 | * format 格式化 16 | * prec 精度(必须为正整数) 17 | * rigor 严格计算.表达式A*B 其中有一个变量值为''时,计算结果为Null (不设置此属性时,变量值为''当做0来计算) 18 | * @author zoro 19 | */ 20 | public class CalcRltWidget extends AbsWidget { 21 | 22 | public static final String WIDGE_NAME = "calc".toLowerCase(); 23 | 24 | @Override 25 | public String parseHtml4Edit(String widgeType, StringBuilder sb, ExcelTable table ,ExcelTableTd td) throws Exception { 26 | double width = td.getWidthNum(); 27 | double height = td.getHeightNum(); 28 | String tagId = getTagId(table, WIDGE_NAME); 29 | String textAlign = td.getTextAlign(); 30 | String fontStyle = getFontStyle(td); 31 | 32 | if (isCur(widgeType)) { 33 | validate(widgeType); 34 | Map attrs = WidgeUtils.parseAttr(widgeType); 35 | int length = 0; 36 | 37 | width = width-2-2;//表格长度-padding-边框 38 | 39 | String exps = attrs.get("exps").toLowerCase();//公式 40 | String format = attrs.get("format")!=null? attrs.get("format").toLowerCase():"";//格式化 41 | String prec = attrs.get("prec")!=null? attrs.get("prec"):"";//精度precision 42 | String rigor = attrs.get("rigor")!=null? attrs.get("rigor"):"";//严格计算 43 | //overflow:hidden;display:inline-block;white-space:nowrap; 44 | sb.append(String 45 | .format( 46 | "
"+ 47 | "
", 49 | width, height, tagId, tagId, WIDGE_NAME, exps, format, prec, rigor, width, height, textAlign, ExcelConstant.WIDGET_BACKGROUND_COLOR, fontStyle, length/2)); 50 | return WIDGE_NAME; 51 | } 52 | return ""; 53 | } 54 | 55 | @Override 56 | public String parseHtml4View(String widgeType, StringBuilder sb, ExcelTable table ,ExcelTableTd td) throws Exception { 57 | double width = td.getWidthNum(); 58 | double height = td.getHeightNum(); 59 | String tagId = getTagId(table, WIDGE_NAME); 60 | String textAlign = td.getTextAlign(); 61 | String fontStyle = getFontStyle(td); 62 | 63 | if (isCur(widgeType)) { 64 | validate(widgeType); 65 | Map attrs = WidgeUtils.parseAttr(widgeType); 66 | int length = 0; 67 | width = width-2-2;//表格长度-padding-边框 68 | 69 | String exps = attrs.get("exps");//公式 70 | String format = attrs.get("format");//格式化 71 | String prec = attrs.get("prec")!=null? attrs.get("prec"):"";//精度 72 | String rigor = attrs.get("rigor")!=null? attrs.get("rigor"):"";//严格计算 73 | sb.append(String 74 | .format( 75 | "
"+ 76 | "
", 78 | width, height, tagId, tagId, WIDGE_NAME, exps, format, prec, rigor, width, height, textAlign, fontStyle, length/2)); 79 | return WIDGE_NAME; 80 | } 81 | return ""; 82 | } 83 | 84 | @Override 85 | public void validate(String widgeType) throws Exception{ 86 | 87 | } 88 | 89 | @Override 90 | public boolean isCur(String widgeType){ 91 | if (widgeType.toLowerCase().startsWith(WIDGE_NAME)){ 92 | return true; 93 | } 94 | return false; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Built-By: Administrator 3 | Build-Jdk: 1.7.0_45 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/com.codecraft/Excel2Html/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Fri Dec 09 16:03:28 CST 2016 3 | version=0.0.1-SNAPSHOT 4 | groupId=com.codecraft 5 | m2e.projectName=Excel2Html 6 | m2e.projectLocation=C\:\\Users\\Administrator\\Workspaces\\MyEclipse Professional 2014\\Excel2Html 7 | artifactId=Excel2Html 8 | -------------------------------------------------------------------------------- /target/classes/META-INF/maven/com.codecraft/Excel2Html/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.codecraft 6 | Excel2Html 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Excel2Html 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 3.8.1 22 | test 23 | 24 | 25 | 26 | org.apache.poi 27 | poi 28 | 3.12 29 | 30 | 31 | 32 | org.apache.poi 33 | poi-examples 34 | 3.12 35 | 36 | 37 | 38 | org.apache.poi 39 | poi-ooxml 40 | 3.12 41 | 42 | 43 | 44 | org.apache.poi 45 | poi-ooxml-schemas 46 | 3.12 47 | 48 | 49 | 50 | org.apache.poi 51 | poi-scratchpad 52 | 3.12 53 | 54 | 55 | 56 | org.apache.xmlbeans 57 | xmlbeans 58 | 2.3.0 59 | 60 | 61 | 62 | org.json 63 | json 64 | 20080701 65 | 66 | 67 | 68 | --------------------------------------------------------------------------------