├── src ├── test │ ├── resources │ │ ├── img │ │ │ ├── read-demo-1.png │ │ │ └── write-demo-2.png │ │ └── excel │ │ │ └── xlsx │ │ │ ├── data_file1.xlsx │ │ │ ├── data_file2.xlsx │ │ │ ├── template_file1.xlsx │ │ │ ├── template_file2.xlsx │ │ │ └── template_file3.xlsx │ └── java │ │ └── org │ │ └── hellojavaer │ │ └── poi │ │ └── excel │ │ └── utils │ │ ├── TestEnum.java │ │ ├── read │ │ ├── ReadDemo3.java │ │ ├── ReadDemo2.java │ │ ├── ReadDemo4.java │ │ └── ReadDemo1.java │ │ ├── ExcelReadExceptionFormat.java │ │ ├── TestBean.java │ │ └── write │ │ ├── WriteDemo3.java │ │ ├── WriteDemo1.java │ │ └── WriteDemo2.java └── main │ └── java │ └── org │ └── hellojavaer │ └── poi │ └── excel │ └── utils │ ├── ExcelType.java │ ├── write │ ├── ExcelWriteTheme.java │ ├── ExcelWriteRowProcessor.java │ ├── ExcelWriteCellProcessor.java │ ├── ExcelWriteCellValueMapping.java │ ├── ExcelWriteSheetProcessor.java │ ├── ExcelWriteFieldMapping.java │ ├── ExcelWriteException.java │ └── ExcelWriteContext.java │ ├── ExcelProcessController.java │ ├── read │ ├── ExcelReadRowProcessor.java │ ├── ExcelReadCellProcessor.java │ ├── ExcelReadCellValueMapping.java │ ├── ExcelCellValue.java │ ├── ExcelReadFieldMapping.java │ ├── ExcelReadSheetProcessor.java │ ├── ExcelReadContext.java │ └── ExcelReadException.java │ ├── common │ └── Assert.java │ └── ExcelUtils.java ├── .gitignore ├── README.md ├── pom.xml └── LICENSE /src/test/resources/img/read-demo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/img/read-demo-1.png -------------------------------------------------------------------------------- /src/test/resources/img/write-demo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/img/write-demo-2.png -------------------------------------------------------------------------------- /src/test/resources/excel/xlsx/data_file1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/excel/xlsx/data_file1.xlsx -------------------------------------------------------------------------------- /src/test/resources/excel/xlsx/data_file2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/excel/xlsx/data_file2.xlsx -------------------------------------------------------------------------------- /src/test/resources/excel/xlsx/template_file1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/excel/xlsx/template_file1.xlsx -------------------------------------------------------------------------------- /src/test/resources/excel/xlsx/template_file2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/excel/xlsx/template_file2.xlsx -------------------------------------------------------------------------------- /src/test/resources/excel/xlsx/template_file3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojavaer/poi-excel-utils/HEAD/src/test/resources/excel/xlsx/template_file3.xlsx -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/TestEnum.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils; 2 | 3 | /** 4 | * @author zoukaiming 5 | */ 6 | public enum TestEnum { 7 | AA, BB, CC; 8 | } 9 | -------------------------------------------------------------------------------- /.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 | /target 14 | 15 | .* -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/ExcelType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils; 17 | 18 | /** 19 | * @author zoukaiming 20 | */ 21 | public enum ExcelType { 22 | XLS, XLSX 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteTheme.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | /** 19 | * @author zoukaiming 20 | */ 21 | public class ExcelWriteTheme { 22 | 23 | public static final int BASE = 0; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/ExcelProcessController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils; 17 | 18 | /** 19 | * 20 | * @author zoukaiming 21 | */ 22 | public interface ExcelProcessController { 23 | 24 | void doSkip(); 25 | 26 | void doBreak(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadRowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import org.apache.poi.ss.usermodel.Row; 19 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 20 | 21 | /** 22 | * @author zoukaiming 23 | */ 24 | public interface ExcelReadRowProcessor { 25 | 26 | T process(ExcelProcessController controller, ExcelReadContext context, Row row, T t); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # poi-excel-utils 2 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.hellojavaer/poi-excel-utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.hellojavaer/poi-excel-utils/) 3 | [![GitHub release](https://img.shields.io/github/release/hellojavaer/poi-excel-utils.svg)](https://github.com/hellojavaer/poi-excel-utils/releases) 4 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 5 | 6 | ExcelUtils 7 | 8 | ### Reading example 9 | 10 | 11 | 12 | ### Writing example 13 | 14 | 15 | 16 | ## [Get some examples](https://github.com/hellojavaer/poi-excel-utils/tree/master/src/test/java/org/hellojavaer/poi/excel/utils) 17 | 18 | ## Download 19 | 20 | http://repo1.maven.org/maven2/org/hellojavaer/poi-excel-utils/ 21 | 22 | ## Maven 23 | 24 | ```xml 25 | 26 | org.hellojavaer 27 | poi-excel-utils 28 | x.x.x 29 | 30 | ``` 31 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteRowProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import org.apache.poi.ss.usermodel.Row; 19 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 20 | 21 | /** 22 | * @author zoukaiming 23 | */ 24 | public interface ExcelWriteRowProcessor { 25 | 26 | /** 27 | * 28 | * @param controller 29 | * @param context 30 | * @param t 31 | * @param row 32 | * @return 33 | */ 34 | void process(ExcelProcessController controller, ExcelWriteContext context, T t, Row row); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteCellProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import org.apache.poi.ss.usermodel.Cell; 19 | 20 | /** 21 | * @author zoukaiming 22 | */ 23 | public interface ExcelWriteCellProcessor { 24 | 25 | /** 26 | * Provide you a chance to modify cell value after system has written.
27 | * If null is returned, this cell will been removed. 28 | * 29 | * @param context 30 | * @param t 31 | * @param cell 32 | * @return 33 | */ 34 | void process(ExcelWriteContext context, Object fieldVal, Cell cell); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadCellProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import org.apache.poi.ss.usermodel.Cell; 19 | 20 | /** 21 | * Provide you a chance to modify current read cell value before the cell value is set to target object. 22 | * 23 | * @author zoukaiming 24 | */ 25 | public interface ExcelReadCellProcessor { 26 | 27 | /** 28 | * @param context 29 | * @param cell 30 | * @param cellValue 31 | * @return value. if return cellValue, cellValue.getOriginalValue() will be 32 | * set as final result. 33 | */ 34 | Object process(ExcelReadContext context, Cell cell, ExcelCellValue cellValue); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/common/Assert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.common; 17 | 18 | /** 19 | * 20 | * @author zoukaiming 2016年4月2日 下午8:28:11 21 | */ 22 | public class Assert { 23 | 24 | public static void notNull(Object object) { 25 | notNull(object, "[Assertion failed] - the object argument must be null"); 26 | } 27 | 28 | public static void notNull(Object object, String message) { 29 | if (object == null) { 30 | throw new IllegalArgumentException(message); 31 | } 32 | } 33 | 34 | public static void isTrue(boolean expression) { 35 | isTrue(expression, "[Assertion failed] - this expression must be true"); 36 | } 37 | 38 | public static void isTrue(boolean expression, String message) { 39 | if (!expression) { 40 | throw new IllegalArgumentException(message); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/read/ReadDemo3.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.read; 2 | 3 | import org.apache.poi.ss.usermodel.Cell; 4 | import org.apache.poi.ss.usermodel.Row; 5 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 6 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 7 | import org.hellojavaer.poi.excel.utils.TestBean; 8 | 9 | import java.io.FileNotFoundException; 10 | import java.io.InputStream; 11 | import java.util.List; 12 | 13 | /** 14 | * @author zoukaiming 15 | */ 16 | public class ReadDemo3 { 17 | 18 | public static void main(String[] args) throws FileNotFoundException { 19 | InputStream in = ReadDemo3.class.getResourceAsStream("/excel/xlsx/data_file1.xlsx"); 20 | ExcelReadSheetProcessor sheetProcessor = new ExcelReadSheetProcessor() { 21 | 22 | @Override 23 | public void beforeProcess(ExcelReadContext context) { 24 | } 25 | 26 | @Override 27 | public void process(ExcelReadContext context, List list) { 28 | } 29 | 30 | @Override 31 | public void onException(ExcelReadContext context, ExcelReadException e) { 32 | throw e; 33 | } 34 | 35 | @Override 36 | public void afterProcess(ExcelReadContext context) { 37 | } 38 | }; 39 | 40 | sheetProcessor.setSheetIndex(0);// required.it can be replaced with 'setSheetName(sheetName)'; 41 | sheetProcessor.setStartRowIndex(1);// 42 | // sheetProcessor.setRowEndIndex(3);// 43 | sheetProcessor.setPageSize(2);// 44 | sheetProcessor.setRowProcessor(new ExcelReadRowProcessor() { 45 | 46 | public TestBean process(ExcelProcessController controller, ExcelReadContext context, Row row, 47 | TestBean t) { 48 | if (row != null) { 49 | Cell cell = row.getCell(0); 50 | System.out.println(ExcelUtils.readCell(cell)); 51 | } 52 | return t; 53 | } 54 | }); 55 | ExcelUtils.read(in, sheetProcessor); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/ExcelReadExceptionFormat.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils; 2 | 3 | import org.hellojavaer.poi.excel.utils.read.ExcelReadException; 4 | 5 | /** 6 | * 7 | * @author zoukaiming,created on 08/12/2016. 8 | */ 9 | public class ExcelReadExceptionFormat { 10 | 11 | public static String format(ExcelReadException e) { 12 | StringBuilder sb = new StringBuilder(); 13 | if (e.getCode() == ExcelReadException.CODE_OF_SHEET_NOT_EXIST) { 14 | sb.append("表:"); 15 | if (e.getSheetName() != null) { 16 | sb.append(e.getSheetName()); 17 | } 18 | if (e.getSheetIndex() != null) { 19 | sb.append('['); 20 | sb.append(e.getSheetIndex()); 21 | sb.append(']'); 22 | } 23 | sb.append("不存在"); 24 | return sb.toString(); 25 | } 26 | if (e.getCode() == ExcelReadException.CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH) { 27 | sb.append("表名:"); 28 | sb.append(e.getSheetName()); 29 | sb.append("和表索引:["); 30 | sb.append(e.getSheetIndex()); 31 | sb.append("]"); 32 | sb.append("不匹配"); 33 | return sb.toString(); 34 | } 35 | if (e.getCode() == ExcelReadException.CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY) { 36 | sb.append("表名和索引不能都为空"); 37 | return sb.toString(); 38 | } 39 | sb.append("表 "); 40 | sb.append(e.getSheetName()); 41 | //sb.append("["); 42 | //sb.append(e.getSheetIndex()); 43 | //sb.append("]"); 44 | if (e.getRowIndex() == null) { 45 | sb.append(" 在处理表数据时异常"); 46 | } else { 47 | sb.append(" , 第 "); 48 | sb.append(e.getRowIndex()); 49 | sb.append(" 行"); 50 | if (e.getColIndex() == null) { 51 | sb.append("时处理异常"); 52 | } else { 53 | sb.append(", 第 "); 54 | sb.append(e.getColStrIndex()); 55 | sb.append(" 列"); 56 | if (e.getCode() == ExcelReadException.CODE_OF_PROCESS_EXCEPTION) { 57 | sb.append(",数据处理异常,请校验数据格式的正确性."); 58 | } else if (e.getCode() == ExcelReadException.CODE_OF_CELL_VALUE_NOT_MATCH) { 59 | sb.append(",所输入的值不合法,请校验数据格式的正确性."); 60 | } else if (e.getCode() == ExcelReadException.CODE_OF_CELL_VALUE_REQUIRED) { 61 | sb.append("是必填项."); 62 | } 63 | } 64 | } 65 | return sb.toString(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadCellValueMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import org.hellojavaer.poi.excel.utils.write.ExcelWriteCellValueMapping; 19 | 20 | import java.util.HashMap; 21 | 22 | /** 23 | * Config the mapping between source value(which must be convertd to type of 24 | * String) to target value.
25 | * If you have used this configration, it also requries that very source value 26 | * must have a target value. If not, {@code #ExcelWriteException} will been 27 | * thrown. To process this case, you can use 'setDefaultValue' method or 28 | * 'setDefaultProcessor' to set default value. 29 | * 30 | * @see ExcelWriteCellValueMapping 31 | * @author zoukaiming 32 | */ 33 | public class ExcelReadCellValueMapping extends HashMap { 34 | 35 | private static final long serialVersionUID = 1L; 36 | 37 | private static final Object DEFAULT_INPUT = new Object(); 38 | private boolean useDefaultValue = false; 39 | private Object defaultValue = null; 40 | private ExcelReadCellProcessor defaultProcessor; 41 | 42 | public Object getDefaultValue() { 43 | return this.defaultValue; 44 | } 45 | 46 | public void setDefaultValue(Object val) { 47 | this.defaultValue = val; 48 | this.useDefaultValue = true; 49 | } 50 | 51 | public void setDefaultValueWithDefaultInput() { 52 | this.defaultValue = DEFAULT_INPUT; 53 | this.useDefaultValue = true; 54 | } 55 | 56 | public void resetDefaultValue() { 57 | this.defaultValue = null; 58 | this.useDefaultValue = false; 59 | } 60 | 61 | public boolean isUseDefaultValue() { 62 | return useDefaultValue; 63 | } 64 | 65 | public boolean isUseDefaultValueWithDefaultInput() { 66 | return useDefaultValue && (defaultValue == DEFAULT_INPUT); 67 | } 68 | 69 | public ExcelReadCellProcessor getDefaultProcessor() { 70 | return defaultProcessor; 71 | } 72 | 73 | public void setDefaultProcessor(ExcelReadCellProcessor defaultProcessor) { 74 | this.defaultProcessor = defaultProcessor; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelCellValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import java.io.Serializable; 19 | import java.math.BigDecimal; 20 | import java.math.BigInteger; 21 | import java.util.Date; 22 | 23 | import com.alibaba.fastjson.util.TypeUtils; 24 | 25 | /** 26 | * provide rich methods for type castting. 27 | * 28 | * @author zoukaiming 29 | */ 30 | public class ExcelCellValue implements Serializable { 31 | 32 | private static final long serialVersionUID = 1L; 33 | private Object originalValue; 34 | 35 | public ExcelCellValue(Object originalValue) { 36 | this.originalValue = originalValue; 37 | } 38 | 39 | public Byte getByteValue() { 40 | return TypeUtils.castToByte(originalValue); 41 | } 42 | 43 | public Short getShortValue() { 44 | return TypeUtils.castToShort(originalValue); 45 | } 46 | 47 | public Integer getIntValue() { 48 | return TypeUtils.castToInt(originalValue); 49 | } 50 | 51 | public Long getLongValue() { 52 | return TypeUtils.castToLong(originalValue); 53 | } 54 | 55 | public Float getFloatValue() { 56 | return TypeUtils.castToFloat(originalValue); 57 | } 58 | 59 | public Double getDoubleValue() { 60 | return TypeUtils.castToDouble(originalValue); 61 | } 62 | 63 | public String getStringValue() { 64 | return TypeUtils.castToString(originalValue); 65 | } 66 | 67 | public Boolean getBooleanValue() { 68 | return TypeUtils.castToBoolean(originalValue); 69 | } 70 | 71 | public Date getDateValue() { 72 | return TypeUtils.castToDate(originalValue); 73 | } 74 | 75 | public BigDecimal getBigDecimal() { 76 | return TypeUtils.castToBigDecimal(originalValue); 77 | } 78 | 79 | public BigInteger getBigInteger() { 80 | return TypeUtils.castToBigInteger(originalValue); 81 | } 82 | 83 | public java.sql.Timestamp getTimestamp() { 84 | return TypeUtils.castToTimestamp(originalValue); 85 | } 86 | 87 | public Object getOriginalValue() { 88 | return originalValue; 89 | } 90 | 91 | @Override 92 | public String toString() { 93 | return TypeUtils.castToString(originalValue); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteCellValueMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import org.hellojavaer.poi.excel.utils.read.ExcelReadCellValueMapping; 19 | 20 | import java.util.HashMap; 21 | 22 | /** 23 | * Config the mapping between source value(which must be convertd to type of 24 | * String) to target value.
25 | * If you have used this configration, it also requries that very source value 26 | * must have a target value. If not, {@code #ExcelWriteException} will been 27 | * thrown. To process this case, you can use 'useDefaultValue' method or 28 | * 'setDefaultProcessor' to set default value. 29 | * 30 | * @see ExcelReadCellValueMapping 31 | * @author zoukaiming 32 | */ 33 | public class ExcelWriteCellValueMapping extends HashMap { 34 | 35 | private static final long serialVersionUID = 1L; 36 | 37 | private static final Object DEFAULT_INPUT = new Object(); 38 | private boolean useDefaultValue = false; 39 | private Object defaultValue = null; 40 | @SuppressWarnings("rawtypes") 41 | private ExcelWriteCellProcessor defaultProcessor; 42 | 43 | public Object getDefaultValue() { 44 | return this.defaultValue; 45 | } 46 | 47 | public void setDefaultValue(Object val) { 48 | this.defaultValue = val; 49 | this.useDefaultValue = true; 50 | } 51 | 52 | public void setDefaultValueWithDefaultInput() { 53 | this.defaultValue = DEFAULT_INPUT; 54 | this.useDefaultValue = true; 55 | } 56 | 57 | public void resetDefaultValue() { 58 | this.defaultValue = null; 59 | this.useDefaultValue = false; 60 | } 61 | 62 | public boolean isUseDefaultValue() { 63 | return useDefaultValue; 64 | } 65 | 66 | public boolean isUseDefaultValueWithDefaultInput() { 67 | return useDefaultValue && (defaultValue == DEFAULT_INPUT); 68 | } 69 | 70 | @SuppressWarnings("rawtypes") 71 | public ExcelWriteCellProcessor getDefaultProcessor() { 72 | return defaultProcessor; 73 | } 74 | 75 | public void setDefaultProcessor(@SuppressWarnings("rawtypes") ExcelWriteCellProcessor defaultProcessor) { 76 | this.defaultProcessor = defaultProcessor; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/TestBean.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * @author zoukaiming 8 | */ 9 | public class TestBean implements Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | private Byte byteField; 14 | private Short shortField; 15 | private Integer intField; 16 | private Long longField; 17 | private Float floatField; 18 | private Double doubleField; 19 | private Boolean boolField; 20 | private String stringField; 21 | private Date dateField; 22 | private String enumField1; 23 | private String enumField2; 24 | private String url; 25 | 26 | public Byte getByteField() { 27 | return byteField; 28 | } 29 | 30 | public void setByteField(Byte byteField) { 31 | this.byteField = byteField; 32 | } 33 | 34 | public Short getShortField() { 35 | return shortField; 36 | } 37 | 38 | public void setShortField(Short shortField) { 39 | this.shortField = shortField; 40 | } 41 | 42 | public Integer getIntField() { 43 | return intField; 44 | } 45 | 46 | public void setIntField(Integer intField) { 47 | this.intField = intField; 48 | } 49 | 50 | public Long getLongField() { 51 | return longField; 52 | } 53 | 54 | public void setLongField(Long longField) { 55 | this.longField = longField; 56 | } 57 | 58 | public Float getFloatField() { 59 | return floatField; 60 | } 61 | 62 | public void setFloatField(Float floatField) { 63 | this.floatField = floatField; 64 | } 65 | 66 | public Double getDoubleField() { 67 | return doubleField; 68 | } 69 | 70 | public void setDoubleField(Double doubleField) { 71 | this.doubleField = doubleField; 72 | } 73 | 74 | public Boolean getBoolField() { 75 | return boolField; 76 | } 77 | 78 | public void setBoolField(Boolean boolField) { 79 | this.boolField = boolField; 80 | } 81 | 82 | public String getStringField() { 83 | return stringField; 84 | } 85 | 86 | public void setStringField(String stringField) { 87 | this.stringField = stringField; 88 | } 89 | 90 | public Date getDateField() { 91 | return dateField; 92 | } 93 | 94 | public void setDateField(Date dateField) { 95 | this.dateField = dateField; 96 | } 97 | 98 | public String getEnumField1() { 99 | return enumField1; 100 | } 101 | 102 | public void setEnumField1(String enumField1) { 103 | this.enumField1 = enumField1; 104 | } 105 | 106 | public String getEnumField2() { 107 | return enumField2; 108 | } 109 | 110 | public void setEnumField2(String enumField2) { 111 | this.enumField2 = enumField2; 112 | } 113 | 114 | public String getUrl() { 115 | return url; 116 | } 117 | 118 | public void setUrl(String url) { 119 | this.url = url; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadFieldMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import java.io.Serializable; 19 | import java.util.LinkedHashMap; 20 | import java.util.Map; 21 | import java.util.concurrent.ConcurrentHashMap; 22 | 23 | import org.hellojavaer.poi.excel.utils.common.Assert; 24 | 25 | /** 26 | * @author zoukaiming 27 | */ 28 | public class ExcelReadFieldMapping implements Serializable { 29 | 30 | private static final long serialVersionUID = 1L; 31 | 32 | private Map> fieldMapping = new LinkedHashMap>(); 33 | 34 | public ExcelReadFieldMappingAttribute put(String colIndexOrColName, String fieldName) { 35 | Assert.notNull(colIndexOrColName); 36 | Assert.notNull(fieldName); 37 | Map map = fieldMapping.get(colIndexOrColName); 38 | if (map == null) { 39 | synchronized (fieldMapping) { 40 | if (fieldMapping.get(colIndexOrColName) == null) { 41 | map = new ConcurrentHashMap(); 42 | fieldMapping.put(colIndexOrColName, map); 43 | } 44 | } 45 | } 46 | ExcelReadFieldMappingAttribute attribute = new ExcelReadFieldMappingAttribute(); 47 | map.put(fieldName, attribute); 48 | return attribute; 49 | } 50 | 51 | public Map> export() { 52 | return fieldMapping; 53 | } 54 | 55 | public class ExcelReadFieldMappingAttribute implements Serializable { 56 | 57 | private static final long serialVersionUID = 1L; 58 | 59 | private boolean required = false; 60 | private ExcelReadCellProcessor cellProcessor; 61 | private ExcelReadCellValueMapping valueMapping; 62 | private String linkField; 63 | 64 | public ExcelReadFieldMappingAttribute setRequired(boolean required) { 65 | this.required = required; 66 | return this; 67 | } 68 | 69 | public ExcelReadFieldMappingAttribute setCellProcessor(ExcelReadCellProcessor cellProcessor) { 70 | this.cellProcessor = cellProcessor; 71 | return this; 72 | } 73 | 74 | public ExcelReadFieldMappingAttribute setValueMapping(ExcelReadCellValueMapping valueMapping) { 75 | this.valueMapping = valueMapping; 76 | return this; 77 | } 78 | 79 | public ExcelReadFieldMappingAttribute setLinkField(String linkField) { 80 | this.linkField = linkField; 81 | return this; 82 | } 83 | 84 | public boolean isRequired() { 85 | return required; 86 | } 87 | 88 | public ExcelReadCellProcessor getCellProcessor() { 89 | return cellProcessor; 90 | } 91 | 92 | public ExcelReadCellValueMapping getValueMapping() { 93 | return valueMapping; 94 | } 95 | 96 | public String getLinkField() { 97 | return linkField; 98 | } 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/read/ReadDemo2.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.read; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.apache.poi.ss.usermodel.Cell; 6 | import org.apache.poi.ss.usermodel.Row; 7 | import org.hellojavaer.poi.excel.utils.*; 8 | 9 | import java.io.FileNotFoundException; 10 | import java.io.InputStream; 11 | import java.util.List; 12 | 13 | /** 14 | * @author zoukaiming 15 | */ 16 | public class ReadDemo2 { 17 | 18 | public static void main(String[] args) throws FileNotFoundException { 19 | InputStream in = ReadDemo2.class.getResourceAsStream("/excel/xlsx/data_file1.xlsx"); 20 | ExcelReadSheetProcessor sheetProcessor = new ExcelReadSheetProcessor() { 21 | 22 | @Override 23 | public void beforeProcess(ExcelReadContext context) { 24 | 25 | } 26 | 27 | @Override 28 | public void process(ExcelReadContext context, List list) { 29 | System.out.println(JSONObject.toJSONString(list, SerializerFeature.WriteDateUseDateFormat)); 30 | } 31 | 32 | @Override 33 | public void onException(ExcelReadContext context, ExcelReadException e) { 34 | throw e; 35 | } 36 | 37 | @Override 38 | public void afterProcess(ExcelReadContext context) { 39 | 40 | } 41 | }; 42 | ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping(); 43 | fieldMapping.put("byte", "byteField").setRequired(true); 44 | fieldMapping.put("short", "shortField"); 45 | fieldMapping.put("int", "intField"); 46 | fieldMapping.put("long", "longField"); 47 | fieldMapping.put("float", "floatField"); 48 | fieldMapping.put("double", "doubleField"); 49 | fieldMapping.put("boolean", "boolField"); 50 | fieldMapping.put("string", "stringField"); 51 | fieldMapping.put("date", "dateField"); 52 | 53 | fieldMapping.put("enum1", "enumField1").setCellProcessor(new ExcelReadCellProcessor() { 54 | 55 | public Object process(ExcelReadContext context, Cell cell, ExcelCellValue cellValue) { 56 | throw new ExcelReadException("test throw exception"); 57 | //return cellValue.getStringValue() + "=>row:" + context.getCurRowIndex() + ",col:" 58 | // + context.getCurColStrIndex(); 59 | } 60 | }); 61 | 62 | ExcelReadCellValueMapping valueMapping = new ExcelReadCellValueMapping(); 63 | valueMapping.put("Please select", null); 64 | valueMapping.put("Option1", TestEnum.AA.toString()); 65 | valueMapping.put("Option2", TestEnum.BB.toString()); 66 | valueMapping.put("Option3", TestEnum.CC.toString()); 67 | // valueMapping.setDefaultValueWithDefaultInput(); 68 | fieldMapping.put("enum2", "enumField2").setValueMapping(valueMapping).setRequired(false); 69 | 70 | sheetProcessor.setSheetIndex(0);// required.it can be replaced with 'setSheetName(sheetName)'; 71 | sheetProcessor.setStartRowIndex(1);// 72 | // sheetProcessor.setRowEndIndex(3);// 73 | sheetProcessor.setTargetClass(TestBean.class);// required 74 | sheetProcessor.setFieldMapping(fieldMapping);// required 75 | sheetProcessor.setPageSize(2);// 76 | sheetProcessor.setTrimSpace(true); 77 | sheetProcessor.setHeadRowIndex(0); 78 | sheetProcessor.setRowProcessor(new ExcelReadRowProcessor() { 79 | 80 | public TestBean process(ExcelProcessController controller, ExcelReadContext context, Row row, 81 | TestBean t) { 82 | return t; 83 | } 84 | }); 85 | 86 | try { 87 | ExcelUtils.read(in, sheetProcessor); 88 | } catch (ExcelReadException e) { 89 | System.out.println(ExcelReadExceptionFormat.format(e)); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/write/WriteDemo3.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.write; 2 | 3 | import org.apache.poi.ss.usermodel.Cell; 4 | import org.apache.poi.ss.usermodel.CellStyle; 5 | import org.hellojavaer.poi.excel.utils.ExcelType; 6 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 7 | 8 | import java.io.File; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.net.URL; 12 | import java.util.*; 13 | import java.util.concurrent.atomic.AtomicBoolean; 14 | 15 | /** 16 | * @author zoukaiming 17 | */ 18 | public class WriteDemo3 { 19 | 20 | public static void main(String[] args) throws IOException { 21 | URL url = WriteDemo3.class.getResource("/"); 22 | final String outputFilePath = url.getPath() + "output_file3.xlsx"; 23 | File outputFile = new File(outputFilePath); 24 | outputFile.createNewFile(); 25 | FileOutputStream output = new FileOutputStream(outputFile); 26 | final AtomicBoolean b = new AtomicBoolean(false); 27 | 28 | ExcelWriteSheetProcessor sheetProcessor = new ExcelWriteSheetProcessor() { 29 | 30 | @Override 31 | public void beforeProcess(ExcelWriteContext context) { 32 | System.out.println("write excel start!"); 33 | } 34 | 35 | @Override 36 | public void onException(ExcelWriteContext context, ExcelWriteException e) { 37 | throw e; 38 | } 39 | 40 | @Override 41 | public void afterProcess(ExcelWriteContext context) { 42 | 43 | Cell cell = context.setCellValue(context.getCurRowIndex() + 2, context.getCurRowIndex() + 4, 0, 8, 44 | "Thinks for using pio-excel-utils!"); 45 | CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); 46 | cellStyle.setWrapText(true); 47 | cell.setCellStyle(cellStyle); 48 | System.out.println("write excel end!"); 49 | System.out.println("output file path is " + outputFilePath); 50 | } 51 | }; 52 | 53 | ExcelWriteFieldMapping fieldMapping = new ExcelWriteFieldMapping(); 54 | fieldMapping.put("A", "byteField").setHead("byteField"); 55 | fieldMapping.put("B", "shortField").setHead("shortField"); 56 | fieldMapping.put("C", "intField").setHead("intField"); 57 | fieldMapping.put("D", "longField").setHead("longField"); 58 | fieldMapping.put("E", "floatField").setHead("floatField"); 59 | fieldMapping.put("F", "doubleField").setHead("doubleField"); 60 | fieldMapping.put("G", "boolField").setHead("boolField"); 61 | fieldMapping.put("H", "stringField").setHead("stringField"); 62 | fieldMapping.put("I", "dateField").setHead("dateField"); 63 | 64 | sheetProcessor.setSheetIndex(0);// required. It can be replaced with 'setSheetName(sheetName)'; 65 | sheetProcessor.setStartRowIndex(1);// 66 | sheetProcessor.setFieldMapping(fieldMapping);// required 67 | sheetProcessor.setHeadRowIndex(0); 68 | // sheetProcessor.setTemplateRowIndex(1); 69 | sheetProcessor.setDataList(getDateList()); 70 | 71 | ExcelUtils.write(ExcelType.XLSX, output, sheetProcessor); 72 | } 73 | 74 | private static List getDateList() { 75 | List list = new ArrayList(); 76 | Map map = new HashMap(); 77 | map.put("byteField", (byte) 1); 78 | map.put("shortField", (short) 2); 79 | map.put("intField", 3); 80 | map.put("longField", 4L); 81 | map.put("floatField", 5.1f); 82 | map.put("doubleField", 6.23); 83 | map.put("boolField", true); 84 | map.put("dateField", new Date()); 85 | map.put("enumField1", "enumField1"); 86 | map.put("enumField2", "enumField2"); 87 | map.put("stringField", "map_test"); 88 | list.add(map); 89 | list.add(map); 90 | list.add(map); 91 | return list; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/read/ReadDemo4.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.read; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.apache.poi.ss.usermodel.Cell; 6 | import org.apache.poi.ss.usermodel.Row; 7 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 8 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 9 | import org.hellojavaer.poi.excel.utils.TestEnum; 10 | 11 | import java.io.FileNotFoundException; 12 | import java.io.InputStream; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | 16 | /** 17 | * @author zoukaiming 18 | */ 19 | public class ReadDemo4 { 20 | 21 | public static void main(String[] args) throws FileNotFoundException { 22 | InputStream in = ReadDemo4.class.getResourceAsStream("/excel/xlsx/data_file1.xlsx"); 23 | ExcelReadSheetProcessor sheetProcessor = new ExcelReadSheetProcessor() { 24 | 25 | @Override 26 | public void beforeProcess(ExcelReadContext context) { 27 | 28 | } 29 | 30 | @Override 31 | public void process(ExcelReadContext context, List list) { 32 | System.out.println(JSONObject.toJSONString(list, SerializerFeature.WriteDateUseDateFormat)); 33 | } 34 | 35 | @Override 36 | public void onException(ExcelReadContext context, ExcelReadException e) { 37 | throw e; 38 | } 39 | 40 | @Override 41 | public void afterProcess(ExcelReadContext context) { 42 | 43 | } 44 | }; 45 | ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping(); 46 | fieldMapping.put("byte", "byteField").setRequired(true); 47 | fieldMapping.put("short", "shortField"); 48 | fieldMapping.put("int", "intField"); 49 | fieldMapping.put("long", "longField"); 50 | fieldMapping.put("float", "floatField"); 51 | fieldMapping.put("double", "doubleField"); 52 | fieldMapping.put("boolean", "boolField"); 53 | fieldMapping.put("string", "stringField"); 54 | fieldMapping.put("date", "dateField"); 55 | 56 | fieldMapping.put("enum1", "enumField1").setCellProcessor(new ExcelReadCellProcessor() { 57 | 58 | public Object process(ExcelReadContext context, Cell cell, ExcelCellValue cellValue) { 59 | // throw new ExcelReadException("test throw exception"); 60 | return cellValue.getStringValue() + "=>row:" + context.getCurRowIndex() + ",col:" 61 | + context.getCurColStrIndex(); 62 | } 63 | }); 64 | 65 | ExcelReadCellValueMapping valueMapping = new ExcelReadCellValueMapping(); 66 | valueMapping.put("Please select", null); 67 | valueMapping.put("Option1", TestEnum.AA.toString()); 68 | valueMapping.put("Option2", TestEnum.BB.toString()); 69 | valueMapping.put("Option3", TestEnum.CC.toString()); 70 | // valueMapping.setDefaultValueWithDefaultInput(); 71 | fieldMapping.put("enum2", "enumField2").setValueMapping(valueMapping).setRequired(false); 72 | 73 | sheetProcessor.setSheetIndex(0);// required.it can be replaced with 'setSheetName(sheetName)'; 74 | sheetProcessor.setStartRowIndex(1);// 75 | // sheetProcessor.setRowEndIndex(3);// 76 | sheetProcessor.setTargetClass(HashMap.class);// required 77 | sheetProcessor.setFieldMapping(fieldMapping);// required 78 | sheetProcessor.setPageSize(2);// 79 | sheetProcessor.setTrimSpace(true); 80 | sheetProcessor.setHeadRowIndex(0); 81 | sheetProcessor.setRowProcessor(new ExcelReadRowProcessor() { 82 | 83 | @Override 84 | public HashMap process(ExcelProcessController controller, ExcelReadContext context, Row row, 85 | HashMap t) { 86 | return t; 87 | } 88 | }); 89 | 90 | ExcelUtils.read(in, sheetProcessor); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/write/WriteDemo1.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.write; 2 | 3 | import org.apache.poi.ss.usermodel.Cell; 4 | import org.apache.poi.ss.usermodel.CellStyle; 5 | import org.hellojavaer.poi.excel.utils.ExcelType; 6 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 7 | import org.hellojavaer.poi.excel.utils.TestBean; 8 | 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | import java.net.URL; 13 | import java.util.ArrayList; 14 | import java.util.Date; 15 | import java.util.List; 16 | import java.util.concurrent.atomic.AtomicBoolean; 17 | 18 | /** 19 | * @author zoukaiming 20 | */ 21 | public class WriteDemo1 { 22 | 23 | public static void main(String[] args) throws IOException { 24 | URL url = WriteDemo1.class.getResource("/"); 25 | final String outputFilePath = url.getPath() + "output_file1.xlsx"; 26 | File outputFile = new File(outputFilePath); 27 | outputFile.createNewFile(); 28 | FileOutputStream output = new FileOutputStream(outputFile); 29 | final AtomicBoolean b = new AtomicBoolean(false); 30 | 31 | ExcelWriteSheetProcessor sheetProcessor = new ExcelWriteSheetProcessor() { 32 | 33 | @Override 34 | public void beforeProcess(ExcelWriteContext context) { 35 | System.out.println("write excel start!"); 36 | } 37 | 38 | @Override 39 | public void onException(ExcelWriteContext context, ExcelWriteException e) { 40 | throw e; 41 | } 42 | 43 | @Override 44 | public void afterProcess(ExcelWriteContext context) { 45 | 46 | Cell cell = context.setCellValue(context.getCurRowIndex() + 2, context.getCurRowIndex() + 4, 0, 8, 47 | "Thinks for using pio-excel-utils!"); 48 | CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); 49 | cellStyle.setWrapText(true); 50 | cell.setCellStyle(cellStyle); 51 | System.out.println("write excel end!"); 52 | System.out.println("output file path is " + outputFilePath); 53 | } 54 | }; 55 | 56 | ExcelWriteFieldMapping fieldMapping = new ExcelWriteFieldMapping(); 57 | fieldMapping.put("A", "byteField").setHead("byteField"); 58 | fieldMapping.put("B", "shortField").setHead("shortField"); 59 | fieldMapping.put("C", "intField").setHead("intField"); 60 | fieldMapping.put("D", "longField").setHead("longField"); 61 | fieldMapping.put("E", "floatField").setHead("floatField"); 62 | fieldMapping.put("F", "doubleField").setHead("doubleField"); 63 | fieldMapping.put("G", "boolField").setHead("boolField"); 64 | fieldMapping.put("H", "stringField").setHead("stringField"); 65 | fieldMapping.put("I", "dateField").setHead("dateField"); 66 | 67 | sheetProcessor.setSheetIndex(0);// required. It can be replaced with 'setSheetName(sheetName)'; 68 | sheetProcessor.setStartRowIndex(1);// 69 | sheetProcessor.setFieldMapping(fieldMapping);// required 70 | sheetProcessor.setHeadRowIndex(0); 71 | // sheetProcessor.setTemplateRowIndex(1); 72 | sheetProcessor.setDataList(getDateList()); 73 | 74 | ExcelUtils.write(ExcelType.XLSX, output, sheetProcessor); 75 | } 76 | 77 | private static List getDateList() { 78 | List list = new ArrayList(); 79 | TestBean bean = new TestBean(); 80 | bean.setByteField((byte) 1); 81 | bean.setShortField((short) 2); 82 | bean.setIntField(3); 83 | bean.setLongField(4L); 84 | bean.setFloatField(5.1f); 85 | bean.setDoubleField(6.23); 86 | bean.setBoolField(true); 87 | bean.setEnumField1("enumField1"); 88 | bean.setEnumField2("enumField2"); 89 | bean.setDateField(new Date()); 90 | bean.setStringField("test"); 91 | 92 | list.add(bean); 93 | list.add(bean); 94 | list.add(bean); 95 | return list; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteSheetProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import org.hellojavaer.poi.excel.utils.common.Assert; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * @author zoukaiming 24 | */ 25 | public abstract class ExcelWriteSheetProcessor { 26 | 27 | public abstract void beforeProcess(ExcelWriteContext context); 28 | 29 | public abstract void onException(ExcelWriteContext context, ExcelWriteException e); 30 | 31 | public abstract void afterProcess(ExcelWriteContext context); 32 | 33 | private Integer sheetIndex; 34 | private String sheetName; 35 | private int startRowIndex = 0; 36 | private Integer templateStartRowIndex; 37 | private Integer templateEndRowIndex; 38 | private ExcelWriteFieldMapping fieldMapping; 39 | private ExcelWriteRowProcessor rowProcessor; 40 | private boolean trimSpace = false; 41 | private Integer headRowIndex; 42 | private List dataList; 43 | private Integer theme; 44 | 45 | public Integer getSheetIndex() { 46 | return sheetIndex; 47 | } 48 | 49 | public void setSheetIndex(Integer sheetIndex) { 50 | this.sheetIndex = sheetIndex; 51 | } 52 | 53 | public String getSheetName() { 54 | return sheetName; 55 | } 56 | 57 | public void setSheetName(String sheetName) { 58 | this.sheetName = sheetName; 59 | } 60 | 61 | public int getStartRowIndex() { 62 | return startRowIndex; 63 | } 64 | 65 | public void setStartRowIndex(int startRowIndex) { 66 | this.startRowIndex = startRowIndex; 67 | } 68 | 69 | public ExcelWriteFieldMapping getFieldMapping() { 70 | return fieldMapping; 71 | } 72 | 73 | public void setFieldMapping(ExcelWriteFieldMapping fieldMapping) { 74 | this.fieldMapping = fieldMapping; 75 | } 76 | 77 | public void setTemplateRows(Integer start, Integer end) { 78 | Assert.isTrue(start != null && end != null && start <= end || start == null && end == null); 79 | this.templateStartRowIndex = start; 80 | this.templateEndRowIndex = end; 81 | } 82 | 83 | public Integer getTemplateStartRowIndex() { 84 | return templateStartRowIndex; 85 | } 86 | 87 | public Integer getTemplateEndRowIndex() { 88 | return templateEndRowIndex; 89 | } 90 | 91 | public ExcelWriteRowProcessor getRowProcessor() { 92 | return rowProcessor; 93 | } 94 | 95 | public void setRowProcessor(ExcelWriteRowProcessor rowProcessor) { 96 | this.rowProcessor = rowProcessor; 97 | } 98 | 99 | public boolean isTrimSpace() { 100 | return trimSpace; 101 | } 102 | 103 | public void setTrimSpace(boolean trimSpace) { 104 | this.trimSpace = trimSpace; 105 | } 106 | 107 | public Integer getHeadRowIndex() { 108 | return headRowIndex; 109 | } 110 | 111 | public void setHeadRowIndex(Integer headRowIndex) { 112 | this.headRowIndex = headRowIndex; 113 | } 114 | 115 | public List getDataList() { 116 | return dataList; 117 | } 118 | 119 | public void setDataList(List dataList) { 120 | this.dataList = dataList; 121 | } 122 | 123 | public Integer getTheme() { 124 | return theme; 125 | } 126 | 127 | public void setTheme(Integer theme) { 128 | this.theme = theme; 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/read/ReadDemo1.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.read; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.apache.poi.ss.usermodel.Cell; 6 | import org.apache.poi.ss.usermodel.Row; 7 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 8 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 9 | import org.hellojavaer.poi.excel.utils.TestBean; 10 | import org.hellojavaer.poi.excel.utils.TestEnum; 11 | 12 | import java.io.InputStream; 13 | import java.util.List; 14 | 15 | /** 16 | * @author zoukaiming 17 | */ 18 | public class ReadDemo1 { 19 | 20 | public static void main(String[] args) throws Throwable { 21 | InputStream in = ReadDemo1.class.getResourceAsStream("/excel/xlsx/data_file1.xlsx"); 22 | ExcelReadSheetProcessor sheetProcessor = new ExcelReadSheetProcessor() { 23 | 24 | @Override 25 | public void beforeProcess(ExcelReadContext context) { 26 | } 27 | 28 | @Override 29 | public void process(ExcelReadContext context, List list) { 30 | System.out.println(JSONObject.toJSONString(list, SerializerFeature.WriteDateUseDateFormat)); 31 | // throw new IllegalStateException("step3."); 32 | // throw new ExcelReadException("step3."); 33 | } 34 | 35 | @Override 36 | public void onException(ExcelReadContext context, ExcelReadException e) { 37 | throw e; 38 | } 39 | 40 | @Override 41 | public void afterProcess(ExcelReadContext context) { 42 | 43 | } 44 | }; 45 | ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping(); 46 | fieldMapping.put("A", "byteField").setRequired(true).setLinkField("url"); 47 | fieldMapping.put("B", "shortField"); 48 | fieldMapping.put("C", "intField"); 49 | fieldMapping.put("D", "longField"); 50 | fieldMapping.put("E", "floatField"); 51 | fieldMapping.put("F", "doubleField"); 52 | fieldMapping.put("G", "boolField"); 53 | fieldMapping.put("H", "stringField"); 54 | fieldMapping.put("I", "dateField"); 55 | 56 | fieldMapping.put("J", "enumField1").setCellProcessor(new ExcelReadCellProcessor() { 57 | 58 | public Object process(ExcelReadContext context, Cell cell, ExcelCellValue cellValue) { 59 | // throw new ExcelReadException("step1."); 60 | // throw new IllegalStateException("step1."); 61 | return cellValue.getStringValue() + "=>row:" + context.getCurRowIndex() + ",col:" 62 | + context.getCurColStrIndex(); 63 | } 64 | }); 65 | 66 | ExcelReadCellValueMapping valueMapping = new ExcelReadCellValueMapping(); 67 | valueMapping.put(null, null); 68 | valueMapping.put("Please select", null); 69 | valueMapping.put("Option1", TestEnum.AA.toString()); 70 | valueMapping.put("Option2", TestEnum.BB.toString()); 71 | valueMapping.put("Option3", TestEnum.CC.toString()); 72 | // valueMapping.setDefaultValueWithDefaultInput(); 73 | fieldMapping.put("K", "enumField2").setValueMapping(valueMapping); 74 | 75 | sheetProcessor.setSheetIndex(0);// required.it can be replaced with 'setSheetName(sheetName)'; 76 | sheetProcessor.setStartRowIndex(1);// 77 | // sheetProcessor.setRowEndIndex(3);// 78 | sheetProcessor.setTargetClass(TestBean.class);// required 79 | sheetProcessor.setFieldMapping(fieldMapping);// required 80 | sheetProcessor.setPageSize(2);// 81 | sheetProcessor.setTrimSpace(true); 82 | sheetProcessor.setRowProcessor(new ExcelReadRowProcessor() { 83 | 84 | public TestBean process(ExcelProcessController controller, ExcelReadContext context, Row row, 85 | TestBean t) { 86 | // throw new ExcelReadException("step2."); 87 | // throw new IllegalStateException("step2."); 88 | return t; 89 | } 90 | }); 91 | 92 | try { 93 | ExcelUtils.read(in, sheetProcessor); 94 | } catch (ExcelReadException e) { 95 | // throw e.getCause(); 96 | // System.out.println(e.getMessage()); 97 | e.printStackTrace(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteFieldMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import java.io.Serializable; 19 | import java.util.LinkedHashMap; 20 | import java.util.Map; 21 | import java.util.concurrent.ConcurrentHashMap; 22 | 23 | import org.apache.poi.common.usermodel.Hyperlink; 24 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 25 | import org.springframework.util.Assert; 26 | 27 | /** 28 | * Config the mapping between excel column(by index) to Object field(by name). 29 | * 30 | * @author zoukaiming 31 | */ 32 | public class ExcelWriteFieldMapping implements Serializable { 33 | 34 | private static final long serialVersionUID = 1L; 35 | 36 | private Map> fieldMapping = new LinkedHashMap>(); 37 | 38 | public ExcelWriteFieldMappingAttribute put(String colIndex, String fieldName) { 39 | Assert.notNull(colIndex); 40 | Assert.notNull(fieldName); 41 | Map map = fieldMapping.get(fieldName); 42 | if (map == null) { 43 | synchronized (fieldMapping) { 44 | if (fieldMapping.get(colIndex) == null) { 45 | map = new ConcurrentHashMap(); 46 | fieldMapping.put(fieldName, map); 47 | } 48 | } 49 | } 50 | ExcelWriteFieldMappingAttribute attribute = new ExcelWriteFieldMappingAttribute(); 51 | map.put(ExcelUtils.convertColCharIndexToIntIndex(colIndex), attribute); 52 | return attribute; 53 | } 54 | 55 | public Map> export() { 56 | return fieldMapping; 57 | } 58 | 59 | public class ExcelWriteFieldMappingAttribute implements Serializable { 60 | 61 | private static final long serialVersionUID = 1L; 62 | @SuppressWarnings("rawtypes") 63 | private ExcelWriteCellProcessor cellProcessor; 64 | private ExcelWriteCellValueMapping valueMapping; 65 | private String head; 66 | private String linkField; 67 | private int linkType; 68 | 69 | @SuppressWarnings("rawtypes") 70 | public ExcelWriteFieldMappingAttribute setCellProcessor(ExcelWriteCellProcessor cellProcessor) { 71 | this.cellProcessor = cellProcessor; 72 | return this; 73 | } 74 | 75 | public ExcelWriteFieldMappingAttribute setValueMapping(ExcelWriteCellValueMapping valueMapping) { 76 | this.valueMapping = valueMapping; 77 | return this; 78 | } 79 | 80 | public ExcelWriteFieldMappingAttribute setHead(String head) { 81 | this.head = head; 82 | return this; 83 | } 84 | 85 | public ExcelWriteFieldMappingAttribute setLinkField(String linkField) { 86 | this.linkField = linkField; 87 | this.linkType = Hyperlink.LINK_URL; 88 | return this; 89 | } 90 | 91 | public ExcelWriteFieldMappingAttribute setLink(String linkFieldName, int linkType) { 92 | this.linkField = linkFieldName; 93 | this.linkType = Hyperlink.LINK_URL; 94 | return this; 95 | } 96 | 97 | @SuppressWarnings("rawtypes") 98 | public ExcelWriteCellProcessor getCellProcessor() { 99 | return cellProcessor; 100 | } 101 | 102 | public ExcelWriteCellValueMapping getValueMapping() { 103 | return valueMapping; 104 | } 105 | 106 | public String getHead() { 107 | return head; 108 | } 109 | 110 | public String getLinkField() { 111 | return linkField; 112 | } 113 | 114 | public int getLinkType() { 115 | return linkType; 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadSheetProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * @author zoukaiming 22 | */ 23 | public abstract class ExcelReadSheetProcessor { 24 | 25 | private Integer sheetIndex; 26 | private String sheetName; 27 | private Class targetClass; 28 | private int startRowIndex = 0; 29 | private Integer endRowIndex; 30 | private Integer pageSize; 31 | private ExcelReadFieldMapping fieldMapping; 32 | private ExcelReadRowProcessor rowProcessor; 33 | private boolean trimSpace = false; 34 | private Integer headRowIndex; 35 | 36 | public abstract void beforeProcess(ExcelReadContext context); 37 | 38 | public abstract void process(ExcelReadContext context, List list); 39 | 40 | public abstract void onException(ExcelReadContext context, ExcelReadException e); 41 | 42 | public abstract void afterProcess(ExcelReadContext context); 43 | 44 | public Integer getSheetIndex() { 45 | return sheetIndex; 46 | } 47 | 48 | /** 49 | * required.it can be replaced with {@code setSheetName}; 50 | * 51 | * @param sheetIndex 52 | * @see #setSheetName 53 | */ 54 | public void setSheetIndex(Integer sheetIndex) { 55 | this.sheetIndex = sheetIndex; 56 | } 57 | 58 | /** 59 | * required.it can be replaced with {@code setSheetIndex}; 60 | * 61 | * @param 62 | * @see #setSheetIndex 63 | */ 64 | public String getSheetName() { 65 | return sheetName; 66 | } 67 | 68 | public void setSheetName(String sheetName) { 69 | this.sheetName = sheetName; 70 | } 71 | 72 | /** 73 | * required 74 | * 75 | * @param 76 | */ 77 | public int getStartRowIndex() { 78 | return startRowIndex; 79 | } 80 | 81 | /** 82 | * 83 | * @param startRowIndex 84 | */ 85 | public void setStartRowIndex(int startRowIndex) { 86 | this.startRowIndex = startRowIndex; 87 | } 88 | 89 | public Integer getPageSize() { 90 | return pageSize; 91 | } 92 | 93 | /** 94 | * 95 | * @param pageSize 96 | */ 97 | public void setPageSize(Integer pageSize) { 98 | this.pageSize = pageSize; 99 | } 100 | 101 | public ExcelReadFieldMapping getFieldMapping() { 102 | return fieldMapping; 103 | } 104 | 105 | public void setFieldMapping(ExcelReadFieldMapping fieldMapping) { 106 | this.fieldMapping = fieldMapping; 107 | } 108 | 109 | public ExcelReadRowProcessor getRowProcessor() { 110 | return rowProcessor; 111 | } 112 | 113 | /** 114 | * 115 | * @param rowProcessor 116 | */ 117 | public void setRowProcessor(ExcelReadRowProcessor rowProcessor) { 118 | this.rowProcessor = rowProcessor; 119 | } 120 | 121 | public Class getTargetClass() { 122 | return targetClass; 123 | } 124 | 125 | /** 126 | * required 127 | * 128 | * @param targetClass 129 | */ 130 | public void setTargetClass(Class targetClass) { 131 | this.targetClass = targetClass; 132 | } 133 | 134 | public Integer getEndRowIndex() { 135 | return endRowIndex; 136 | } 137 | 138 | /** 139 | * 140 | * @param endRowIndex 141 | */ 142 | public void setEndRowIndex(Integer endRowIndex) { 143 | this.endRowIndex = endRowIndex; 144 | } 145 | 146 | public boolean isTrimSpace() { 147 | return trimSpace; 148 | } 149 | 150 | public void setTrimSpace(boolean trimSpace) { 151 | this.trimSpace = trimSpace; 152 | } 153 | 154 | public Integer getHeadRowIndex() { 155 | return headRowIndex; 156 | } 157 | 158 | public void setHeadRowIndex(Integer headRowIndex) { 159 | this.headRowIndex = headRowIndex; 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.hellojavaer 6 | poi-excel-utils 7 | 2.0.0-SNAPSHOT 8 | jar 9 | poi-excel-utils makes the conversion between excel file data and java bean easy 10 | 11 | poi-excel-utils 12 | https://github.com/hellojavaer/poi-excel-utils 13 | 14 | 15 | 4.11 16 | true 17 | false 18 | UTF-8 19 | 1.6 20 | 21 | 22 | 23 | zoukaiming 24 | zoukaiming 25 | hellojavaer@gmail.com 26 | 27 | developer 28 | 29 | 8 30 | 31 | 32 | 33 | https://github.com/hellojavaer/poi-excel-utils.git 34 | scm:git:https://github.com/hellojavaer/poi-excel-utils.git 35 | 36 | 37 | 38 | Apache 2 39 | http://www.apache.org/licenses/LICENSE-2.0.txt 40 | repo 41 | A business-friendly OSS license 42 | 43 | 44 | 45 | 46 | oss 47 | https://oss.sonatype.org/content/repositories/snapshots 48 | 49 | 50 | oss 51 | https://oss.sonatype.org/service/local/staging/deploy/maven2 52 | 53 | 54 | 55 | 56 | 57 | org.apache.maven.plugins 58 | maven-compiler-plugin 59 | 2.5.1 60 | 61 | UTF-8 62 | ${jdk.version} 63 | ${jdk.version} 64 | 65 | 66 | 67 | org.codehaus.plexus 68 | plexus-compiler-javac 69 | 1.8.1 70 | 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-source-plugin 76 | 2.1.1 77 | 78 | 79 | attach-sources 80 | 81 | jar-no-fork 82 | 83 | 84 | 85 | 86 | true 87 | 88 | 89 | 90 | maven-javadoc-plugin 91 | 92 | 93 | attach-javadoc 94 | 95 | jar 96 | 97 | 98 | 99 | 100 | ${javadoc.skip} 101 | public 102 | UTF-8 103 | UTF-8 104 | UTF-8 105 | 106 | http://docs.oracle.com/javase/6/docs/api 107 | 108 | 109 | 110 | 111 | org.apache.maven.plugins 112 | maven-surefire-plugin 113 | 2.4.2 114 | 115 | true 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-gpg-plugin 121 | 122 | ${gpg.skip} 123 | 124 | 1.5 125 | 126 | 127 | sign-artifacts 128 | verify 129 | 130 | sign 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | org.apache.poi 141 | poi-ooxml 142 | 3.12 143 | 144 | 145 | org.apache.poi 146 | poi 147 | 3.12 148 | 149 | 150 | com.alibaba 151 | fastjson 152 | 1.2.7 153 | 154 | 155 | org.springframework 156 | spring-beans 157 | 4.2.2.RELEASE 158 | 159 | 160 | junit 161 | junit 162 | ${junit.version} 163 | test 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import java.io.Serializable; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import org.apache.poi.ss.usermodel.Cell; 24 | import org.apache.poi.ss.usermodel.Row; 25 | import org.apache.poi.ss.usermodel.Sheet; 26 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 27 | 28 | /** 29 | * Reading excel context. 30 | * @author zoukaiming 31 | */ 32 | public class ExcelReadContext implements Serializable { 33 | 34 | private static final long serialVersionUID = 1L; 35 | 36 | private Map contextContainer = new HashMap(); 37 | 38 | private Sheet curSheet; 39 | private Integer curSheetIndex; 40 | private String curSheetName; 41 | 42 | private Row curRow; 43 | private Integer curRowIndex; 44 | 45 | private Cell curCell; 46 | private Integer curColIndex; 47 | private String curColStrIndex; 48 | 49 | private T curRowData; 50 | private List dataList; 51 | 52 | public Cell getCell(Integer rowIndex, Integer colIndex) { 53 | if (rowIndex == null || rowIndex < 0 || colIndex == null || colIndex < 0) { 54 | return null; 55 | } 56 | if (this.curSheet == null) { 57 | return null; 58 | } else { 59 | Row row = curSheet.getRow(rowIndex); 60 | if (row == null) { 61 | return null; 62 | } else { 63 | return row.getCell(colIndex); 64 | } 65 | } 66 | } 67 | 68 | public Cell getCell(Integer rowIndex, String colStrIndex) { 69 | return getCell(rowIndex, ExcelUtils.convertColCharIndexToIntIndex(colStrIndex)); 70 | } 71 | 72 | public ExcelCellValue getCellValue(Integer rowIndex, Integer colIndex) { 73 | Cell cell = getCell(rowIndex, colIndex); 74 | return ExcelUtils.readCell(cell); 75 | } 76 | 77 | public ExcelCellValue getCellValue(Integer rowIndex, String colStrIndex) { 78 | return getCellValue(rowIndex, ExcelUtils.convertColCharIndexToIntIndex(colStrIndex)); 79 | } 80 | 81 | public void setAttribute(String key, Object value) { 82 | this.contextContainer.put(key, value); 83 | } 84 | 85 | public Object getAttribute(String key) { 86 | return this.contextContainer.get(key); 87 | } 88 | 89 | public Sheet getCurSheet() { 90 | return curSheet; 91 | } 92 | 93 | public void setCurSheet(Sheet curSheet) { 94 | this.curSheet = curSheet; 95 | } 96 | 97 | public Row getCurRow() { 98 | return curRow; 99 | } 100 | 101 | public void setCurRow(Row curRow) { 102 | this.curRow = curRow; 103 | } 104 | 105 | public Cell getCurCell() { 106 | return curCell; 107 | } 108 | 109 | public void setCurCell(Cell curCell) { 110 | this.curCell = curCell; 111 | } 112 | 113 | public T getCurRowData() { 114 | return curRowData; 115 | } 116 | 117 | public void setCurRowData(T curRowData) { 118 | this.curRowData = curRowData; 119 | } 120 | 121 | public List getDataList() { 122 | return dataList; 123 | } 124 | 125 | public void setDataList(List dataList) { 126 | this.dataList = dataList; 127 | } 128 | 129 | // ==================Extends Get Method==================== 130 | 131 | public Integer getCurRowIndex() { 132 | return curRowIndex; 133 | } 134 | 135 | public void setCurRowIndex(Integer curRowIndex) { 136 | this.curRowIndex = curRowIndex; 137 | } 138 | 139 | public Integer getCurColIndex() { 140 | return curColIndex; 141 | } 142 | 143 | public void setCurSheetIndex(Integer curSheetIndex) { 144 | this.curSheetIndex = curSheetIndex; 145 | } 146 | 147 | /** 148 | * NOTE HERE 149 | * 150 | * @param curColIndex 151 | */ 152 | public void setCurColIndex(Integer curColIndex) { 153 | this.curColIndex = curColIndex; 154 | if (curColIndex == null) { 155 | this.curColStrIndex = null; 156 | } else { 157 | this.curColStrIndex = ExcelUtils.convertColIntIndexToCharIndex(curColIndex); 158 | } 159 | } 160 | 161 | public String getCurSheetName() { 162 | return curSheetName; 163 | } 164 | 165 | public void setCurSheetName(String curSheetName) { 166 | this.curSheetName = curSheetName; 167 | } 168 | 169 | public String getCurColStrIndex() { 170 | return curColStrIndex; 171 | } 172 | 173 | public Integer getCurSheetIndex() { 174 | return curSheetIndex; 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 19 | 20 | /** 21 | * @author zoukaiming 22 | */ 23 | public class ExcelWriteException extends RuntimeException { 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | public static final int CODE_OF_PROCESS_EXCEPTION = 0; 28 | public static final int CODE_OF_SHEET_NOT_EXIST = 20; 29 | public static final int CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH = 21; 30 | public static final int CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY = 22; 31 | public static final int CODE_OF_FIELD_VALUE_NOT_MATCH = 61; 32 | 33 | private String sheetName = null; 34 | private Integer sheetIndex = null; 35 | private Integer rowIndex = null; 36 | private String colStrIndex = null; 37 | private Integer colIndex = null; 38 | 39 | /** 40 | * [0-99] are system reserved values.user-define value should be larger than 41 | * or equal to 100. 42 | */ 43 | private int code = CODE_OF_PROCESS_EXCEPTION; 44 | 45 | private String msg; 46 | 47 | public ExcelWriteException() { 48 | super(); 49 | } 50 | 51 | public ExcelWriteException(String message, Throwable cause) { 52 | super(message, cause); 53 | this.msg = message; 54 | } 55 | 56 | public ExcelWriteException(String message) { 57 | super(message); 58 | this.msg = message; 59 | } 60 | 61 | public ExcelWriteException(Throwable cause) { 62 | super(cause); 63 | } 64 | 65 | @Override 66 | public String getMessage() { 67 | StringBuilder sb = new StringBuilder(); 68 | sb.append(this.msg); 69 | sb.append(" Detail coordinate is sheet:"); 70 | sb.append(this.getSheetName()); 71 | sb.append("[index:"); 72 | sb.append(this.getSheetIndex()); 73 | sb.append("]"); 74 | sb.append(" row:"); 75 | if (this.getRowIndex() != null) { 76 | sb.append(this.getRowIndex() + 1); 77 | } else { 78 | sb.append("null"); 79 | } 80 | sb.append(" column:"); 81 | sb.append(this.getColStrIndex()); 82 | sb.append("[index:"); 83 | sb.append(this.getColIndex()); 84 | sb.append("], code is "); 85 | sb.append(this.getCode()); 86 | sb.append(", and description is '"); 87 | switch (this.getCode()) { 88 | case CODE_OF_PROCESS_EXCEPTION: 89 | sb.append("process exception"); 90 | break; 91 | case CODE_OF_SHEET_NOT_EXIST: 92 | sb.append("sheet not exist"); 93 | break; 94 | case CODE_OF_FIELD_VALUE_NOT_MATCH: 95 | sb.append("field value not match"); 96 | break; 97 | } 98 | sb.append("'."); 99 | return sb.toString(); 100 | } 101 | 102 | /** 103 | * [0-99] are system reserved values.user-define value should be larger than 104 | * or equal to 100. 105 | */ 106 | public int getCode() { 107 | return code; 108 | } 109 | 110 | /** 111 | * [0-99] are system reserved values.user-define value should be larger than 112 | * or equal to 100. 113 | */ 114 | public void setCode(int code) { 115 | this.code = code; 116 | } 117 | 118 | public String getSheetName() { 119 | return sheetName; 120 | } 121 | 122 | public void setSheetName(String sheetName) { 123 | this.sheetName = sheetName; 124 | } 125 | 126 | public Integer getSheetIndex() { 127 | return sheetIndex; 128 | } 129 | 130 | public void setSheetIndex(Integer sheetIndex) { 131 | this.sheetIndex = sheetIndex; 132 | } 133 | 134 | public Integer getRowIndex() { 135 | return rowIndex; 136 | } 137 | 138 | public void setRowIndex(Integer rowIndex) { 139 | this.rowIndex = rowIndex; 140 | } 141 | 142 | public String getColStrIndex() { 143 | return colStrIndex; 144 | } 145 | 146 | public Integer getColIndex() { 147 | return colIndex; 148 | } 149 | 150 | public void setColStrIndex(String colStrIndex) { 151 | this.colStrIndex = colStrIndex; 152 | if (colStrIndex == null) { 153 | this.colIndex = null; 154 | } else { 155 | this.colIndex = ExcelUtils.convertColCharIndexToIntIndex(colStrIndex); 156 | } 157 | } 158 | 159 | public void setColIndex(Integer colIndex) { 160 | this.colIndex = colIndex; 161 | if (colIndex == null) { 162 | this.colStrIndex = null; 163 | } else { 164 | this.colStrIndex = ExcelUtils.convertColIntIndexToCharIndex(colIndex); 165 | } 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/read/ExcelReadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.read; 17 | 18 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 19 | 20 | /** 21 | * @author zoukaiming 22 | */ 23 | public class ExcelReadException extends RuntimeException { 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | public static final int CODE_OF_PROCESS_EXCEPTION = 0; 28 | public static final int CODE_OF_SHEET_NOT_EXIST = 20; 29 | public static final int CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH = 21; 30 | public static final int CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY = 22; 31 | public static final int CODE_OF_CELL_VALUE_REQUIRED = 60; 32 | public static final int CODE_OF_CELL_VALUE_NOT_MATCH = 61; 33 | public static final int CODE_OF_CELL_ERROR = 62; 34 | 35 | private String sheetName = null; 36 | private Integer sheetIndex = null; 37 | private Integer rowIndex = null; 38 | private String colStrIndex = null; 39 | private Integer colIndex = null; 40 | 41 | private String msg; 42 | /** 43 | * [0-99] are system reserved value.user-define value should be larger than 44 | * or equal to 100. 45 | */ 46 | private int code = CODE_OF_PROCESS_EXCEPTION; 47 | 48 | public ExcelReadException() { 49 | } 50 | 51 | public ExcelReadException(Throwable cause) { 52 | super(cause); 53 | } 54 | 55 | public ExcelReadException(String message) { 56 | super(message); 57 | this.msg = message; 58 | } 59 | 60 | public ExcelReadException(String message, Throwable cause) { 61 | super(message, cause); 62 | this.msg = message; 63 | } 64 | 65 | @Override 66 | public String getMessage() { 67 | StringBuilder sb = new StringBuilder(); 68 | sb.append(this.msg); 69 | sb.append(" Detail coordinate is sheet:"); 70 | sb.append(this.getSheetName()); 71 | sb.append("[index:"); 72 | sb.append(this.getSheetIndex()); 73 | sb.append("]"); 74 | sb.append(" row:"); 75 | if (this.getRowIndex() != null) { 76 | sb.append(this.getRowIndex() + 1); 77 | } else { 78 | sb.append("null"); 79 | } 80 | sb.append(" column:"); 81 | sb.append(this.getColStrIndex()); 82 | sb.append("[index:"); 83 | sb.append(this.getColIndex()); 84 | sb.append("], code is "); 85 | sb.append(this.getCode()); 86 | sb.append(", and description is '"); 87 | switch (this.getCode()) { 88 | case CODE_OF_PROCESS_EXCEPTION: 89 | sb.append("process exception"); 90 | break; 91 | case CODE_OF_SHEET_NOT_EXIST: 92 | sb.append("sheet not exist"); 93 | break; 94 | case CODE_OF_CELL_VALUE_REQUIRED: 95 | sb.append("cell value is required"); 96 | break; 97 | case CODE_OF_CELL_VALUE_NOT_MATCH: 98 | sb.append("cell value not match"); 99 | break; 100 | case CODE_OF_CELL_ERROR: 101 | sb.append("process error"); 102 | break; 103 | } 104 | sb.append("'."); 105 | return sb.toString(); 106 | } 107 | 108 | /** 109 | * [0-99] are system reserved value.user-define value should be larger than 110 | * or equal to 100. 111 | */ 112 | public int getCode() { 113 | return code; 114 | } 115 | 116 | /** 117 | * [0-99] are system reserved value.user-define value should be larger than 118 | * or equal to 100. 119 | */ 120 | public void setCode(int code) { 121 | this.code = code; 122 | } 123 | 124 | public String getSheetName() { 125 | return sheetName; 126 | } 127 | 128 | public void setSheetName(String sheetName) { 129 | this.sheetName = sheetName; 130 | } 131 | 132 | public Integer getSheetIndex() { 133 | return sheetIndex; 134 | } 135 | 136 | public void setSheetIndex(Integer sheetIndex) { 137 | this.sheetIndex = sheetIndex; 138 | } 139 | 140 | public Integer getRowIndex() { 141 | return rowIndex; 142 | } 143 | 144 | public void setRowIndex(Integer rowIndex) { 145 | this.rowIndex = rowIndex; 146 | } 147 | 148 | public String getColStrIndex() { 149 | return colStrIndex; 150 | } 151 | 152 | public Integer getColIndex() { 153 | return colIndex; 154 | } 155 | 156 | public void setColStrIndex(String colStrIndex) { 157 | this.colStrIndex = colStrIndex; 158 | if (colStrIndex == null) { 159 | this.colIndex = null; 160 | } else { 161 | this.colIndex = ExcelUtils.convertColCharIndexToIntIndex(colStrIndex); 162 | } 163 | } 164 | 165 | public void setColIndex(Integer colIndex) { 166 | this.colIndex = colIndex; 167 | if (colIndex == null) { 168 | this.colStrIndex = null; 169 | } else { 170 | this.colStrIndex = ExcelUtils.convertColIntIndexToCharIndex(colIndex); 171 | } 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/write/ExcelWriteContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils.write; 17 | 18 | import java.io.Serializable; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import org.apache.poi.ss.usermodel.Cell; 23 | import org.apache.poi.ss.usermodel.Row; 24 | import org.apache.poi.ss.usermodel.Sheet; 25 | import org.apache.poi.ss.util.CellRangeAddress; 26 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 27 | import org.hellojavaer.poi.excel.utils.read.ExcelCellValue; 28 | 29 | /** 30 | * Writting excel context 31 | * @author zoukaiming 32 | */ 33 | public class ExcelWriteContext implements Serializable { 34 | 35 | private static final long serialVersionUID = 1L; 36 | 37 | private Map contextContainer = new HashMap(); 38 | 39 | private Sheet curSheet; 40 | private Integer curSheetIndex; 41 | private String curSheetName; 42 | 43 | private Row curRow; 44 | private Integer curRowIndex; 45 | 46 | private Cell curCell; 47 | private Integer curColIndex; 48 | private String curColStrIndex; 49 | 50 | public Cell getCell(Integer rowIndex, Integer colIndex) { 51 | if (rowIndex == null || rowIndex < 0 || colIndex == null || colIndex < 0) { 52 | return null; 53 | } 54 | if (this.curSheet == null) { 55 | return null; 56 | } else { 57 | Row row = curSheet.getRow(rowIndex); 58 | if (row == null) { 59 | return null; 60 | } else { 61 | return row.getCell(colIndex); 62 | } 63 | } 64 | } 65 | 66 | public Cell getCell(Integer rowIndex, String colStrIndex) { 67 | return getCell(rowIndex, ExcelUtils.convertColCharIndexToIntIndex(colStrIndex)); 68 | } 69 | 70 | public ExcelCellValue getCellValue(Integer rowIndex, Integer colIndex) { 71 | Cell cell = getCell(rowIndex, colIndex); 72 | return ExcelUtils.readCell(cell); 73 | } 74 | 75 | public ExcelCellValue getCellValue(Integer rowIndex, String colStrIndex) { 76 | return getCellValue(rowIndex, ExcelUtils.convertColCharIndexToIntIndex(colStrIndex)); 77 | } 78 | 79 | public Cell setCellValue(Integer rowIndex, String colStrIndex, Object val) { 80 | return setCellValue(rowIndex, ExcelUtils.convertColCharIndexToIntIndex(colStrIndex), val); 81 | } 82 | 83 | // CellRangeAddress 84 | public Cell setCellValue(int firstRow, int lastRow, int firstCol, int lastCol, Object val) { 85 | CellRangeAddress cellRangeAddress = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); 86 | curSheet.addMergedRegion(cellRangeAddress); 87 | return setCellValue(firstRow, firstCol, val); 88 | } 89 | 90 | public Cell setCellValue(int rowIndex, int colIndex, Object val) { 91 | if (rowIndex < 0 || colIndex < 0) { 92 | throw new IllegalArgumentException("rowIndex:" + rowIndex + " &colIndex:" + colIndex); 93 | } 94 | if (curSheet == null) { 95 | throw new NullPointerException("sheet is null"); 96 | } 97 | Row row = curSheet.getRow(rowIndex); 98 | if (row == null) { 99 | row = curSheet.createRow(rowIndex); 100 | } 101 | Cell cell = row.getCell(colIndex); 102 | if (cell == null) { 103 | cell = row.createCell(colIndex); 104 | } 105 | ExcelUtils.writeCell(cell, val); 106 | return cell; 107 | } 108 | 109 | public Sheet getCurSheet() { 110 | return curSheet; 111 | } 112 | 113 | public void setCurSheet(Sheet curSheet) { 114 | this.curSheet = curSheet; 115 | } 116 | 117 | public Integer getCurSheetIndex() { 118 | return curSheetIndex; 119 | } 120 | 121 | public void setCurSheetIndex(Integer curSheetIndex) { 122 | this.curSheetIndex = curSheetIndex; 123 | } 124 | 125 | public String getCurSheetName() { 126 | return curSheetName; 127 | } 128 | 129 | public void setCurSheetName(String curSheetName) { 130 | this.curSheetName = curSheetName; 131 | } 132 | 133 | public Row getCurRow() { 134 | return curRow; 135 | } 136 | 137 | public void setCurRow(Row curRow) { 138 | this.curRow = curRow; 139 | } 140 | 141 | public Integer getCurRowIndex() { 142 | return curRowIndex; 143 | } 144 | 145 | public void setCurRowIndex(Integer curRowIndex) { 146 | this.curRowIndex = curRowIndex; 147 | } 148 | 149 | public Cell getCurCell() { 150 | return curCell; 151 | } 152 | 153 | public void setCurCell(Cell curCell) { 154 | this.curCell = curCell; 155 | } 156 | 157 | public Integer getCurColIndex() { 158 | return curColIndex; 159 | } 160 | 161 | public void setCurColIndex(Integer curColIndex) { 162 | this.curColIndex = curColIndex; 163 | if (curColIndex == null) { 164 | this.curColStrIndex = null; 165 | } else { 166 | this.curColStrIndex = ExcelUtils.convertColIntIndexToCharIndex(curColIndex); 167 | } 168 | } 169 | 170 | public String getCurColStrIndex() { 171 | return curColStrIndex; 172 | } 173 | 174 | public void setAttribute(String key, Object value) { 175 | this.contextContainer.put(key, value); 176 | } 177 | 178 | public Object getAttribute(String key) { 179 | return this.contextContainer.get(key); 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /src/test/java/org/hellojavaer/poi/excel/utils/write/WriteDemo2.java: -------------------------------------------------------------------------------- 1 | package org.hellojavaer.poi.excel.utils.write; 2 | 3 | import org.apache.poi.ss.usermodel.Cell; 4 | import org.apache.poi.ss.usermodel.Row; 5 | import org.hellojavaer.poi.excel.utils.ExcelProcessController; 6 | import org.hellojavaer.poi.excel.utils.ExcelUtils; 7 | import org.hellojavaer.poi.excel.utils.TestBean; 8 | import org.hellojavaer.poi.excel.utils.TestEnum; 9 | import org.hellojavaer.poi.excel.utils.read.*; 10 | 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.net.URL; 16 | import java.util.ArrayList; 17 | import java.util.Date; 18 | import java.util.List; 19 | import java.util.concurrent.atomic.AtomicLong; 20 | 21 | /** 22 | * @author zoukaiming 23 | */ 24 | public class WriteDemo2 { 25 | 26 | private static List testDataCache; 27 | 28 | public static void main(String[] args) throws IOException { 29 | InputStream excelTemplate = WriteDemo2.class.getResourceAsStream("/excel/xlsx/template_file3.xlsx"); 30 | URL url = WriteDemo2.class.getResource("/"); 31 | final String outputFilePath = url.getPath() + "output_file2.xlsx"; 32 | File outputFile = new File(outputFilePath); 33 | outputFile.createNewFile(); 34 | FileOutputStream output = new FileOutputStream(outputFile); 35 | 36 | final AtomicLong rowIndex = new AtomicLong(0); 37 | ExcelWriteSheetProcessor sheetProcessor = new ExcelWriteSheetProcessor() { 38 | 39 | @Override 40 | public void beforeProcess(ExcelWriteContext context) { 41 | System.out.println("write excel start!"); 42 | } 43 | 44 | @Override 45 | public void onException(ExcelWriteContext context, ExcelWriteException e) { 46 | throw e; 47 | } 48 | 49 | @Override 50 | public void afterProcess(ExcelWriteContext context) { 51 | context.setCellValue(2, 0, "Test output"); 52 | context.setCellValue(4, 0, "zoukaiming"); 53 | context.setCellValue(6, 0, "hellojavaer@gmail.com"); 54 | context.setCellValue(8, 0, new Date()); 55 | System.out.println("write excel end!"); 56 | System.out.println("output file path is " + outputFilePath); 57 | } 58 | }; 59 | ExcelWriteFieldMapping fieldMapping = new ExcelWriteFieldMapping(); 60 | fieldMapping.put("C", "byteField"); 61 | fieldMapping.put("D", "shortField"); 62 | fieldMapping.put("E", "intField"); 63 | fieldMapping.put("F", "longField"); 64 | fieldMapping.put("G", "floatField"); 65 | fieldMapping.put("H", "doubleField"); 66 | fieldMapping.put("I", "boolField"); 67 | fieldMapping.put("J", "stringField"); 68 | fieldMapping.put("K", "dateField"); 69 | fieldMapping.put("L", "enumField1").setCellProcessor(new ExcelWriteCellProcessor() { 70 | 71 | public void process(ExcelWriteContext context, Object obj, Cell cell) { 72 | if (obj == null) { 73 | cell.setCellValue("Please select"); 74 | } 75 | } 76 | }); 77 | ExcelWriteCellValueMapping kValueMapping = new ExcelWriteCellValueMapping(); 78 | kValueMapping.put(null, "Please select"); 79 | kValueMapping.put(TestEnum.AA.toString(), "Option1"); 80 | kValueMapping.put(TestEnum.BB.toString(), "Option2"); 81 | kValueMapping.put(TestEnum.CC.toString(), "Option3"); 82 | fieldMapping.put("M", "enumField2").setValueMapping(kValueMapping); 83 | 84 | sheetProcessor.setSheetIndex(0); 85 | sheetProcessor.setStartRowIndex(1); 86 | sheetProcessor.setFieldMapping(fieldMapping); 87 | sheetProcessor.setTemplateRows(1, 2); 88 | // sheetProcessor.setRowProcessor(new ExcelWriteRowProcessor() { 89 | // @Override 90 | // public void process(ExcelProcessController controller, ExcelWriteContext context, TestBean t, 91 | // Row row) { 92 | // } 93 | // }); 94 | sheetProcessor.setDataList(getDataList()); 95 | 96 | ExcelUtils.write(excelTemplate, output, sheetProcessor); 97 | } 98 | 99 | private static List getDataList() { 100 | final List re = new ArrayList(); 101 | InputStream in = WriteDemo2.class.getResourceAsStream("/excel/xlsx/data_file2.xlsx"); 102 | ExcelReadSheetProcessor sheetProcessor = new ExcelReadSheetProcessor() { 103 | 104 | @Override 105 | public void beforeProcess(ExcelReadContext context) { 106 | 107 | } 108 | 109 | @Override 110 | public void process(ExcelReadContext context, List list) { 111 | re.addAll(list); 112 | } 113 | 114 | @Override 115 | public void onException(ExcelReadContext context, ExcelReadException e) { 116 | throw e; 117 | } 118 | 119 | @Override 120 | public void afterProcess(ExcelReadContext context) { 121 | 122 | } 123 | }; 124 | 125 | ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping(); 126 | fieldMapping.put("A", "byteField"); 127 | fieldMapping.put("B", "shortField"); 128 | fieldMapping.put("C", "intField"); 129 | fieldMapping.put("D", "longField"); 130 | fieldMapping.put("E", "floatField"); 131 | fieldMapping.put("F", "doubleField"); 132 | fieldMapping.put("G", "boolField"); 133 | fieldMapping.put("H", "stringField"); 134 | fieldMapping.put("I", "dateField"); 135 | 136 | fieldMapping.put("J", "enumField1").setCellProcessor(new ExcelReadCellProcessor() { 137 | 138 | public Object process(ExcelReadContext context, Cell cell, ExcelCellValue cellValue) { 139 | String str = cellValue.getStringValue(); 140 | if (str == null || str.trim().equals("")) { 141 | return null; 142 | } else { 143 | return str; 144 | } 145 | } 146 | }); 147 | 148 | ExcelReadCellValueMapping valueMapping = new ExcelReadCellValueMapping(); 149 | valueMapping.put("Please select", null); 150 | valueMapping.put("Option1", TestEnum.AA.toString()); 151 | valueMapping.put("Option2", TestEnum.BB.toString()); 152 | valueMapping.put("Option3", TestEnum.CC.toString()); 153 | fieldMapping.put("K", "enumField2").setValueMapping(valueMapping).setRequired(false); 154 | 155 | sheetProcessor.setSheetIndex(0);// required.it can be replaced with 'setSheetName(sheetName)'; 156 | sheetProcessor.setStartRowIndex(1);// 157 | sheetProcessor.setTargetClass(TestBean.class);// required 158 | sheetProcessor.setFieldMapping(fieldMapping);// required 159 | sheetProcessor.setRowProcessor(new ExcelReadRowProcessor() { 160 | 161 | public TestBean process(ExcelProcessController controller, ExcelReadContext context, Row row, 162 | TestBean t) { 163 | return t; 164 | } 165 | }); 166 | 167 | ExcelUtils.read(in, sheetProcessor); 168 | return re; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /src/main/java/org/hellojavaer/poi/excel/utils/ExcelUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.hellojavaer.poi.excel.utils; 17 | 18 | import com.alibaba.fastjson.util.TypeUtils; 19 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; 20 | import org.apache.poi.ss.usermodel.*; 21 | import org.apache.poi.ss.util.CellRangeAddress; 22 | import org.apache.poi.ss.util.CellRangeAddressList; 23 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 24 | import org.hellojavaer.poi.excel.utils.common.Assert; 25 | import org.hellojavaer.poi.excel.utils.read.*; 26 | import org.hellojavaer.poi.excel.utils.read.ExcelReadFieldMapping.ExcelReadFieldMappingAttribute; 27 | import org.hellojavaer.poi.excel.utils.write.*; 28 | import org.hellojavaer.poi.excel.utils.write.ExcelWriteFieldMapping.ExcelWriteFieldMappingAttribute; 29 | import org.springframework.beans.BeanUtils; 30 | 31 | import java.beans.PropertyDescriptor; 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.io.OutputStream; 35 | import java.lang.reflect.InvocationTargetException; 36 | import java.lang.reflect.Modifier; 37 | import java.text.DateFormat; 38 | import java.text.ParseException; 39 | import java.text.SimpleDateFormat; 40 | import java.util.*; 41 | import java.util.Map.Entry; 42 | 43 | /** 44 | * 45 | * @author zoukaiming 46 | */ 47 | public class ExcelUtils { 48 | 49 | private static long TIME_1899_12_31_00_00_00_000; 50 | private static long TIME_1900_01_01_00_00_00_000; 51 | private static long TIME_1900_01_02_00_00_00_000; 52 | 53 | static { 54 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); 55 | try { 56 | TIME_1899_12_31_00_00_00_000 = df.parse("1899-12-31 00:00:00:000").getTime(); 57 | TIME_1900_01_01_00_00_00_000 = df.parse("1900-01-01 00:00:00:000").getTime(); 58 | TIME_1900_01_02_00_00_00_000 = df.parse("1900-01-02 00:00:00:000").getTime(); 59 | } catch (ParseException e) { 60 | throw new RuntimeException(e); 61 | } 62 | } 63 | 64 | private static void convertFieldMapping(Sheet sheet, ExcelReadSheetProcessor sheetProcessor, 65 | Map> src, 66 | Map> tar) { 67 | if (src == null) { 68 | return; 69 | } 70 | Integer headRowIndex = sheetProcessor.getHeadRowIndex(); 71 | Map colCache = new HashMap(); 72 | if (headRowIndex != null) { 73 | Row row = sheet.getRow(headRowIndex); 74 | if (row != null) { 75 | int start = row.getFirstCellNum(); 76 | int end = row.getLastCellNum(); 77 | for (int i = start; i < end; i++) { 78 | Cell cell = row.getCell(i); 79 | Object cellValue = _readCell(cell); 80 | if (cellValue != null) { 81 | String strVal = cellValue.toString().trim(); 82 | colCache.put(strVal, i); 83 | } 84 | } 85 | } 86 | } 87 | 88 | for (Map.Entry> entry : src.entrySet()) { 89 | String colIndexOrColName = entry.getKey(); 90 | Integer colIndex = null; 91 | if (headRowIndex == null) { 92 | colIndex = convertColCharIndexToIntIndex(colIndexOrColName); 93 | } else { 94 | colIndex = colCache.get(colIndexOrColName); 95 | if (colIndex == null) { 96 | throw new IllegalStateException("For sheet:" + sheet.getSheetName() + " headRowIndex:" 97 | + headRowIndex + " can't find colum named '" + colIndexOrColName 98 | + "'"); 99 | } 100 | } 101 | tar.put(colIndex, entry.getValue()); 102 | } 103 | } 104 | 105 | private static void readConfigParamVerify(ExcelReadSheetProcessor sheetProcessor, 106 | Map> fieldMapping) { 107 | Class clazz = sheetProcessor.getTargetClass(); 108 | 109 | for (Entry> indexFieldMapping : fieldMapping.entrySet()) { 110 | for (Map.Entry filedMapping : indexFieldMapping.getValue().entrySet()) { 111 | String fieldName = filedMapping.getKey(); 112 | if (fieldName != null) { 113 | PropertyDescriptor pd = getPropertyDescriptor(clazz, fieldName); 114 | if (pd == null || pd.getWriteMethod() == null) { 115 | throw new IllegalArgumentException("In fieldMapping config {colIndex:" 116 | + indexFieldMapping.getKey() + "[" 117 | + convertColIntIndexToCharIndex(indexFieldMapping.getKey()) 118 | + "]<->fieldName:" + filedMapping.getKey() + "}, " 119 | + " class " + clazz.getName() + " can't find field '" 120 | + filedMapping.getKey() + "' and can not also find " 121 | + filedMapping.getKey() + "'s writter method."); 122 | } 123 | if (!Modifier.isPublic(pd.getWriteMethod().getDeclaringClass().getModifiers())) { 124 | pd.getWriteMethod().setAccessible(true); 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | /** 132 | * parse excel file data to java object 133 | * 134 | * @param workbookInputStream 135 | * @param sheetProcessors 136 | */ 137 | @SuppressWarnings({ "unchecked", "rawtypes" }) 138 | public static void read(InputStream workbookInputStream, ExcelReadSheetProcessor... sheetProcessors) { 139 | Assert.isTrue(workbookInputStream != null, "workbookInputStream can't be null"); 140 | Assert.isTrue(sheetProcessors != null && sheetProcessors.length != 0, "sheetProcessor can't be null"); 141 | try { 142 | Workbook workbook = WorkbookFactory.create(workbookInputStream); 143 | for (ExcelReadSheetProcessor sheetProcessor : sheetProcessors) { 144 | ExcelReadContext context = new ExcelReadContext(); 145 | String sheetName = sheetProcessor.getSheetName(); 146 | Integer sheetIndex = sheetProcessor.getSheetIndex(); 147 | try { 148 | Class clazz = sheetProcessor.getTargetClass(); 149 | context.setCurSheetIndex(sheetIndex); 150 | context.setCurSheetName(sheetName); 151 | Sheet sheet = null; 152 | if (sheetName != null) { 153 | try { 154 | sheet = workbook.getSheet(sheetName); 155 | } catch (IllegalArgumentException e) { 156 | // ignore 157 | } 158 | if (sheet != null && sheetIndex != null && !sheetIndex.equals(workbook.getSheetIndex(sheet))) { 159 | ExcelReadException e = new ExcelReadException(); 160 | e.setCode(ExcelReadException.CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH); 161 | throw e; 162 | } 163 | } else if (sheetIndex != null) { 164 | try { 165 | sheet = workbook.getSheetAt(sheetIndex); 166 | } catch (IllegalArgumentException e) { 167 | // ignore 168 | } 169 | } else { 170 | ExcelReadException e = new ExcelReadException(); 171 | e.setCode(ExcelReadException.CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY); 172 | throw e; 173 | } 174 | if (sheet == null) { 175 | ExcelReadException e = new ExcelReadException("Sheet of '" + sheetName + "' is not exist"); 176 | e.setCode(ExcelReadException.CODE_OF_SHEET_NOT_EXIST); 177 | throw e; 178 | } 179 | 180 | if (sheetIndex == null) { 181 | sheetIndex = workbook.getSheetIndex(sheet); 182 | } 183 | if (sheetName == null) { 184 | sheetName = sheet.getSheetName(); 185 | } 186 | // do check 187 | Map> fieldMapping = new HashMap>(); 188 | Map> src = null; 189 | if (sheetProcessor.getFieldMapping() != null) { 190 | src = sheetProcessor.getFieldMapping().export(); 191 | } 192 | convertFieldMapping(sheet, sheetProcessor, src, fieldMapping); 193 | if (sheetProcessor.getTargetClass() != null && sheetProcessor.getFieldMapping() != null 194 | && !Map.class.isAssignableFrom(sheetProcessor.getTargetClass())) { 195 | readConfigParamVerify(sheetProcessor, fieldMapping); 196 | } 197 | 198 | // proc sheet 199 | context.setCurSheet(sheet); 200 | context.setCurSheetIndex(sheetIndex); 201 | context.setCurSheetName(sheet.getSheetName()); 202 | context.setCurRow(null); 203 | context.setCurRowData(null); 204 | context.setCurRowIndex(null); 205 | context.setCurColIndex(null); 206 | context.setCurColIndex(null); 207 | // beforeProcess 208 | sheetProcessor.beforeProcess(context); 209 | 210 | if (sheetProcessor.getPageSize() != null) { 211 | context.setDataList(new ArrayList(sheetProcessor.getPageSize())); 212 | } else { 213 | context.setDataList(new ArrayList()); 214 | } 215 | 216 | Integer pageSize = sheetProcessor.getPageSize(); 217 | int startRow = sheetProcessor.getStartRowIndex(); 218 | Integer rowEndIndex = sheetProcessor.getEndRowIndex(); 219 | int actLastRow = sheet.getLastRowNum(); 220 | if (rowEndIndex != null) { 221 | if (rowEndIndex > actLastRow) { 222 | rowEndIndex = actLastRow; 223 | } 224 | } else { 225 | rowEndIndex = actLastRow; 226 | } 227 | 228 | ExcelProcessControllerImpl controller = new ExcelProcessControllerImpl(); 229 | if (pageSize != null) { 230 | int total = rowEndIndex - startRow + 1; 231 | int pageCount = (total + pageSize - 1) / pageSize; 232 | for (int i = 0; i < pageCount; i++) { 233 | int start = startRow + pageSize * i; 234 | int size = pageSize; 235 | if (i == pageCount - 1) { 236 | size = rowEndIndex - start + 1; 237 | } 238 | read(controller, context, sheet, start, size, fieldMapping, clazz, 239 | sheetProcessor.getRowProcessor(), sheetProcessor.isTrimSpace()); 240 | sheetProcessor.process(context, context.getDataList()); 241 | context.getDataList().clear(); 242 | if (controller.isDoBreak()) { 243 | controller.reset(); 244 | break; 245 | } 246 | } 247 | } else { 248 | read(controller, context, sheet, startRow, rowEndIndex - startRow + 1, fieldMapping, clazz, 249 | sheetProcessor.getRowProcessor(), sheetProcessor.isTrimSpace()); 250 | sheetProcessor.process(context, context.getDataList()); 251 | context.getDataList().clear(); 252 | } 253 | } catch (Throwable e) { 254 | if (e instanceof ExcelReadException) { 255 | ExcelReadException e0 = (ExcelReadException) e; 256 | e0.setSheetName(sheetName); 257 | e0.setSheetIndex(sheetIndex); 258 | sheetProcessor.onException(context, (ExcelReadException) e0); 259 | } else { 260 | ExcelReadException e0 = new ExcelReadException(e); 261 | e0.setSheetName(sheetName); 262 | e0.setSheetIndex(sheetIndex); 263 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 264 | sheetProcessor.onException(context, e0); 265 | } 266 | } finally { 267 | sheetProcessor.afterProcess(context); 268 | } 269 | } 270 | } catch (Exception e) { 271 | if (e instanceof RuntimeException) { 272 | throw (RuntimeException) e; 273 | } else { 274 | throw new RuntimeException(e); 275 | } 276 | } 277 | } 278 | 279 | private static void read(ExcelProcessControllerImpl controller, ExcelReadContext context, Sheet sheet, 280 | int startRow, Integer pageSize, 281 | Map> fieldMapping, 282 | Class targetClass, ExcelReadRowProcessor processor, boolean isTrimSpace) { 283 | Assert.isTrue(sheet != null, "sheet can't be null"); 284 | Assert.isTrue(startRow >= 0, "startRow must greater than or equal to 0"); 285 | Assert.isTrue(pageSize == null || pageSize >= 1, "pageSize == null || pageSize >= 1"); 286 | Assert.isTrue(fieldMapping != null, "fieldMapping can't be null"); 287 | // Assert.isTrue(targetClass != null, "clazz can't be null"); 288 | 289 | List list = context.getDataList(); 290 | if (sheet.getPhysicalNumberOfRows() == 0) { 291 | return; 292 | } 293 | // 294 | int endRow = sheet.getLastRowNum(); 295 | if (pageSize != null) { 296 | endRow = startRow + pageSize - 1; 297 | } 298 | for (int i = startRow; i <= endRow; i++) { 299 | Row row = sheet.getRow(i); 300 | // proc row 301 | context.setCurRow(row); 302 | context.setCurRowIndex(i); 303 | context.setCurCell(null); 304 | context.setCurColIndex(null); 305 | 306 | T t = null; 307 | if (!fieldMapping.isEmpty()) { 308 | t = readRow(context, row, fieldMapping, targetClass, processor, isTrimSpace); 309 | } 310 | if (processor != null) { 311 | try { 312 | controller.reset(); 313 | t = processor.process(controller, context, row, t); 314 | } catch (Throwable e) { 315 | if (e instanceof ExcelReadException) { 316 | ExcelReadException e0 = (ExcelReadException) e; 317 | e0.setRowIndex(row.getRowNum()); 318 | // e0.setColIndex(null);//user may want to set this value, 319 | throw e0; 320 | } else { 321 | ExcelReadException e0 = new ExcelReadException(e); 322 | e0.setRowIndex(row.getRowNum()); 323 | e0.setColIndex(null); 324 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 325 | throw e0; 326 | } 327 | } 328 | } 329 | if (!controller.isDoSkip()) { 330 | list.add(t); 331 | } 332 | if (controller.isDoBreak()) { 333 | break; 334 | } 335 | } 336 | } 337 | 338 | @SuppressWarnings({ "unchecked", "rawtypes" }) 339 | private static T readRow(ExcelReadContext context, Row row, 340 | Map> fieldMapping, 341 | Class targetClass, ExcelReadRowProcessor processor, boolean isTrimSpace) { 342 | try { 343 | context.setCurRowData(targetClass.newInstance()); 344 | } catch (Exception e1) { 345 | throw new RuntimeException(e1); 346 | } 347 | int curRowIndex = context.getCurRowIndex(); 348 | for (Entry> fieldMappingEntry : fieldMapping.entrySet()) { 349 | int curColIndex = fieldMappingEntry.getKey();// excel index; 350 | // proc cell 351 | context.setCurColIndex(curColIndex); 352 | 353 | Cell cell = null; 354 | if (row != null) { 355 | cell = row.getCell(curColIndex); 356 | } 357 | context.setCurCell(cell); 358 | 359 | Map fields = fieldMappingEntry.getValue(); 360 | for (Map.Entry fieldEntry : fields.entrySet()) { 361 | String fieldName = fieldEntry.getKey(); 362 | ExcelReadFieldMappingAttribute attribute = fieldEntry.getValue(); 363 | // proccess link 364 | String linkField = attribute.getLinkField(); 365 | if (linkField != null) { 366 | String address = null; 367 | if (cell != null) { 368 | Hyperlink hyperlink = cell.getHyperlink(); 369 | if (hyperlink != null) { 370 | address = hyperlink.getAddress(); 371 | } 372 | } 373 | if (isTrimSpace && address != null) { 374 | address = address.trim(); 375 | if (address.length() == 0) { 376 | address = null; 377 | } 378 | } 379 | if (Map.class.isAssignableFrom(targetClass)) {// map 380 | ((Map) context.getCurRowData()).put(linkField, address); 381 | } else {// java bean 382 | try { 383 | setProperty(context.getCurRowData(), linkField, address); 384 | } catch (Throwable e) { 385 | if (e instanceof ExcelReadException) { 386 | ExcelReadException e0 = (ExcelReadException) e; 387 | e0.setRowIndex(curRowIndex); 388 | e0.setColIndex(curColIndex); 389 | throw e0; 390 | } else { 391 | ExcelReadException e0 = new ExcelReadException(e); 392 | e0.setRowIndex(curRowIndex); 393 | e0.setColIndex(curColIndex); 394 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 395 | throw e0; 396 | } 397 | } 398 | } 399 | } 400 | 401 | Object value = _readCell(cell); 402 | if (value != null && value instanceof String && isTrimSpace) { 403 | value = ((String) value).trim(); 404 | if (((String) value).length() == 0) { 405 | value = null; 406 | } 407 | } 408 | if (value == null && attribute.isRequired()) { 409 | ExcelReadException e = new ExcelReadException("Cell value is null"); 410 | e.setRowIndex(curRowIndex); 411 | e.setColIndex(curColIndex); 412 | e.setCode(ExcelReadException.CODE_OF_CELL_VALUE_REQUIRED); 413 | throw e; 414 | } 415 | // 416 | try { 417 | if (Map.class.isAssignableFrom(targetClass)) {// map 418 | value = procValueConvert(context, row, cell, attribute, fieldName, value); 419 | ((Map) context.getCurRowData()).put(fieldName, value); 420 | } else {// java bean 421 | value = procValueConvert(context, row, cell, attribute, fieldName, value); 422 | setProperty(context.getCurRowData(), fieldName, value); 423 | } 424 | } catch (Throwable e) { 425 | if (e instanceof ExcelReadException) { 426 | ExcelReadException e0 = (ExcelReadException) e; 427 | e0.setRowIndex(curRowIndex); 428 | e0.setColIndex(curColIndex); 429 | throw e0; 430 | } else { 431 | ExcelReadException e0 = new ExcelReadException(e); 432 | e0.setRowIndex(curRowIndex); 433 | e0.setColIndex(curColIndex); 434 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 435 | throw e0; 436 | } 437 | } 438 | } 439 | } 440 | return context.getCurRowData(); 441 | } 442 | 443 | /** 444 | * convert Cell type to ExcelCellValue type 445 | * @param cell 446 | * @return 447 | * @see ExcelCellValue 448 | */ 449 | public static ExcelCellValue readCell(Cell cell) { 450 | Object val = _readCell(cell); 451 | return new ExcelCellValue(val); 452 | } 453 | 454 | private static Object _readCell(Cell cell) { 455 | if (cell == null) { 456 | return null; 457 | } 458 | int cellType = cell.getCellType(); 459 | Object value = null; 460 | switch (cellType) { 461 | case Cell.CELL_TYPE_BLANK: 462 | value = null; 463 | break; 464 | case Cell.CELL_TYPE_BOOLEAN: 465 | boolean bool = cell.getBooleanCellValue(); 466 | value = bool; 467 | break; 468 | case Cell.CELL_TYPE_ERROR: 469 | // cell.getErrorCellValue(); 470 | ExcelReadException e = new ExcelReadException("Cell type error"); 471 | e.setRowIndex(cell.getRowIndex()); 472 | e.setColIndex(cell.getColumnIndex()); 473 | e.setCode(ExcelReadException.CODE_OF_CELL_ERROR); 474 | throw e; 475 | case Cell.CELL_TYPE_FORMULA: 476 | value = cell.getCellFormula(); 477 | break; 478 | case Cell.CELL_TYPE_NUMERIC: 479 | Object inputValue = null;// 480 | double doubleVal = cell.getNumericCellValue(); 481 | if (DateUtil.isCellDateFormatted(cell)) { 482 | inputValue = DateUtil.getJavaDate(doubleVal); 483 | } else { 484 | long longVal = Math.round(cell.getNumericCellValue()); 485 | if (Double.parseDouble(longVal + ".0") == doubleVal) { 486 | inputValue = longVal; 487 | } else { 488 | inputValue = doubleVal; 489 | } 490 | } 491 | value = inputValue; 492 | break; 493 | case Cell.CELL_TYPE_STRING: 494 | value = cell.getStringCellValue(); 495 | break; 496 | default: 497 | throw new RuntimeException("Unsupport cell type " + cellType); 498 | } 499 | return value; 500 | } 501 | 502 | private static Object procValueConvert(ExcelReadContext context, Row row, Cell cell, 503 | ExcelReadFieldMappingAttribute entry, String fieldName, Object value) { 504 | Object convertedValue = value; 505 | if (entry.getValueMapping() != null) { 506 | ExcelReadCellValueMapping valueMapping = entry.getValueMapping(); 507 | String strValue = TypeUtils.castToString(value); 508 | convertedValue = valueMapping.get(strValue); 509 | if (convertedValue == null) { 510 | if (!valueMapping.containsKey(strValue)) { 511 | if (valueMapping.isUseDefaultValue()) { 512 | if (valueMapping.isUseDefaultValueWithDefaultInput()) { 513 | convertedValue = value; 514 | } else { 515 | convertedValue = valueMapping.getDefaultValue(); 516 | } 517 | } else if (valueMapping.getDefaultProcessor() != null) { 518 | try { 519 | convertedValue = valueMapping.getDefaultProcessor().process(context, cell, 520 | new ExcelCellValue(value)); 521 | } catch (Throwable e) { 522 | if (e instanceof ExcelReadException) { 523 | ExcelReadException e0 = (ExcelReadException) e; 524 | e0.setRowIndex(row.getRowNum()); 525 | e0.setColIndex(cell.getColumnIndex()); 526 | throw e0; 527 | } else { 528 | ExcelReadException e0 = new ExcelReadException(e); 529 | e0.setRowIndex(row.getRowNum()); 530 | e0.setColIndex(cell.getColumnIndex()); 531 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 532 | throw e0; 533 | } 534 | } 535 | if (convertedValue != null && convertedValue instanceof ExcelCellValue) { 536 | convertedValue = value; 537 | } 538 | } else { 539 | ExcelReadException e = new ExcelReadException("Cell value is value " + strValue); 540 | e.setRowIndex(row.getRowNum()); 541 | e.setColIndex(cell.getColumnIndex()); 542 | e.setCode(ExcelReadException.CODE_OF_CELL_VALUE_NOT_MATCH); 543 | throw e; 544 | } 545 | } 546 | } 547 | } else if (entry.getCellProcessor() != null) { 548 | try { 549 | convertedValue = entry.getCellProcessor().process(context, cell, new ExcelCellValue(value)); 550 | } catch (Throwable e) { 551 | if (e instanceof ExcelReadException) { 552 | ExcelReadException e0 = (ExcelReadException) e; 553 | e0.setRowIndex(row.getRowNum()); 554 | e0.setColIndex(cell.getColumnIndex()); 555 | throw e0; 556 | } else { 557 | ExcelReadException e0 = new ExcelReadException(e); 558 | e0.setRowIndex(row.getRowNum()); 559 | e0.setColIndex(cell.getColumnIndex()); 560 | e0.setCode(ExcelReadException.CODE_OF_PROCESS_EXCEPTION); 561 | throw e0; 562 | } 563 | } 564 | if (convertedValue != null && convertedValue instanceof ExcelCellValue) { 565 | convertedValue = value; 566 | } 567 | } 568 | if (convertedValue == null && entry.isRequired()) { 569 | ExcelReadException e = new ExcelReadException("Cell value is null"); 570 | e.setRowIndex(row.getRowNum()); 571 | e.setColIndex(cell.getColumnIndex()); 572 | e.setCode(ExcelReadException.CODE_OF_CELL_VALUE_REQUIRED); 573 | throw e; 574 | } else { 575 | return convertedValue; 576 | } 577 | } 578 | 579 | /** 580 | * parse java object to excel file 581 | * 582 | * @param template 583 | * @param outputStream 584 | * @param sheetProcessors 585 | */ 586 | public static void write(InputStream template, OutputStream outputStream, 587 | ExcelWriteSheetProcessor... sheetProcessors) { 588 | Assert.notNull(template); 589 | Assert.notNull(outputStream); 590 | Assert.isTrue(sheetProcessors != null && sheetProcessors.length > 0); 591 | Workbook workbook; 592 | try { 593 | workbook = WorkbookFactory.create(template); 594 | } catch (Exception e) { 595 | throw new RuntimeException(e); 596 | } 597 | write(true, workbook, outputStream, sheetProcessors); 598 | } 599 | 600 | /** 601 | * parse java object to excel file 602 | * 603 | * @param fileType 604 | * @param outputStream 605 | * @param sheetProcessors 606 | */ 607 | public static void write(ExcelType fileType, OutputStream outputStream, 608 | ExcelWriteSheetProcessor... sheetProcessors) { 609 | 610 | Assert.notNull(fileType); 611 | Assert.notNull(outputStream); 612 | Assert.isTrue(sheetProcessors != null && sheetProcessors.length > 0); 613 | Workbook workbook = null; 614 | if (fileType == ExcelType.XLS) { 615 | workbook = new HSSFWorkbook(); 616 | } else { 617 | workbook = new XSSFWorkbook(); 618 | } 619 | write(false, workbook, outputStream, sheetProcessors); 620 | } 621 | 622 | private static class InnerRow { 623 | 624 | private short height; 625 | private float heightInPoints; 626 | private CellStyle rowStyle; 627 | private boolean zeroHeight; 628 | private Map cellMap = new HashMap(); 629 | 630 | public short getHeight() { 631 | return height; 632 | } 633 | 634 | public void setHeight(short height) { 635 | this.height = height; 636 | } 637 | 638 | public float getHeightInPoints() { 639 | return heightInPoints; 640 | } 641 | 642 | public void setHeightInPoints(float heightInPoints) { 643 | this.heightInPoints = heightInPoints; 644 | } 645 | 646 | public CellStyle getRowStyle() { 647 | return rowStyle; 648 | } 649 | 650 | public void setRowStyle(CellStyle rowStyle) { 651 | this.rowStyle = rowStyle; 652 | } 653 | 654 | public boolean isZeroHeight() { 655 | return zeroHeight; 656 | } 657 | 658 | public void setZeroHeight(boolean zeroHeight) { 659 | this.zeroHeight = zeroHeight; 660 | } 661 | 662 | public InnerCell getCell(Integer colIndex) { 663 | return cellMap.get(colIndex); 664 | } 665 | 666 | public void setCell(Integer colIndex, InnerCell cell) { 667 | cellMap.put(colIndex, cell); 668 | } 669 | } 670 | 671 | private static class InnerCell { 672 | 673 | private CellStyle cellStyle; 674 | private int cellType; 675 | 676 | public CellStyle getCellStyle() { 677 | return cellStyle; 678 | } 679 | 680 | public void setCellStyle(CellStyle cellStyle) { 681 | this.cellStyle = cellStyle; 682 | } 683 | 684 | public int getCellType() { 685 | return cellType; 686 | } 687 | 688 | public void setCellType(int cellType) { 689 | this.cellType = cellType; 690 | } 691 | } 692 | 693 | @SuppressWarnings("rawtypes") 694 | private static void writeHead(boolean useTemplate, Sheet sheet, ExcelWriteSheetProcessor sheetProcessor) { 695 | Integer headRowIndex = sheetProcessor.getHeadRowIndex(); 696 | if (headRowIndex == null) { 697 | return; 698 | } 699 | Workbook wookbook = sheet.getWorkbook(); 700 | // use theme 701 | CellStyle style = null; 702 | if (!useTemplate && sheetProcessor.getTheme() != null) { 703 | int theme = sheetProcessor.getTheme(); 704 | if (theme == ExcelWriteTheme.BASE) { 705 | style = wookbook.createCellStyle(); 706 | style.setFillPattern(CellStyle.SOLID_FOREGROUND); 707 | style.setFillForegroundColor((short) 44); 708 | style.setBorderBottom(CellStyle.BORDER_THIN); 709 | style.setBorderLeft(CellStyle.BORDER_THIN); 710 | style.setBorderRight(CellStyle.BORDER_THIN); 711 | style.setBorderTop(CellStyle.BORDER_THIN); 712 | // style.setBottomBorderColor((short) 44); 713 | style.setAlignment(CellStyle.ALIGN_CENTER); 714 | } 715 | // freeze Pane 716 | if (sheetProcessor.getHeadRowIndex() != null && sheetProcessor.getHeadRowIndex() == 0) { 717 | sheet.createFreezePane(0, 1, 0, 1); 718 | } 719 | } 720 | 721 | Row row = sheet.getRow(headRowIndex); 722 | if (row == null) { 723 | row = sheet.createRow(headRowIndex); 724 | } 725 | for (Map.Entry> entry : sheetProcessor.getFieldMapping().export().entrySet()) { 726 | Map map = entry.getValue(); 727 | if (map != null) { 728 | for (Map.Entry entry2 : map.entrySet()) { 729 | String head = entry2.getValue().getHead(); 730 | Integer colIndex = entry2.getKey(); 731 | Cell cell = row.getCell(colIndex); 732 | if (cell == null) { 733 | cell = row.createCell(colIndex); 734 | } 735 | // use theme 736 | if (!useTemplate && sheetProcessor.getTheme() != null) { 737 | cell.setCellStyle(style); 738 | 739 | } 740 | cell.setCellValue(head); 741 | } 742 | } 743 | } 744 | 745 | } 746 | 747 | private static void write(boolean useTemplate, Workbook workbook, OutputStream outputStream, 748 | ExcelWriteSheetProcessor... sheetProcessors) { 749 | 750 | for (ExcelWriteSheetProcessor sheetProcessor : sheetProcessors) { 751 | ExcelWriteContext context = new ExcelWriteContext(); 752 | String sheetName = sheetProcessor.getSheetName(); 753 | Integer sheetIndex = sheetProcessor.getSheetIndex(); 754 | try { 755 | if (sheetProcessor == null) { 756 | continue; 757 | } 758 | Sheet sheet = null; 759 | if (sheetProcessor.getTemplateStartRowIndex() == null 760 | && sheetProcessor.getTemplateEndRowIndex() == null) { 761 | sheetProcessor.setTemplateRows(sheetProcessor.getStartRowIndex(), sheetProcessor.getStartRowIndex()); 762 | } 763 | // sheetName priority, 764 | if (useTemplate) { 765 | if (sheetName != null) { 766 | try { 767 | sheet = workbook.getSheet(sheetName); 768 | } catch (IllegalArgumentException e) { 769 | // ignore 770 | } 771 | if (sheet != null && sheetIndex != null && !sheetIndex.equals(workbook.getSheetIndex(sheet))) { 772 | ExcelWriteException e = new ExcelWriteException("sheetName[" + sheetName 773 | + "] and sheetIndex[" + sheetIndex 774 | + "] not match."); 775 | e.setCode(ExcelWriteException.CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH); 776 | throw e; 777 | } 778 | } else if (sheetIndex != null) { 779 | try { 780 | sheet = workbook.getSheetAt(sheetIndex); 781 | } catch (IllegalArgumentException e) { 782 | // ignore 783 | } 784 | } else { 785 | ExcelWriteException e = new ExcelWriteException("sheetName and sheetIndex can't be both null"); 786 | e.setCode(ExcelWriteException.CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY); 787 | throw e; 788 | } 789 | if (sheet == null) { 790 | ExcelWriteException e = new ExcelWriteException("sheet of '" + sheetName + "' is not exist."); 791 | e.setCode(ExcelWriteException.CODE_OF_SHEET_NOT_EXIST); 792 | throw e; 793 | } 794 | } else { 795 | if (sheetName != null) { 796 | sheet = workbook.getSheet(sheetName); 797 | if (sheet != null) { 798 | if (sheetIndex != null && !sheetIndex.equals(workbook.getSheetIndex(sheet))) { 799 | ExcelWriteException e = new ExcelWriteException("sheetName[" + sheetName 800 | + "] and sheetIndex[" + sheetIndex 801 | + "] not match."); 802 | e.setCode(ExcelWriteException.CODE_OF_SHEET_NAME_AND_INDEX_NOT_MATCH); 803 | throw e; 804 | } 805 | } else { 806 | sheet = workbook.createSheet(sheetName); 807 | if (sheetIndex != null) { 808 | workbook.setSheetOrder(sheetName, sheetIndex); 809 | } 810 | } 811 | } else if (sheetIndex != null) { 812 | sheet = workbook.createSheet(); 813 | workbook.setSheetOrder(sheet.getSheetName(), sheetIndex); 814 | } else { 815 | ExcelWriteException e = new ExcelWriteException("SheetName and sheetIndex can't be both null."); 816 | e.setCode(ExcelWriteException.CODE_OF_SHEET_NAME_AND_INDEX_IS_EMPTY); 817 | throw e; 818 | } 819 | } 820 | 821 | if (sheetIndex == null) { 822 | sheetIndex = workbook.getSheetIndex(sheet); 823 | } 824 | if (sheetName == null) { 825 | sheetName = sheet.getSheetName(); 826 | } 827 | 828 | // proc sheet 829 | context.setCurSheet(sheet); 830 | context.setCurSheetIndex(sheetIndex); 831 | context.setCurSheetName(sheet.getSheetName()); 832 | context.setCurRow(null); 833 | context.setCurRowIndex(null); 834 | context.setCurCell(null); 835 | context.setCurColIndex(null); 836 | // beforeProcess 837 | sheetProcessor.beforeProcess(context); 838 | // write head 839 | writeHead(useTemplate, sheet, sheetProcessor); 840 | // sheet 841 | ExcelProcessControllerImpl controller = new ExcelProcessControllerImpl(); 842 | int writeRowIndex = sheetProcessor.getStartRowIndex(); 843 | boolean isBreak = false; 844 | Map cacheForTemplateRow = new HashMap(); 845 | 846 | List dataList = sheetProcessor.getDataList(); // 847 | if (dataList != null && !dataList.isEmpty()) { 848 | for (Object rowData : dataList) { 849 | // proc row 850 | Row row = sheet.getRow(writeRowIndex); 851 | if (row == null) { 852 | row = sheet.createRow(writeRowIndex); 853 | } 854 | InnerRow templateRow = getTemplateRow(cacheForTemplateRow, sheet, sheetProcessor, writeRowIndex); 855 | if (templateRow != null) { 856 | row.setHeight(templateRow.getHeight()); 857 | row.setHeightInPoints(templateRow.getHeightInPoints()); 858 | row.setRowStyle(templateRow.getRowStyle()); 859 | row.setZeroHeight(templateRow.isZeroHeight()); 860 | } 861 | context.setCurRow(row); 862 | context.setCurRowIndex(writeRowIndex); 863 | context.setCurColIndex(null); 864 | context.setCurCell(null); 865 | // 866 | try { 867 | controller.reset(); 868 | if (sheetProcessor.getRowProcessor() != null) { 869 | sheetProcessor.getRowProcessor().process(controller, context, rowData, row); 870 | } 871 | if (!controller.isDoSkip()) { 872 | writeRow(context, templateRow, row, rowData, sheetProcessor); 873 | writeRowIndex++; 874 | } 875 | if (controller.isDoBreak()) { 876 | isBreak = true; 877 | break; 878 | } 879 | } catch (RuntimeException e) { 880 | if (e instanceof ExcelWriteException) { 881 | ExcelWriteException ewe = (ExcelWriteException) e; 882 | // ef.setColIndex(null); user may want to set this value, 883 | ewe.setRowIndex(writeRowIndex); 884 | throw ewe; 885 | } else { 886 | ExcelWriteException ewe = new ExcelWriteException(e); 887 | ewe.setColIndex(null); 888 | ewe.setCode(ExcelWriteException.CODE_OF_PROCESS_EXCEPTION); 889 | ewe.setRowIndex(writeRowIndex); 890 | throw ewe; 891 | } 892 | } 893 | } 894 | if (isBreak) { 895 | break; 896 | } 897 | } 898 | if (sheetProcessor.getTemplateStartRowIndex() != null 899 | && sheetProcessor.getTemplateEndRowIndex() != null) { 900 | writeDataValidations(sheet, sheetProcessor); 901 | writeStyleAfterFinish(useTemplate, sheet, sheetProcessor); 902 | } 903 | } catch (Throwable e) { 904 | if (e instanceof ExcelWriteException) { 905 | ExcelWriteException e0 = (ExcelWriteException) e; 906 | e0.setSheetName(sheetName); 907 | e0.setSheetIndex(sheetIndex); 908 | sheetProcessor.onException(context, e0); 909 | } else { 910 | ExcelWriteException e0 = new ExcelWriteException(e); 911 | e0.setSheetName(sheetName); 912 | e0.setSheetIndex(sheetIndex); 913 | e0.setCode(ExcelWriteException.CODE_OF_PROCESS_EXCEPTION); 914 | sheetProcessor.onException(context, e0); 915 | } 916 | } finally { 917 | sheetProcessor.afterProcess(context); 918 | } 919 | } 920 | 921 | try { 922 | workbook.write(outputStream); 923 | } catch (IOException e) { 924 | throw new RuntimeException(e); 925 | } 926 | } 927 | 928 | private static InnerRow getTemplateRow(Map cache, Sheet sheet, 929 | ExcelWriteSheetProcessor sheetProcessor, int rowIndex) { 930 | InnerRow cachedRow = cache.get(rowIndex); 931 | if (cachedRow != null || cache.containsKey(rowIndex)) { 932 | return cachedRow; 933 | } 934 | InnerRow templateRow = null; 935 | if (sheetProcessor.getTemplateStartRowIndex() != null && sheetProcessor.getTemplateEndRowIndex() != null) { 936 | if (rowIndex <= sheetProcessor.getTemplateEndRowIndex()) { 937 | return null; 938 | } 939 | int tempRowIndex = (rowIndex - sheetProcessor.getTemplateEndRowIndex() - 1) 940 | % (sheetProcessor.getTemplateEndRowIndex() - sheetProcessor.getTemplateStartRowIndex() + 1) 941 | + sheetProcessor.getTemplateStartRowIndex(); 942 | Row tempRow = sheet.getRow(tempRowIndex); 943 | if (tempRow != null) { 944 | templateRow = new InnerRow(); 945 | templateRow.setHeight(tempRow.getHeight()); 946 | templateRow.setHeightInPoints(tempRow.getHeightInPoints()); 947 | templateRow.setRowStyle(tempRow.getRowStyle()); 948 | templateRow.setZeroHeight(tempRow.getZeroHeight()); 949 | for (int i = tempRow.getFirstCellNum(); i <= tempRow.getLastCellNum(); i++) { 950 | Cell cell = tempRow.getCell(i); 951 | if (cell != null) { 952 | InnerCell innerCell = new InnerCell(); 953 | innerCell.setCellStyle(cell.getCellStyle()); 954 | innerCell.setCellType(cell.getCellType()); 955 | templateRow.setCell(i, innerCell); 956 | } 957 | } 958 | } 959 | } 960 | cache.put(rowIndex, templateRow); 961 | return templateRow; 962 | } 963 | 964 | private static void writeStyleAfterFinish(boolean useTemplate, Sheet sheet, 965 | ExcelWriteSheetProcessor sheetProcessor) { 966 | if (useTemplate) { 967 | return; 968 | } 969 | ExcelWriteFieldMapping excelWriteFieldMapping = sheetProcessor.getFieldMapping(); 970 | if (excelWriteFieldMapping == null) { 971 | return; 972 | } 973 | Map> mme = excelWriteFieldMapping.export(); 974 | if (mme == null) { 975 | return; 976 | } 977 | for (Map.Entry> entry : mme.entrySet()) { 978 | Map me = entry.getValue(); 979 | for (Integer column : me.keySet()) { 980 | sheet.autoSizeColumn(column); 981 | } 982 | } 983 | } 984 | 985 | private static void writeDataValidations(Sheet sheet, ExcelWriteSheetProcessor sheetProcessor) { 986 | int templateRowStartIndex = sheetProcessor.getTemplateStartRowIndex(); 987 | int templateRowEndIndex = sheetProcessor.getTemplateEndRowIndex(); 988 | int step = templateRowEndIndex - templateRowStartIndex + 1; 989 | int rowStartIndex = sheetProcessor.getStartRowIndex(); 990 | 991 | Set configColIndexSet = new HashSet(); 992 | for (Entry> fieldIndexMapping : sheetProcessor.getFieldMapping().export().entrySet()) { 993 | if (fieldIndexMapping == null || fieldIndexMapping.getValue() == null) { 994 | continue; 995 | } 996 | for (Entry indexProcessorMapping : fieldIndexMapping.getValue().entrySet()) { 997 | if (indexProcessorMapping == null || indexProcessorMapping.getKey() == null) { 998 | continue; 999 | } 1000 | configColIndexSet.add(indexProcessorMapping.getKey()); 1001 | } 1002 | } 1003 | 1004 | List dataValidations = sheet.getDataValidations(); 1005 | if (dataValidations != null) { 1006 | for (DataValidation dataValidation : dataValidations) { 1007 | if (dataValidation == null) { 1008 | continue; 1009 | } 1010 | CellRangeAddressList cellRangeAddressList = dataValidation.getRegions(); 1011 | if (cellRangeAddressList == null) { 1012 | continue; 1013 | } 1014 | 1015 | CellRangeAddress[] cellRangeAddresses = cellRangeAddressList.getCellRangeAddresses(); 1016 | if (cellRangeAddresses == null || cellRangeAddresses.length == 0) { 1017 | continue; 1018 | } 1019 | 1020 | CellRangeAddressList newCellRangeAddressList = new CellRangeAddressList(); 1021 | boolean validationContains = false; 1022 | for (CellRangeAddress cellRangeAddress : cellRangeAddresses) { 1023 | if (cellRangeAddress == null) { 1024 | continue; 1025 | } 1026 | if (templateRowEndIndex < cellRangeAddress.getFirstRow() 1027 | || templateRowStartIndex > cellRangeAddress.getLastRow()) {// specify row 1028 | continue; 1029 | } 1030 | for (Integer configColIndex : configColIndexSet) { 1031 | if (configColIndex < cellRangeAddress.getFirstColumn() 1032 | || configColIndex > cellRangeAddress.getLastColumn()) {// specify column 1033 | continue; 1034 | } 1035 | if (templateRowStartIndex == templateRowEndIndex) { 1036 | newCellRangeAddressList.addCellRangeAddress(rowStartIndex, configColIndex, 1037 | sheet.getLastRowNum(), configColIndex); 1038 | validationContains = true; 1039 | } else { 1040 | int start = cellRangeAddress.getFirstRow() > templateRowStartIndex ? cellRangeAddress.getFirstRow() : templateRowStartIndex; 1041 | int end = cellRangeAddress.getLastRow() < templateRowEndIndex ? cellRangeAddress.getLastRow() : templateRowEndIndex; 1042 | long lastRow = sheet.getLastRowNum(); 1043 | if (lastRow > end) { 1044 | long count = (lastRow - templateRowEndIndex) / step; 1045 | int i = templateRowEndIndex; 1046 | for (; i < count; i++) { 1047 | newCellRangeAddressList.addCellRangeAddress(start + i * step, configColIndex, 1048 | end + i * step, configColIndex); 1049 | validationContains = true; 1050 | } 1051 | long _start = start + i * step; 1052 | if (_start <= lastRow) { 1053 | long _end = end + i * step; 1054 | _end = _end < lastRow ? _end : lastRow; 1055 | newCellRangeAddressList.addCellRangeAddress((int) _start, configColIndex, 1056 | (int) _end, configColIndex); 1057 | validationContains = true; 1058 | } 1059 | } 1060 | } 1061 | } 1062 | } 1063 | if (validationContains) { 1064 | DataValidation newDataValidation = sheet.getDataValidationHelper().createValidation(dataValidation.getValidationConstraint(), 1065 | newCellRangeAddressList); 1066 | sheet.addValidationData(newDataValidation); 1067 | } 1068 | } 1069 | } 1070 | } 1071 | 1072 | private static void writeRow(ExcelWriteContext context, InnerRow templateRow, Row row, Object rowData, 1073 | ExcelWriteSheetProcessor sheetProcessor) { 1074 | boolean useTemplate = false; 1075 | if (templateRow != null) { 1076 | useTemplate = true; 1077 | } 1078 | ExcelWriteFieldMapping fieldMapping = sheetProcessor.getFieldMapping(); 1079 | for (Entry> entry : fieldMapping.export().entrySet()) { 1080 | String fieldName = entry.getKey(); 1081 | Map map = entry.getValue(); 1082 | for (Map.Entry fieldValueMapping : map.entrySet()) { 1083 | Integer colIndex = fieldValueMapping.getKey(); 1084 | ExcelWriteFieldMappingAttribute attribute = fieldValueMapping.getValue(); 1085 | Object val = null; 1086 | if (rowData != null) { 1087 | val = getFieldValue(rowData, fieldName, sheetProcessor.isTrimSpace()); 1088 | } 1089 | // proc cell 1090 | Cell cell = row.getCell(colIndex); 1091 | if (cell == null) { 1092 | cell = row.createCell(colIndex); 1093 | } 1094 | if (templateRow != null) { 1095 | InnerCell tempalteCell = templateRow.getCell(colIndex); 1096 | if (tempalteCell != null) { 1097 | cell.setCellStyle(tempalteCell.getCellStyle()); 1098 | cell.setCellType(tempalteCell.getCellType()); 1099 | } 1100 | } 1101 | context.setCurColIndex(colIndex); 1102 | context.setCurCell(cell); 1103 | 1104 | ExcelWriteCellValueMapping valueMapping = attribute.getValueMapping(); 1105 | ExcelWriteCellProcessor processor = attribute.getCellProcessor(); 1106 | if (valueMapping != null) { 1107 | String key = null; 1108 | if (val != null) { 1109 | key = val.toString(); 1110 | } 1111 | Object cval = valueMapping.get(key); 1112 | if (cval != null) { 1113 | writeCell(row.getRowNum(), colIndex, cell, cval, useTemplate, attribute, rowData); 1114 | } else { 1115 | if (!valueMapping.containsKey(key)) { 1116 | if (valueMapping.isUseDefaultValue()) { 1117 | if (valueMapping.isUseDefaultValueWithDefaultInput()) { 1118 | writeCell(row.getRowNum(), colIndex, cell, val, useTemplate, attribute, rowData); 1119 | } else { 1120 | writeCell(row.getRowNum(), colIndex, cell, valueMapping.getDefaultValue(), 1121 | useTemplate, attribute, rowData); 1122 | } 1123 | } else if (valueMapping.getDefaultProcessor() != null) { 1124 | valueMapping.getDefaultProcessor().process(context, rowData, cell); 1125 | } else { 1126 | ExcelWriteException ex = new ExcelWriteException("Field value is " + key); 1127 | ex.setCode(ExcelWriteException.CODE_OF_FIELD_VALUE_NOT_MATCH); 1128 | ex.setColIndex(colIndex); 1129 | ex.setRowIndex(row.getRowNum()); 1130 | throw ex; 1131 | } 1132 | } else { 1133 | // contains null 1134 | // ok 1135 | } 1136 | } 1137 | } else if (processor != null) { 1138 | writeCell(cell, val, useTemplate, attribute, rowData); 1139 | try { 1140 | processor.process(context, val, cell); 1141 | } catch (Throwable e) { 1142 | if (e instanceof ExcelWriteException) { 1143 | ExcelWriteException e0 = (ExcelWriteException) e; 1144 | e0.setColIndex(colIndex); 1145 | e0.setRowIndex(row.getRowNum()); 1146 | throw e0; 1147 | } else { 1148 | ExcelWriteException e0 = new ExcelWriteException(e); 1149 | e0.setRowIndex(row.getRowNum()); 1150 | e0.setColIndex(colIndex); 1151 | e0.setCode(ExcelWriteException.CODE_OF_PROCESS_EXCEPTION); 1152 | throw e0; 1153 | } 1154 | } 1155 | } else { 1156 | writeCell(cell, val, useTemplate, attribute, rowData); 1157 | } 1158 | } 1159 | } 1160 | } 1161 | 1162 | @SuppressWarnings("rawtypes") 1163 | private static Object getFieldValue(Object obj, String fieldName, boolean isTrimSpace) { 1164 | Object val = null; 1165 | if (obj instanceof Map) { 1166 | val = ((Map) obj).get(fieldName); 1167 | } else {// java bean 1168 | val = getProperty(obj, fieldName); 1169 | } 1170 | // trim 1171 | if (val != null && val instanceof String && isTrimSpace) { 1172 | val = ((String) val).trim(); 1173 | if ("".equals(val)) { 1174 | val = null; 1175 | } 1176 | } 1177 | return val; 1178 | } 1179 | 1180 | private static void writeCell(int rowIndex, int colIndex, Cell cell, Object val, boolean userTemplate, 1181 | ExcelWriteFieldMappingAttribute attribute, Object bean) { 1182 | try { 1183 | writeCell(cell, val, userTemplate, attribute, bean); 1184 | } catch (Throwable e) { 1185 | if (e instanceof ExcelWriteException) { 1186 | ExcelWriteException e0 = new ExcelWriteException(); 1187 | e0.setRowIndex(rowIndex); 1188 | e0.setColIndex(colIndex); 1189 | throw e0; 1190 | } else { 1191 | ExcelWriteException e0 = new ExcelWriteException(e); 1192 | e0.setRowIndex(rowIndex); 1193 | e0.setColIndex(colIndex); 1194 | e0.setCode(ExcelWriteException.CODE_OF_PROCESS_EXCEPTION); 1195 | throw e0; 1196 | } 1197 | } 1198 | } 1199 | 1200 | public static void writeCell(Cell cell, Object val) { 1201 | if (cell.getCellStyle() != null && cell.getCellStyle().getDataFormat() > 0) { 1202 | writeCell(cell, val, true, null, null); 1203 | } else { 1204 | writeCell(cell, val, false, null, null); 1205 | } 1206 | } 1207 | 1208 | @SuppressWarnings("unused") 1209 | private static void writeCell(Cell cell, Object val, boolean userTemplate, 1210 | ExcelWriteFieldMappingAttribute attribute, Object bean) { 1211 | if (attribute != null && attribute.getLinkField() != null) { 1212 | String addressFieldName = attribute.getLinkField(); 1213 | String address = null; 1214 | if (bean != null) { 1215 | address = (String) getFieldValue(bean, addressFieldName, true); 1216 | } 1217 | Workbook wb = cell.getRow().getSheet().getWorkbook(); 1218 | 1219 | Hyperlink link = wb.getCreationHelper().createHyperlink(attribute.getLinkType()); 1220 | link.setAddress(address); 1221 | cell.setHyperlink(link); 1222 | // Its style can't inherit from cell. 1223 | CellStyle style = wb.createCellStyle(); 1224 | Font hlinkFont = wb.createFont(); 1225 | hlinkFont.setUnderline(Font.U_SINGLE); 1226 | hlinkFont.setColor(IndexedColors.BLUE.getIndex()); 1227 | style.setFont(hlinkFont); 1228 | if (cell.getCellStyle() != null) { 1229 | style.setFillBackgroundColor(cell.getCellStyle().getFillBackgroundColor()); 1230 | } 1231 | cell.setCellStyle(style); 1232 | } 1233 | if (val == null) { 1234 | cell.setCellValue((String) null); 1235 | return; 1236 | } 1237 | Class clazz = val.getClass(); 1238 | if (val instanceof Byte) {// Double 1239 | Byte temp = (Byte) val; 1240 | cell.setCellValue((double) temp.byteValue()); 1241 | } else if (val instanceof Short) { 1242 | Short temp = (Short) val; 1243 | cell.setCellValue((double) temp.shortValue()); 1244 | } else if (val instanceof Integer) { 1245 | Integer temp = (Integer) val; 1246 | cell.setCellValue((double) temp.intValue()); 1247 | } else if (val instanceof Long) { 1248 | Long temp = (Long) val; 1249 | cell.setCellValue((double) temp.longValue()); 1250 | } else if (val instanceof Float) { 1251 | Float temp = (Float) val; 1252 | cell.setCellValue((double) temp.floatValue()); 1253 | } else if (val instanceof Double) { 1254 | Double temp = (Double) val; 1255 | cell.setCellValue((double) temp.doubleValue()); 1256 | } else if (val instanceof Date) {// Date 1257 | Date dateVal = (Date) val; 1258 | long time = dateVal.getTime(); 1259 | // read is based on 1899/12/31 but DateUtil.getExcelDate is base on 1260 | // 1900/01/01 1261 | if (time >= TIME_1899_12_31_00_00_00_000 && time < TIME_1900_01_01_00_00_00_000) { 1262 | Date incOneDay = new Date(time + 24 * 60 * 60 * 1000); 1263 | double d = DateUtil.getExcelDate(incOneDay); 1264 | cell.setCellValue(d - 1); 1265 | } else { 1266 | cell.setCellValue(dateVal); 1267 | } 1268 | 1269 | if (!userTemplate) { 1270 | Workbook wb = cell.getRow().getSheet().getWorkbook(); 1271 | CellStyle cellStyle = cell.getCellStyle(); 1272 | if (cellStyle == null) { 1273 | cellStyle = wb.createCellStyle(); 1274 | } 1275 | DataFormat dataFormat = wb.getCreationHelper().createDataFormat(); 1276 | // @see #BuiltinFormats 1277 | // 0xe, "m/d/yy" 1278 | // 0x14 "h:mm" 1279 | // 0x16 "m/d/yy h:mm" 1280 | // {@linke https://en.wikipedia.org/wiki/Year_10,000_problem} 1281 | /** [1899/12/31 00:00:00:000~1900/01/01 00:00:000) */ 1282 | if (time >= TIME_1899_12_31_00_00_00_000 && time < TIME_1900_01_02_00_00_00_000) { 1283 | cellStyle.setDataFormat(dataFormat.getFormat("h:mm")); 1284 | // cellStyle.setDataFormat(dataFormat.getFormat("m/d/yy h:mm")); 1285 | } else { 1286 | // if ( time % (24 * 60 * 60 * 1000) == 0) {//for time 1287 | // zone,we can't use this way. 1288 | Calendar calendar = Calendar.getInstance(); 1289 | calendar.setTime(dateVal); 1290 | int hour = calendar.get(Calendar.HOUR_OF_DAY); 1291 | int minute = calendar.get(Calendar.MINUTE); 1292 | int second = calendar.get(Calendar.SECOND); 1293 | int millisecond = calendar.get(Calendar.MILLISECOND); 1294 | if (millisecond == 0 && second == 0 && minute == 0 && hour == 0) { 1295 | cellStyle.setDataFormat(dataFormat.getFormat("m/d/yy")); 1296 | } else { 1297 | cellStyle.setDataFormat(dataFormat.getFormat("m/d/yy h:mm")); 1298 | } 1299 | } 1300 | cell.setCellStyle(cellStyle); 1301 | } 1302 | } else if (val instanceof Boolean) {// Boolean 1303 | cell.setCellValue(((Boolean) val).booleanValue()); 1304 | } else {// String 1305 | cell.setCellValue((String) val.toString()); 1306 | } 1307 | } 1308 | 1309 | private static class ExcelProcessControllerImpl implements ExcelProcessController { 1310 | 1311 | private boolean doSkip = false; 1312 | private boolean doBreak = false; 1313 | 1314 | public boolean isDoSkip() { 1315 | return doSkip; 1316 | } 1317 | 1318 | public boolean isDoBreak() { 1319 | return doBreak; 1320 | } 1321 | 1322 | public void doSkip() { 1323 | this.doSkip = true; 1324 | } 1325 | 1326 | public void doBreak() { 1327 | this.doBreak = true; 1328 | } 1329 | 1330 | public void reset() { 1331 | this.doBreak = false; 1332 | this.doSkip = false; 1333 | } 1334 | } 1335 | 1336 | /** 1337 | * Convert excel column character index (such as 'A','B','AC') to integer index (0-based) 1338 | * note: character index ignores case 1339 | * eg: 'A' -> 0 1340 | * 'B' -> 1 1341 | * 'AC' -> 28 1342 | * 'aC' -> 28 1343 | * 'Ac' -> 28 1344 | * @param colIndex column character index 1345 | * @return column integer index 1346 | * @see #convertColIntIndexToCharIndex 1347 | */ 1348 | public static int convertColCharIndexToIntIndex(String colIndex) { 1349 | char[] chars = colIndex.toCharArray(); 1350 | int index = 0; 1351 | int baseStep = 'z' - 'a' + 1; 1352 | int curStep = 1; 1353 | for (int i = chars.length - 1; i >= 0; i--) { 1354 | char ch = chars[i]; 1355 | if (ch >= 'A' && ch <= 'Z') { 1356 | index += (ch - 'A' + 1) * curStep; 1357 | } else if (ch >= 'a' && ch <= 'z') { 1358 | index += (ch - 'a' + 1) * curStep; 1359 | } else { 1360 | throw new IllegalArgumentException("colIndex must be a-z or A-Z,unexpected character:" + ch); 1361 | } 1362 | curStep *= baseStep; 1363 | } 1364 | index--; 1365 | return index; 1366 | } 1367 | 1368 | /** 1369 | * Convert excel column integer index (0-based) to character index (such as 'A','B','AC') 1370 | * eg: 0 -> 'A' 1371 | * 1 -> 'B' 1372 | * 28 -> 'AC' 1373 | * @param colIndex column integer index. 1374 | * @return column character index in capitals 1375 | * @ #convertColCharIndexToIntIndex 1376 | */ 1377 | public static String convertColIntIndexToCharIndex(Integer index) { 1378 | Assert.isTrue(index >= 0); 1379 | StringBuilder sb = new StringBuilder(); 1380 | do { 1381 | char c = (char) ((index % 26) + 'A'); 1382 | sb.insert(0, c); 1383 | index = index / 26 - 1; 1384 | } while (index >= 0); 1385 | return sb.toString(); 1386 | } 1387 | 1388 | private static Object getProperty(Object obj, String fieldName) { 1389 | PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), fieldName); 1390 | if (pd == null || pd.getReadMethod() == null) { 1391 | throw new IllegalStateException("In class" + obj.getClass() + ", no getter method found for field '" 1392 | + fieldName + "'"); 1393 | } 1394 | try { 1395 | return pd.getReadMethod().invoke(obj, (Object[]) null); 1396 | } catch (Exception e) { 1397 | throw new RuntimeException(e); 1398 | } 1399 | } 1400 | 1401 | private static void setProperty(Object obj, String fieldName, Object value) throws IllegalAccessException, 1402 | IllegalArgumentException, 1403 | InvocationTargetException { 1404 | PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), fieldName); 1405 | if (pd == null || pd.getWriteMethod() == null) { 1406 | throw new IllegalStateException("In class" + obj.getClass() + "no setter method found for field '" 1407 | + fieldName + "'"); 1408 | } 1409 | Class paramType = pd.getWriteMethod().getParameterTypes()[0]; 1410 | if (value != null && !paramType.isAssignableFrom(value.getClass())) { 1411 | value = TypeUtils.cast(value, paramType, null); 1412 | } 1413 | pd.getWriteMethod().invoke(obj, value); 1414 | } 1415 | 1416 | private static PropertyDescriptor getPropertyDescriptor(Class clazz, String propertyName) { 1417 | return BeanUtils.getPropertyDescriptor(clazz, propertyName); 1418 | } 1419 | } 1420 | --------------------------------------------------------------------------------