From d011846d84ceb24d71e29c9b3473f32c116b5b5c Mon Sep 17 00:00:00 2001 From: wangbing <1919101440@qq.com> Date: Mon, 11 Nov 2019 00:00:36 +0800 Subject: [PATCH] init --- .gitignore | 16 + pom.xml | 40 + src/main/java/com/wb/excel/api/Excel.java | 341 +++++ .../com/wb/excel/api/annotation/Enum.java | 17 + .../wb/excel/api/annotation/EnumValue.java | 26 + .../excel/api/annotation/ExcelCollection.java | 39 + .../wb/excel/api/annotation/ExcelVerify.java | 94 ++ .../api/annotation/HeaderDescription.java | 17 + .../wb/excel/api/annotation/HeaderName.java | 31 + .../wb/excel/api/annotation/IsDuplicated.java | 17 + .../com/wb/excel/api/annotation/NoRepeat.java | 17 + .../wb/excel/api/annotation/ParentFirst.java | 16 + .../com/wb/excel/api/annotation/Split.java | 28 + .../wb/excel/api/annotation/Substring.java | 18 + .../com/wb/excel/api/annotation/Type.java | 19 + .../java/com/wb/excel/api/datatable/Cell.java | 59 + .../com/wb/excel/api/datatable/Column.java | 109 ++ .../com/wb/excel/api/datatable/DataExcel.java | 60 + .../com/wb/excel/api/datatable/DataRow.java | 14 + .../com/wb/excel/api/datatable/DataTable.java | 1194 +++++++++++++++++ .../wb/excel/api/datatable/ExcelImport.java | 601 +++++++++ .../wb/excel/api/datatable/ImportParams.java | 62 + .../wb/excel/api/entity/DataVerifyResult.java | 51 + .../api/entity/ExcelCollectionEntity.java | 61 + .../com/wb/excel/api/entity/ExcelEntity.java | 124 ++ .../excel/api/entity/ExcelImportEntity.java | 37 + .../excel/api/entity/ExcelImportResult.java | 183 +++ .../excel/api/entity/ExcelVerifyEntity.java | 141 ++ .../wb/excel/api/enumeration/DataType.java | 119 ++ .../com/wb/excel/api/enumeration/Gender.java | 18 + .../com/wb/excel/api/enumeration/Status.java | 50 + .../com/wb/excel/api/enumeration/YesNo.java | 18 + .../ColumnNameNotExistException.java | 32 + .../com/wb/excel/api/exception/Error.java | 52 + .../com/wb/excel/api/exception/ErrorType.java | 38 + .../exception/ExistedColumnNameException.java | 32 + .../exception/IllegalParameterException.java | 32 + .../exception/TemplateNotMatchException.java | 29 + .../wb/excel/api/interfaces/EnumSupport.java | 38 + .../api/interfaces/IExcelVerifyHandler.java | 34 + .../com/wb/excel/api/style/BaseCellStyle.java | 29 + .../java/com/wb/excel/api/style/BaseFont.java | 29 + .../api/style/CheckFailureCellStyle.java | 44 + .../api/style/CheckMessageCellStyle.java | 24 + .../api/style/CheckSuccessCellStyle.java | 40 + .../wb/excel/api/style/ErrorCellStyle.java | 39 + .../excel/api/style/ErrorNumberCellStyle.java | 17 + .../com/wb/excel/api/style/HeadCellStyle.java | 39 + .../wb/excel/api/style/NormalCellStyle.java | 28 + .../com/wb/excel/api/style/NormalFont.java | 18 + .../api/style/NormalNumberCellStyle.java | 17 + .../java/com/wb/excel/api/style/RedFont.java | 18 + .../com/wb/excel/api/util/BaseVerifyUtil.java | 135 ++ .../java/com/wb/excel/api/util/ClassUtil.java | 195 +++ .../com/wb/excel/api/util/DataTableUtil.java | 46 + .../java/com/wb/excel/api/util/EnumUtil.java | 127 ++ .../java/com/wb/excel/api/util/ExcelUtil.java | 32 + .../com/wb/excel/api/util/StringUtil.java | 206 +++ .../com/wb/excel/api/util/StringUtils.java | 146 ++ .../com/wb/excel/api/util/TransferUtil.java | 101 ++ .../com/wb/excel/api/util/ValidationUtil.java | 241 ++++ .../com/wb/excel/api/util/VerifyDataUtil.java | 64 + src/test/java/ExampleTest.java | 109 ++ src/test/java/User.java | 55 + 64 files changed, 5723 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/com/wb/excel/api/Excel.java create mode 100644 src/main/java/com/wb/excel/api/annotation/Enum.java create mode 100644 src/main/java/com/wb/excel/api/annotation/EnumValue.java create mode 100644 src/main/java/com/wb/excel/api/annotation/ExcelCollection.java create mode 100644 src/main/java/com/wb/excel/api/annotation/ExcelVerify.java create mode 100644 src/main/java/com/wb/excel/api/annotation/HeaderDescription.java create mode 100644 src/main/java/com/wb/excel/api/annotation/HeaderName.java create mode 100644 src/main/java/com/wb/excel/api/annotation/IsDuplicated.java create mode 100644 src/main/java/com/wb/excel/api/annotation/NoRepeat.java create mode 100644 src/main/java/com/wb/excel/api/annotation/ParentFirst.java create mode 100644 src/main/java/com/wb/excel/api/annotation/Split.java create mode 100644 src/main/java/com/wb/excel/api/annotation/Substring.java create mode 100644 src/main/java/com/wb/excel/api/annotation/Type.java create mode 100644 src/main/java/com/wb/excel/api/datatable/Cell.java create mode 100644 src/main/java/com/wb/excel/api/datatable/Column.java create mode 100644 src/main/java/com/wb/excel/api/datatable/DataExcel.java create mode 100644 src/main/java/com/wb/excel/api/datatable/DataRow.java create mode 100644 src/main/java/com/wb/excel/api/datatable/DataTable.java create mode 100644 src/main/java/com/wb/excel/api/datatable/ExcelImport.java create mode 100644 src/main/java/com/wb/excel/api/datatable/ImportParams.java create mode 100644 src/main/java/com/wb/excel/api/entity/DataVerifyResult.java create mode 100644 src/main/java/com/wb/excel/api/entity/ExcelCollectionEntity.java create mode 100644 src/main/java/com/wb/excel/api/entity/ExcelEntity.java create mode 100644 src/main/java/com/wb/excel/api/entity/ExcelImportEntity.java create mode 100644 src/main/java/com/wb/excel/api/entity/ExcelImportResult.java create mode 100644 src/main/java/com/wb/excel/api/entity/ExcelVerifyEntity.java create mode 100644 src/main/java/com/wb/excel/api/enumeration/DataType.java create mode 100644 src/main/java/com/wb/excel/api/enumeration/Gender.java create mode 100644 src/main/java/com/wb/excel/api/enumeration/Status.java create mode 100644 src/main/java/com/wb/excel/api/enumeration/YesNo.java create mode 100644 src/main/java/com/wb/excel/api/exception/ColumnNameNotExistException.java create mode 100644 src/main/java/com/wb/excel/api/exception/Error.java create mode 100644 src/main/java/com/wb/excel/api/exception/ErrorType.java create mode 100644 src/main/java/com/wb/excel/api/exception/ExistedColumnNameException.java create mode 100644 src/main/java/com/wb/excel/api/exception/IllegalParameterException.java create mode 100644 src/main/java/com/wb/excel/api/exception/TemplateNotMatchException.java create mode 100644 src/main/java/com/wb/excel/api/interfaces/EnumSupport.java create mode 100644 src/main/java/com/wb/excel/api/interfaces/IExcelVerifyHandler.java create mode 100644 src/main/java/com/wb/excel/api/style/BaseCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/BaseFont.java create mode 100644 src/main/java/com/wb/excel/api/style/CheckFailureCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/CheckMessageCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/CheckSuccessCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/ErrorCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/ErrorNumberCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/HeadCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/NormalCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/NormalFont.java create mode 100644 src/main/java/com/wb/excel/api/style/NormalNumberCellStyle.java create mode 100644 src/main/java/com/wb/excel/api/style/RedFont.java create mode 100644 src/main/java/com/wb/excel/api/util/BaseVerifyUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/ClassUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/DataTableUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/EnumUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/ExcelUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/StringUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/StringUtils.java create mode 100644 src/main/java/com/wb/excel/api/util/TransferUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/ValidationUtil.java create mode 100644 src/main/java/com/wb/excel/api/util/VerifyDataUtil.java create mode 100644 src/test/java/ExampleTest.java create mode 100644 src/test/java/User.java diff --git a/.gitignore b/.gitignore index 32858aa..2034201 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,19 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + + +/.idea +*.iml +/.settings +/bin +/gen +/build +/gradle +/classes +.classpath +.project +*.gradle +*.bat +gradlew +local.properties diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e5f6851 --- /dev/null +++ b/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + xyx.wbsite + wexcel + 1.0-SNAPSHOT + + + + org.hibernate + hibernate-validator + + + org.hibernate + hibernate-validator + 5.1.2.Final + + + + org.apache.poi + poi-ooxml + 3.8 + + + + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/src/main/java/com/wb/excel/api/Excel.java b/src/main/java/com/wb/excel/api/Excel.java new file mode 100644 index 0000000..8976295 --- /dev/null +++ b/src/main/java/com/wb/excel/api/Excel.java @@ -0,0 +1,341 @@ +package com.wb.excel.api; + +import com.wb.excel.api.annotation.HeaderDescription; +import com.wb.excel.api.datatable.Cell; +import com.wb.excel.api.datatable.Column; +import com.wb.excel.api.datatable.DataTable; +import com.wb.excel.api.enumeration.DataType; +import com.wb.excel.api.enumeration.Status; +import com.wb.excel.api.style.*; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +/** + * Excel帮助类. + *

+ * Created on 2014/9/27. + * + * @author + * @since 0.1.0 + */ +public class Excel { + /** + * Excel表格 + */ + private XSSFWorkbook workbook; + + /** + * 表头样式 + */ + private CellStyle headCellStyle; + + /** + * 错误单元格的样式 + */ + private CellStyle errorCellStyle; + + /** + * 错误的数字单元格的样式(数字靠右) + */ + private CellStyle errorNumberCellStyle; + + /** + * 普通单元格的样式 + */ + private CellStyle normalCellStyle; + + /** + * 普通数字单元格的样式 + */ + private CellStyle normalNumberCellStyle; + + /** + * 检查消息单元格的样式(最右边一列) + */ + private CellStyle checkMessageCellStyle; + + /** + * 检查结果失败的单元格的样式 + */ + private CellStyle checkFailureCellStyle; + + /** + * 检查结果通过的单元格的样式 + */ + private CellStyle checkSuccessCellStyle; + + /** + * 正常的文字 + */ + private Font normalFont; + + /** + * 红色文字 + */ + private Font redFont; + + /** + * 初始化一个Excel文件. + */ + public void init() { + workbook = new XSSFWorkbook(); + + //---------- 创建样式 ------------------ + headCellStyle = new HeadCellStyle(workbook).getStyle(); + errorCellStyle = new ErrorCellStyle(workbook).getStyle(); + errorNumberCellStyle = new ErrorNumberCellStyle(workbook).getStyle(); + normalCellStyle = new NormalCellStyle(workbook).getStyle(); + normalNumberCellStyle = new NormalNumberCellStyle(workbook).getStyle(); + checkMessageCellStyle = new CheckMessageCellStyle(workbook).getStyle(); + checkFailureCellStyle = new CheckFailureCellStyle(workbook).getStyle(); + checkSuccessCellStyle = new CheckSuccessCellStyle(workbook).getStyle(); + + //----------- 创建字体 ---------------- + normalFont = new NormalFont(workbook).getFont(); + redFont = new RedFont(workbook).getFont(); + } + + /** + * 默认无参构造方法. + */ + public Excel() { + init(); + } + + /** + * 将一个DataTable转换为Excel对象,不显示检查结果和错误消息栏.
+ * 通常用于导出报表. + * {@link Excel#Excel(boolean flag, DataTable... dataTable)} + * + * @param tables 要导出的DataTable集合 + */ + public Excel(DataTable... tables) { + workbook = this.initExcel(false, tables); + } + + /** + * 将一个DataTable转换为Excel对象. + * + * @param table DataTable + * @param flag 是否需要添加检查结果和错误消息栏(true,会添加;false,不会添加) + */ + @Deprecated + public Excel(DataTable table, boolean flag) { + workbook = this.initExcel(flag, table); + } + + /** + * 将若干DataTable转换为Excel对象. + * + * @param flag 是否需要添加检查结果和错误消息栏(true,会添加;false,不会添加) + * @param tables DataTable列表 + */ + public Excel(boolean flag, DataTable... tables) { + workbook = this.initExcel(flag, tables); + } + + public XSSFWorkbook initExcel(boolean flag, DataTable... tables) { + init(); + Set nameSet = new HashSet<>(tables.length); + for (DataTable table : tables) { + String name = table.getName(); + int index = 1; + while (nameSet.contains(name)) { + name = table.getName() + "(" + index + ")"; + index++; + } + nameSet.add(name); + + //创建一个Sheet表 + XSSFSheet sheet = workbook.createSheet(name); + sheet.setDefaultRowHeightInPoints(20); + Row firstRow = sheet.createRow(0); // 下标为0的行开始 + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + + //----------------表头-------------------- + if (flag) { + // 检查结果栏 + org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(0); + String columnName = DataTable.CHECK_STATUS_NAME; + firstCell.setCellStyle(headCellStyle); + firstCell.setCellValue(new XSSFRichTextString(columnName)); + sheet.setColumnWidth(0, (4 + 8) * 256); + } + // 数据栏 + int hiddenNumber = 0; + for (int j = 0; j < table.getColumnIndex(); j++) { + Column column = table.getColumns()[j]; + if (column.isHidden()) { + hiddenNumber++; + continue; + } + int k = j - hiddenNumber; + if (flag) { + k++; + } + org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(k); + String columnName = column.getName(); + XSSFRichTextString textString; + if (column.isRequired()) { + textString = new XSSFRichTextString("*" + columnName); + textString.applyFont(0, 1, redFont); + textString.applyFont(1, textString.length(), normalFont); + } else { + textString = new XSSFRichTextString(columnName); + textString.applyFont(normalFont); + } + StringBuilder sb = new StringBuilder(); + sb.append(column.getDescription()).append("\n"); + if (column.getDataType() != DataType.STRING) { + // 如果数据类型不是字符串类型,添加特殊数据类型的说明信息。 + Field[] fields = DataType.class.getDeclaredFields(); + for (Field field : fields) { + if (field.getName().equals(column.getDataType().name())) { + if (field.isAnnotationPresent(HeaderDescription.class)) { + + // 获取声明字段上的Description信息。 + HeaderDescription headerDescription = field.getAnnotation(HeaderDescription.class); + if (headerDescription.value() != null) { + sb.append(headerDescription.value()); + } + } + } + } + } + + // 如果填写了注释信息 + if (sb.length() > 1) { + XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6); + XSSFComment comment = drawing.createCellComment(anchor); + comment.setString(sb.toString()); + firstCell.setCellComment(comment); + } + firstCell.setCellValue(textString); + firstCell.setCellStyle(headCellStyle); + sheet.setColumnWidth(k, (4 + column.getCellWidth()) * 256); + } + + // 错误消息栏 + if (flag) { + org.apache.poi.ss.usermodel.Cell firstCell = firstRow.createCell(table.getColumnIndex() + 1 - hiddenNumber); + String columnName = DataTable.CHECK_STATUS_RESULT; + firstCell.setCellStyle(headCellStyle); + firstCell.setCellValue(new XSSFRichTextString(columnName)); + sheet.setColumnWidth(table.getColumnIndex() + 1, (4 + 10) * 256); + } + + // 冻结第一行 + //sheet.createFreezePane(255,1); + + //------------------数据-------------------- + for (int i = 0; i < table.getRowIndex(); i++) { + Row row = sheet.createRow(i + 1); + boolean rowFlag = true; + + //如果该行有错误 + if (flag) { + org.apache.poi.ss.usermodel.Cell xssfCell = row.createCell(0); + if (table.getRowError(i) != null) { + rowFlag = false; + xssfCell.setCellValue("不通过"); + xssfCell.setCellStyle(checkFailureCellStyle); + } else { + xssfCell.setCellValue("通过"); + xssfCell.setCellStyle(checkSuccessCellStyle); + } + } + + int j = 0; + hiddenNumber = 0; + for (; j < table.getColumnIndex(); j++) { + Column column = table.getColumns()[j]; + if (column.isHidden()) { + hiddenNumber++; + continue; + } + int k = j - hiddenNumber; + if (flag) { + k++; + } + + org.apache.poi.ss.usermodel.Cell xssfCell = row.createCell(k); + Cell cell = table.getCell(i, j); + if (null == cell) { + continue; + } + String value = cell.getValue(); + xssfCell.setCellValue(value); + + // 如果该列是数字类型,则靠右 + if (table.getColumns()[j].getDataType() == DataType.DECIMAL + || table.getColumns()[j].getDataType() == DataType.NUMBER + || table.getColumns()[j].getDataType() == DataType.LONG) { + if (flag && !cell.getStatus().equals(Status.PASS)) { + xssfCell.setCellStyle(errorNumberCellStyle); + } else { + xssfCell.setCellStyle(normalNumberCellStyle); + } + } else { + if (flag && !cell.getStatus().equals(Status.PASS)) { + xssfCell.setCellStyle(errorCellStyle); + } else { + xssfCell.setCellStyle(normalCellStyle); + } + } + } + + if (flag && !rowFlag) { + org.apache.poi.ss.usermodel.Cell xssfCell = row.createCell(j + 1 - hiddenNumber); + xssfCell.setCellValue(table.getRowError(i)); + xssfCell.setCellStyle(checkMessageCellStyle); + } + } + } + return workbook; + } + + /** + * 将一个DataTable转换为Excel对象 + * + * @param table DataTable + * @param flag 是否需要添加检查结果和错误消息栏 + * @return Excel的Workbook对象 + */ + @Deprecated + public XSSFWorkbook initExcel(DataTable table, boolean flag) { + return initExcel(flag, table); + } + + /** + * 得到已生成好的Excel文件的字节流信息 + * + * @return 字节流信息 + * @throws IOException + */ + public byte[] getBytes() throws IOException { + if (workbook != null) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + workbook.write(outputStream); + return outputStream.toByteArray(); + } + return null; + } + + //------------ getter & setter -------------------- + public Workbook getWorkbook() { + return workbook; + } + + public void setWorkbook(XSSFWorkbook workbook) { + this.workbook = workbook; + } +} diff --git a/src/main/java/com/wb/excel/api/annotation/Enum.java b/src/main/java/com/wb/excel/api/annotation/Enum.java new file mode 100644 index 0000000..76fe5b3 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/Enum.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * 优先通过target来判断枚举的值 + * Created on 2014/9/26. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Enum { + public Class target(); +} diff --git a/src/main/java/com/wb/excel/api/annotation/EnumValue.java b/src/main/java/com/wb/excel/api/annotation/EnumValue.java new file mode 100644 index 0000000..6acc43b --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/EnumValue.java @@ -0,0 +1,26 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * 枚举类的key所对应的value数组。

+ * 导出时: + * 如果一个字段上出现了多个value,会取出第一个作为导出内容。
+ * 如果未定义值,会把字段名作为导出内容。

+ *

+ * 导入时: + * 如果value数组中出现了导入的值,返回该value对应的key值。

+ * 但是,如果同一个文件里出现了重复的value,DataTable会默认使用第一个出现该value的Key值
+ * 不能保证第一个出现的地方是你想要的结果,所以可能会返回无法预料的结果。
+ * 所以,强烈建议使用时避免出现重复的内容。

+ * Created on 2014/9/28. + * + * @author + * @version 0.1.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EnumValue { + String[] value() default ""; +} diff --git a/src/main/java/com/wb/excel/api/annotation/ExcelCollection.java b/src/main/java/com/wb/excel/api/annotation/ExcelCollection.java new file mode 100644 index 0000000..7ae4a05 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/ExcelCollection.java @@ -0,0 +1,39 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.ArrayList; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription: 导入导出接合
+ * ***************************************************************
+ * 
+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ExcelCollection { + /** + * 名称 + * + * @return + */ + public String value(); + + /** + * 所属的排序 + * + * @return + */ + public String orderNum() default "0"; + + /** + * 创建时创建的类型 默认值是 arrayList + */ + public Class type() default ArrayList.class; +} diff --git a/src/main/java/com/wb/excel/api/annotation/ExcelVerify.java b/src/main/java/com/wb/excel/api/annotation/ExcelVerify.java new file mode 100644 index 0000000..f4a8468 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/ExcelVerify.java @@ -0,0 +1,94 @@ +/** + * Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com) + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.wb.excel.api.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excel 导入校验 + * + * @author JueYue + * @date 2014年6月23日 下午10:46:26 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ExcelVerify { + /** + * 接口校验 + * @return + */ + public boolean interHandler() default false; + + /** + * 是电子邮件 + * + * @return + */ + public boolean isEmail() default false; + + /** + * 是13位移动电话 + * + * @return + */ + public boolean isMobile() default false; + + /** + * 是座机号码 + * + * @return + */ + public boolean isTel() default false; + + /** + * 最大长度 + * + * @return + */ + public int maxLength() default -1; + + /** + * 最小长度 + * + * @return + */ + public int minLength() default -1; + + /** + * 不允许空 + * + * @return + */ + public boolean notNull() default false; + + /** + * 正在表达式 + * + * @return + */ + public String regex() default ""; + + /** + * 正在表达式,错误提示信息 + * + * @return + */ + public String regexTip() default "数据不符合规范"; + +} diff --git a/src/main/java/com/wb/excel/api/annotation/HeaderDescription.java b/src/main/java/com/wb/excel/api/annotation/HeaderDescription.java new file mode 100644 index 0000000..b6dc28b --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/HeaderDescription.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * Created on 2014/9/24. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface HeaderDescription { + String value() default ""; + +} diff --git a/src/main/java/com/wb/excel/api/annotation/HeaderName.java b/src/main/java/com/wb/excel/api/annotation/HeaderName.java new file mode 100644 index 0000000..a4b0c1a --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/HeaderName.java @@ -0,0 +1,31 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * 为字段、方法或类注解名称。
+ * Created on 2014/9/24. + * + * @author + * @version v1.0.0.0 + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface HeaderName { + String value(); + + /** + * 排序 + * + * @return + */ + public String orderNum() default "0"; + + /** + * 日期格式化 + * + * @return + */ + public String dateFormat() default "yyyy-MM-dd"; +} diff --git a/src/main/java/com/wb/excel/api/annotation/IsDuplicated.java b/src/main/java/com/wb/excel/api/annotation/IsDuplicated.java new file mode 100644 index 0000000..3131370 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/IsDuplicated.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * 是否允许该列重复。默认为false(不允许重复) + * Created on 2014/9/24. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface IsDuplicated { + boolean value() default false; +} diff --git a/src/main/java/com/wb/excel/api/annotation/NoRepeat.java b/src/main/java/com/wb/excel/api/annotation/NoRepeat.java new file mode 100644 index 0000000..4a62af4 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/NoRepeat.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * Created on 2014/9/24. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface NoRepeat { + String value() default ""; + +} diff --git a/src/main/java/com/wb/excel/api/annotation/ParentFirst.java b/src/main/java/com/wb/excel/api/annotation/ParentFirst.java new file mode 100644 index 0000000..a5347ee --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/ParentFirst.java @@ -0,0 +1,16 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * Created on 2015/5/28. + * + * @author 金洋 + * @since 2.1.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ParentFirst { + boolean value() default true; +} diff --git a/src/main/java/com/wb/excel/api/annotation/Split.java b/src/main/java/com/wb/excel/api/annotation/Split.java new file mode 100644 index 0000000..5ce2f12 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/Split.java @@ -0,0 +1,28 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * Created on 2014/9/26. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Split { + /** + * 分隔字符 + * + * @return + */ + String reg() default ""; + + /** + * 取分隔后的结果的下标。从0开始。 + * + * @return + */ + int index() default 0; +} diff --git a/src/main/java/com/wb/excel/api/annotation/Substring.java b/src/main/java/com/wb/excel/api/annotation/Substring.java new file mode 100644 index 0000000..155c6c0 --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/Substring.java @@ -0,0 +1,18 @@ +package com.wb.excel.api.annotation; + +import java.lang.annotation.*; + +/** + * Created on 2014/9/26. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Substring { + int start() default 0; + + int end() default 0; +} diff --git a/src/main/java/com/wb/excel/api/annotation/Type.java b/src/main/java/com/wb/excel/api/annotation/Type.java new file mode 100644 index 0000000..43fa41d --- /dev/null +++ b/src/main/java/com/wb/excel/api/annotation/Type.java @@ -0,0 +1,19 @@ +package com.wb.excel.api.annotation; + + +import com.wb.excel.api.enumeration.DataType; + +import java.lang.annotation.*; + +/** + * Created on 2014/9/24. + * + * @author + * @version v1.0.0.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Type { + public DataType value() default DataType.STRING; +} diff --git a/src/main/java/com/wb/excel/api/datatable/Cell.java b/src/main/java/com/wb/excel/api/datatable/Cell.java new file mode 100644 index 0000000..a53199c --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/Cell.java @@ -0,0 +1,59 @@ +package com.wb.excel.api.datatable; + + +import com.wb.excel.api.enumeration.Status; + +import java.io.Serializable; + +/** + * 单元格. + * Created on 2014/9/23. + * + * @author + * @since 0.1.0 + */ +public class Cell implements Serializable { + /** + * 单元格的状态 + */ + private Status status; + + /** + * 单元格的值 + */ + private String value; + + /** + * 默认无参构造方法.会将单元格的状态设为通过. + */ + public Cell() { + this.status = Status.PASS; + this.value = ""; + } + + /** + * 传入默认单元格值的构造方法. + * + * @param value 单元格的值. + */ + public Cell(String value) { + this.value = value; + this.status = Status.PASS; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/wb/excel/api/datatable/Column.java b/src/main/java/com/wb/excel/api/datatable/Column.java new file mode 100644 index 0000000..2224b96 --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/Column.java @@ -0,0 +1,109 @@ +package com.wb.excel.api.datatable; + + +import com.wb.excel.api.enumeration.DataType; +import com.wb.excel.api.util.StringUtil; + +import java.io.Serializable; + +/** + * DataTable中的表头,包含本列的一些限制条件。
+ * 现有:列名、是否必须、是否允许重复、说明字段以及数据类型 + * Created by edward on 9/19/14. + */ +public class Column implements Serializable { + /** + * 列名 + */ + private String name; + /** + * 该列的最大宽度 + */ + private int cellWidth; + /** + * 是否为隐藏列,如果为隐藏列,在导出Excel文件时会被忽略 + */ + private boolean isHidden; + /** + * 是否是必输列 + */ + private boolean isRequired; + /** + * 该列的描述字段 + */ + private String description; + /** + * 该列的数据类型 + */ + private DataType dataType; + + public Column() { + this.name = ""; + this.cellWidth = 1; + this.isHidden = false; + this.isRequired = false; + this.description = ""; + this.dataType = DataType.STRING; + } + + public Column(String name) { + this.name = name; + this.cellWidth = 1; + this.isHidden = false; + this.isRequired = false; + this.description = ""; + this.dataType = DataType.STRING; + } + + //----------- getter & setter -------------- + public String getName() { + return name; + } + + public void setName(String name) { + if (StringUtil.getByteLength(name) > cellWidth) { + cellWidth = StringUtil.getByteLength(name); + } + this.name = name; + } + + public int getCellWidth() { + return cellWidth; + } + + public void setCellWidth(int cellWidth) { + this.cellWidth = cellWidth; + } + + public boolean isHidden() { + return isHidden; + } + + public void setHidden(boolean isHidden) { + this.isHidden = isHidden; + } + + public boolean isRequired() { + return isRequired; + } + + public void setRequired(boolean isRequired) { + this.isRequired = isRequired; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public DataType getDataType() { + return dataType; + } + + public void setDataType(DataType dataType) { + this.dataType = dataType; + } +} diff --git a/src/main/java/com/wb/excel/api/datatable/DataExcel.java b/src/main/java/com/wb/excel/api/datatable/DataExcel.java new file mode 100644 index 0000000..3295859 --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/DataExcel.java @@ -0,0 +1,60 @@ +package com.wb.excel.api.datatable; + + +import com.wb.excel.api.entity.ExcelImportResult; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:
+ * ***************************************************************
+ * 
+ */ +public class DataExcel { +// static Logger LOGGER = Logger.getLogger(DataExcel.class); + + /** + * @param file + * @param pojoClass + * @param + * @return + */ + public static ExcelImportResult importExcel(File file, Class pojoClass, ImportParams importParams) { + FileInputStream in = null; + try { + in = new FileInputStream(file); + return new ExcelImport().importExcelByIs(in, pojoClass, importParams); + } catch (Exception e) { +// LOGGER.error(e.getMessage(), e); + } finally { + try { + in.close(); + } catch (IOException e) { +// LOGGER.error(e.getMessage(), e); + } + } + return null; + } + + + /** + * Excel 导入 数据源IO流,不返回校验结果 导入 字段类型 Integer,Long,Double,Date,String,Boolean + * + * @param inputstream + * @param pojoClass + * @return + * @throws Exception + */ + public static ExcelImportResult importExcel(InputStream inputstream, Class pojoClass, ImportParams importParams) throws Exception { + return new ExcelImport().importExcelByIs(inputstream, pojoClass, importParams); + } + + +} diff --git a/src/main/java/com/wb/excel/api/datatable/DataRow.java b/src/main/java/com/wb/excel/api/datatable/DataRow.java new file mode 100644 index 0000000..89a9879 --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/DataRow.java @@ -0,0 +1,14 @@ +package com.wb.excel.api.datatable; + +import java.io.Serializable; +import java.util.HashMap; + +/** + * DataTable中的行对象. + * Created on 2014/09/19. + * + * @author + * @since 0.1.0 + */ +public class DataRow extends HashMap implements Serializable { +} diff --git a/src/main/java/com/wb/excel/api/datatable/DataTable.java b/src/main/java/com/wb/excel/api/datatable/DataTable.java new file mode 100644 index 0000000..1f1c358 --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/DataTable.java @@ -0,0 +1,1194 @@ +package com.wb.excel.api.datatable; + +import com.wb.excel.api.annotation.*; +import com.wb.excel.api.annotation.Enum; +import com.wb.excel.api.enumeration.DataType; +import com.wb.excel.api.enumeration.Status; +import com.wb.excel.api.exception.*; +import com.wb.excel.api.exception.Error; +import com.wb.excel.api.util.*; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.DecimalMax; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotNull; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * 数据表的定义。
+ * Created on 2014/09/19. + * + * @author 沈振家 + * @since 0.1.0 + */ +public class DataTable implements Serializable, Cloneable { + + public final static String CHECK_STATUS_NAME = "检查状态"; + public final static String CHECK_STATUS_RESULT = "结果消息"; + + /** + * 初始化时最大的行数 + */ + private int MAX_ROW_NUMBER = 100; + + /** + * 初始化时最大的列数 + */ + private int MAX_COLUMN_NUMBER = 20; + + /** + * 表名 + */ + private String name; + + /** + * 表头的集合 + */ + private Column[] columns; + + /** + * 当前的行数 + */ + private int rowIndex; + private int columnIndex; + + /** + * 单元格里存放的对象 + */ + private Cell[][] data; + + /** + * 整个Table的错误列表 + */ + private List errorList; + + /** + * 每一行的错误情况。 + */ + private List> errorLists; + + /** + * 初始化准备工作。在构造方法前调用。 + */ + public void init() { + rowIndex = 0; + columnIndex = 0; + + columns = new Column[MAX_COLUMN_NUMBER]; + data = new Cell[MAX_ROW_NUMBER][MAX_COLUMN_NUMBER]; + + errorList = new ArrayList<>(); + errorLists = new ArrayList<>(MAX_ROW_NUMBER); + for (int i = 0; i < MAX_ROW_NUMBER; i++) { + errorLists.add(new ArrayList()); + } + } + + /** + * 默认构造方法。 + */ + public DataTable() { + init(); + } + + /** + * 根据输入的模板类打印下载模板。 + * + * @param clazz 模板类 + */ + public DataTable(Class clazz) { + init(); + setColumns(clazz); + } + + /** + * 根据模板类对DataTable添加相应的列。 + * + * @param clazz 模板类 + * @return 包含@Name标记的字段Set + */ + private Set setColumns(Class clazz) { + HeaderName tempHeaderName = clazz.getAnnotation(HeaderName.class); + ParentFirst parentFirstAnnotation = clazz.getAnnotation(ParentFirst.class); + boolean parentFirst = parentFirstAnnotation != null && parentFirstAnnotation.value(); + if (tempHeaderName != null) { + this.setName(tempHeaderName.value()); + } else { + this.setName(clazz.getName()); + } + //Field [] fields = clazz.getDeclaredFields(); + Field[] fields = ClassUtil.getFields(clazz, parentFirst); + Set set = new HashSet<>(); + for (Field field : fields) { + set.add(field); + Column column = null; + if (!field.isAnnotationPresent(HeaderName.class)) { + String name = field.getName(); + column = new Column(name); + } else { + HeaderName columnHeaderName = field.getAnnotation(HeaderName.class); + column = new Column(columnHeaderName.value()); + } + if (field.isAnnotationPresent(NotNull.class)) { + column.setRequired(true); + } + + if (field.isAnnotationPresent(Type.class)) { + Type type = field.getAnnotation(Type.class); + column.setDataType(type.value()); + } else { + column.setDataType(DataType.STRING); + } + + if (field.isAnnotationPresent(HeaderDescription.class)) { + column.setDescription(field.getAnnotation(HeaderDescription.class).value()); + } + this.addColumn(column); + } + return set; + } + + /** + * 此构造方法仅用于转换对象列表。
+ * 并不会对数据的格式和合法性进行检验。 + * + * @param list 需要导出的对象列表 + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws IllegalAccessException + */ + public DataTable(List list) + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + init(); + if (list == null || list.size() == 0) { + throw new IllegalParameterException("不允许传入空的列表"); + } + if (list.size() > 0) { + T tClass = list.get(0); + Set set = setColumns(tClass.getClass()); + + for (T t : list) { + DataRow row = new DataRow(); + for (Field field : set) { + + // 获取字段上的名称注解(作为列名使用) + String HeaderName = ""; + HeaderName fieldHeaderName = field.getAnnotation(HeaderName.class); + if (fieldHeaderName == null) { + HeaderName = field.getName(); + } else { + HeaderName = fieldHeaderName.value(); + } + String att = StringUtil.upperFirstWord(field.getName()); + Method method = t.getClass().getMethod("get" + att); + Object value = method.invoke(t); + if (null == value) { + row.put(fieldHeaderName.value(), new Cell()); + } else { + if (field.isAnnotationPresent(Type.class)) { + Type type = field.getAnnotation(Type.class); + switch (type.value()) { + case DATE: { + Date date = (Date) value; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + value = sdf.format(date); + break; + } + case DATETIME: { + Date date = (Date) value; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + value = sdf.format(date); + break; + } + case DATEMINUTE: { + Date date = (Date) value; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + value = sdf.format(date); + break; + } + case NUMBER: + value = StringUtil.transferInteger(value.toString()); + break; + case LONG: + value = StringUtil.transferLong(value.toString()); + break; + case BOOLEAN: + value = StringUtil.transferBoolean(value.toString()); + break; + default: + break; + } + } + + // 如果该变量包含枚举标签,处理枚举 + if (field.isAnnotationPresent(Enum.class)) { + Enum e = field.getAnnotation(Enum.class); + value = EnumUtil.getValue(e.target(), value.toString()); + } + row.put(HeaderName, new Cell(value.toString())); + } + } + this.addRow(row); + } + } + } + + /** + * 构造方法。传入Excel流,不需要指定类型。同时,也不会对数据进行检查。 + * + * @param bytes Excel的字节数组。 + * @throws IOException 可能会出现的错误。通常为以下错误:
+ * 1.流不能转换为Workbook + */ + @Deprecated + public DataTable(byte[] bytes) throws IOException, TemplateNotMatchException { + init(); + InputStream inputStream = null; //文件输入流 + Workbook workbook = null; //导入的文档 + boolean flag; //用于判断文件的类型 + try { + flag = true; + inputStream = new ByteArrayInputStream(bytes); + workbook = new HSSFWorkbook(inputStream); + } catch (Exception e) { + flag = false; + } + if (!flag) { + try { + flag = true; + inputStream = new ByteArrayInputStream(bytes); + workbook = new XSSFWorkbook(inputStream); + } catch (Exception e) { + flag = false; + } + } + if (inputStream != null) { + inputStream.close(); + } + if (!flag) { + throw new TemplateNotMatchException("不支持的文件类型"); + } + + /* 创建导入表的对象 */ + Sheet sheet = workbook.getSheetAt(0); //默认只处理第一个Sheet表 + this.setName(sheet.getSheetName()); + + /* 读取表头 */ + Row headRow = sheet.getRow(0); + int columnNum = headRow.getPhysicalNumberOfCells(); + for (int i = 0; i < columnNum; i++) { + org.apache.poi.ss.usermodel.Cell cell = headRow.getCell(i); + Column column = new Column(); + column.setName(ExcelUtil.getValue(cell)); + this.addColumn(column); + } + + /* 逐行读取导入文件的数据,从1开始是因为第0行为表头 */ + int rowNumber = sheet.getLastRowNum(); + for (int i = 1; i <= rowNumber; i++) { + Row inputRow = sheet.getRow(i); + DataRow row = new DataRow(); + if (null != inputRow) { + for (int j = 0; j < columnNum; j++) { + org.apache.poi.ss.usermodel.Cell excelCell = inputRow.getCell(j); + if (null != excelCell) { + row.put(this.getColumns()[j].getName(), new Cell(ExcelUtil.getValue(excelCell))); + } + } + } + this.addRow(row); + } + } + + /** + * 以Excel文件的字节数组为数据源,为自己赋值的同时,与指定的模板类进行数据校验。
+ * 如果匹配过程中发现了不符合的数据,会在对应的单元中添加错误信息。
+ * + * @param bytes Excel文件的字节数组 + * @param clazz 类型 + * @throws IOException
1:输入流无法转为Excel文件 - 请检查输入的 bytes 是否正确;
+ * 2:输入流关闭出错;
+ * @throws TemplateNotMatchException
1:Excel文件的列数与对象类型不匹配 - 请检查Excel表与模板类是否一致;
+ * 2:获取枚举类型出错 - 你在模板类中标注了一个变量的值为枚举类型,但程序寻找枚举类时出错;
+ */ + public DataTable(byte[] bytes, Class clazz) throws IOException, TemplateNotMatchException { + init(); + Workbook workbook = null; + InputStream is = null; + boolean flag; + try { + flag = true; + is = new ByteArrayInputStream(bytes); //读取文件流 + workbook = new HSSFWorkbook(is); + } catch (Exception e) { + flag = false; + } + if (!flag) { + try { + flag = true; + is = new ByteArrayInputStream(bytes); //读取文件流 + workbook = new XSSFWorkbook(is); + } catch (Exception e) { + flag = false; + } + } + if (is != null) { + is.close(); + } + if (!flag) { + throw new TemplateNotMatchException("不支持的文件类型"); + } + + Sheet sheet = workbook.getSheetAt(0); //处理第一张Sheet表 + String tableName = sheet.getSheetName(); //DataTable的名字 + + /* 获取指定类所有带有Name注解的属性集合 */ + HeaderName classHeaderName = clazz.getAnnotation(HeaderName.class); //该类所声明的名字 + ParentFirst parentFirstAnnotation = clazz.getAnnotation(ParentFirst.class); + boolean parentFirst = parentFirstAnnotation != null && parentFirstAnnotation.value(); + if (classHeaderName != null) { + tableName = classHeaderName.value(); + } + this.setName(tableName); //将类名设为表名,如果类名不存在,将Excel表名设为表名 + + //Field[] fields = clazz.getDeclaredFields(); //该类所声明的全部属性 + Field[] fields = ClassUtil.getFields(clazz, parentFirst); //该类所声明的全部属性 + Set set = new HashSet<>(); //用于保存所有带有Name注解的属性 + for (Field field : fields) { + if (field.isAnnotationPresent(HeaderName.class)) { + set.add(field); + } + } + + /* 读取表头 */ + Row headRow = sheet.getRow(0); + int columnSum = headRow.getPhysicalNumberOfCells(); //获取Excel列的总数 + int columnMatchNumber = 0; //匹配列的数量。用于判断Excel是否包含所有必须列。 + + /* 为Excel表中的每一列分配空间 */ + List> sets = new ArrayList<>(); + Type[] types = new Type[columnSum]; + Enum[] enums = new Enum[columnSum]; + Split[] splits = new Split[columnSum]; + Length[] lengths = new Length[columnSum]; + NotNull[] notNulls = new NotNull[columnSum]; + Substring[] substrings = new Substring[columnSum]; + DecimalMin[] decimalMins = new DecimalMin[columnSum]; + DecimalMax[] decimalMaxs = new DecimalMax[columnSum]; + HeaderDescription[] headerDescriptions = new HeaderDescription[columnSum]; + IsDuplicated[] isDuplicateds = new IsDuplicated[columnSum]; + + boolean[] matchFlag = new boolean[set.size()]; //保存字段是否出现在Excel文件中。 + + /* 查找匹配列的数量 */ + for (int i = 0; i < columnSum; i++) { + + sets.add(new HashSet()); + + org.apache.poi.ss.usermodel.Cell cell = headRow.getCell(i); + String headValue = ExcelUtil.getValue(cell); //获取列名 + headValue = headValue.replace("*", ""); + headValue = headValue.replace(" ", ""); + + int tempFieldIndex = 0; //字段的编号,临时变量 + for (Field field : set) { + HeaderName fieldHeaderName = field.getAnnotation(HeaderName.class); + if (headValue.equals(fieldHeaderName.value())) { //如果Excel列名与Class属性名相一致 + columnMatchNumber++; //标记该列的存在 + types[i] = field.getAnnotation(Type.class); + enums[i] = field.getAnnotation(Enum.class); + splits[i] = field.getAnnotation(Split.class); + lengths[i] = field.getAnnotation(Length.class); + notNulls[i] = field.getAnnotation(NotNull.class); + substrings[i] = field.getAnnotation(Substring.class); + decimalMins[i] = field.getAnnotation(DecimalMin.class); + decimalMaxs[i] = field.getAnnotation(DecimalMax.class); + headerDescriptions[i] = field.getAnnotation(HeaderDescription.class); + isDuplicateds[i] = field.getAnnotation(IsDuplicated.class); + + matchFlag[tempFieldIndex] = true; + break; + } + tempFieldIndex++; + } + Column column = new Column(); + column.setName(ExcelUtil.getValue(cell)); + if (headerDescriptions[i] != null) { + column.setDescription(headerDescriptions[i].value()); + } + if (types[i] != null) { + column.setDataType(types[i].value()); + } + if (notNulls[i] != null) { + column.setRequired(true); + } + this.addColumn(column); + } + + /* 如果文件不匹配 */ + if (columnMatchNumber != set.size()) { + StringBuilder templateExcept = new StringBuilder(); + int tempIndex = 0; + for (Field field : set) { + if (matchFlag[tempIndex++]) { + continue; + } + templateExcept.append(field.getAnnotation(HeaderName.class).value()).append("栏;"); + } + throw new TemplateNotMatchException("不匹配的Excel文件,没有:" + templateExcept.toString()); + } + + int maxRowNumber = sheet.getLastRowNum(); //Excel文件的总行数 + /* 逐行读取导入文件的数据 */ + for (int i = 0; i < maxRowNumber; i++) { + Row inputRow = sheet.getRow(i + 1); //Excel中的一行数据,第0行为表头,所以要加1 + DataRow row = new DataRow(); //DataTable中的一行 + this.addRow(row); + + if (null != inputRow) { + for (int j = 0; j < columnSum; j++) { //逐格扫描 + + /* 取得当前格子的值 */ + org.apache.poi.ss.usermodel.Cell excelCell = inputRow.getCell(j); + Cell cell = new Cell(); + this.setCell(i, columns[j].getName(), cell); + + String value = ""; + if (null != excelCell) { + value = ExcelUtil.getValue(excelCell); + } + value = value.trim(); + boolean cellFlag = true; + + /* 如果要对字符进行切分 */ + if (null != splits[j]) { + value = StringUtil.split(value, splits[j].reg(), splits[j].index()); + } + + /* 如果要截取一段字符 */ + if (null != substrings[j]) { + value = StringUtil.substring(value, substrings[j].start(), substrings[j].end()); + } + + cell.setValue(value); + + /* 如果要求非空 */ + if (null != notNulls[j]) { + if (value.length() == 0) { + this.setStatus(i, j, Status.EMPTY); + cellFlag = false; + } + } + + /* 如果属于枚举类型 */ + if (cellFlag && null != enums[j]) { + Class enumClass = enums[j].target(); + + if (!EnumUtil.check(enumClass, value)) { + this.setStatus(i, j, Status.ERROR_VALUE); + cellFlag = false; + } + } + + /* 如果对长度有要求 */ + if (cellFlag && null != lengths[j]) { + if (value.length() > lengths[j].max() || value.length() < lengths[j].min()) { + this.setStatus(i, j, Status.LENGTH); + cellFlag = false; + } + } + + /* 如果对类型有要求 */ + if (cellFlag && null != types[j] && !types[j].value().equals(DataType.STRING)) { + if (!DataType.check(types[j].value(), cell, value)) { + this.setStatus(i, j, Status.FORMAT); + cellFlag = false; + } + } + + // 如果对最小值有要求 + if (cellFlag && null != decimalMins[j] && value.length() > 0) { + Double dou = TransferUtil.transferDouble(value); + Double minValue = TransferUtil.transferDouble(decimalMins[j].value()); + if (dou < minValue) { + this.setStatus(i, j, Status.TOO_SMALL); + cellFlag = false; + } + } + + // 如果对最大值有要求 + if (cellFlag && null != decimalMaxs[j] && value.length() > 0) { + Double dou = TransferUtil.transferDouble(value); + Double maxValue = TransferUtil.transferDouble(decimalMaxs[j].value()); + if (dou > maxValue) { + this.setStatus(i, j, Status.TOO_BIG); + cellFlag = false; + } + } + + /* 如果不允许重复 */ + if (cellFlag && null != isDuplicateds[j] && !isDuplicateds[j].value()) { + if (value.length() > 0) { + int tempSize = sets.get(j).size(); + sets.get(j).add(value); + if (sets.get(j).size() == tempSize) { + this.setStatus(i, j, Status.REPEAT); + } + } + } + } + } + } + } + + + /** + * 获取所有的表头 + * + * @return 表头数组 + */ + public Column[] getColumns() { + return this.columns; + } + + /** + * 通过坐标取得单元格 + * + * @param rowNumber 行坐标 + * @param columnName 列名 + * @return 对应坐标的单元格 + * @throws IndexOutOfBoundsException 下标越界 + * @throws ColumnNameNotExistException 列名不存在 + */ + public Cell getCell(int rowNumber, String columnName) + throws IndexOutOfBoundsException, ColumnNameNotExistException { + int columnNumber = getColumnIndex(columnName); + return getCell(rowNumber, columnNumber); + } + + /** + * 通过坐标取得单元格 + * + * @param rowNumber 行坐标 + * @param columnNumber 列坐标 + * @throws IndexOutOfBoundsException 下标越界 + */ + public final Cell getCell(int rowNumber, int columnNumber) throws IndexOutOfBoundsException { + if (rowNumber > this.rowIndex || rowNumber < 0) { + throw new IndexOutOfBoundsException("不存在的行坐标: " + rowNumber); + } + if (columnNumber > this.columnIndex || columnNumber < 0) { + throw new IndexOutOfBoundsException("不存在的列坐标: " + columnNumber); + } + return data[rowNumber][columnNumber]; + } + + /** + * 设置某个单元格的值。 + * + * @param rowNumber 行坐标 + * @param columnNumber 列坐标 + * @param cell 单元格 + * @throws IndexOutOfBoundsException 坐标不存在的情况下,会报出异常,提示坐标不存在。 + */ + public void setCell(int rowNumber, int columnNumber, Cell cell) throws IndexOutOfBoundsException { + if (rowNumber > this.rowIndex || rowNumber < 0) { + throw new IndexOutOfBoundsException("不存在的行坐标: " + rowNumber); + } + if (columnNumber > this.columnIndex || columnNumber < 0) { + throw new IndexOutOfBoundsException("不存在的列坐标: " + columnNumber); + } + data[rowNumber][columnNumber] = cell; + this.setStatus(rowNumber, columnNumber, cell.getStatus()); + } + + /** + * 设置某个单元格的值。注意:传入的是值 + * + * @param rowIndex 行坐标 + * @param columnName 列坐标 + * @param cell 单元格 + * @throws IndexOutOfBoundsException 下标越界 + * @throws ColumnNameNotExistException 列名不存在 + */ + public void setCell(int rowIndex, String columnName, Cell cell) + throws IndexOutOfBoundsException, ColumnNameNotExistException { + int columnNumber = getColumnIndex(columnName); + this.setCell(rowIndex, columnNumber, cell); + } + + /** + * 设置某个单元格的状态值 。注意:传入的是值 + * + * @param rowNumber 行坐标 + * @param columnNumber 列坐标 + * @param status 状态值。 + * @throws IndexOutOfBoundsException 下标越界 + */ + public void setStatus(int rowNumber, int columnNumber, Status status) throws IndexOutOfBoundsException { + if (!status.equals(Status.PASS)) { + Cell cell = this.getCell(rowNumber, columnNumber); + if (null == cell) { + cell = new Cell(); + this.setCell(rowNumber, columnNumber, cell); + } + cell.setStatus(status); + + StringBuilder message = new StringBuilder(this.getColumns()[columnNumber].getName()); + message.append("栏"); + switch (status) { + case NOTEXIST: + message.append("不存在的关联项;"); + break; + case EMPTY: + message.append("不能为空;"); + break; + case LENGTH: + message.append("长度超出限制;"); + break; + case EXIST: + message.append("已存在的记录;"); + break; + case ERROR_VALUE: + message.append("的值无法识别;"); + break; + case REPEAT: + message.append("重复的值;"); + break; + case TOO_SMALL: + message.append("过小的值"); + break; + case TOO_BIG: + message.append("过大的值"); + break; + case FORMAT: + message.append("格式错误;"); + break; + } + this.appendError(rowNumber, message.toString()); + } + } + + /** + * 能过列名取得列下标。 + * + * @param columnName 列名 + * @return 该列对应的下标 + * @throws ColumnNameNotExistException + */ + private int getColumnIndex(String columnName) throws ColumnNameNotExistException { + int columnIndex = -1; + for (int i = 0; i < this.getColumnIndex(); i++) { + if (this.getColumns()[i].getName().equals(columnName)) { + columnIndex = i; + break; + } + } + if (columnIndex == -1) { + throw new ColumnNameNotExistException("不存在的列名:" + columnName); + } + return columnIndex; + } + + /** + * 设置某个单元格的值。注意:传入的是值 + * + * @param rowNumber 行坐标 + * @param columnName 列坐标 + * @param status 单元格 + * @throws IndexOutOfBoundsException 下标越界 + * @throws ColumnNameNotExistException 列名不存在 + */ + public void setStatus(int rowNumber, String columnName, Status status) + throws IndexOutOfBoundsException, ColumnNameNotExistException { + int currentColumn = getColumnIndex(columnName); + this.setStatus(rowNumber, currentColumn, status); + } + + /** + * 按行获取所有的单元格 + * + * @return 行的数组 + */ + public DataRow[] getDataRows() { + DataRow[] dataRows = new DataRow[this.rowIndex]; + for (int i = 0; i < this.rowIndex; i++) { + DataRow row = new DataRow(); + for (int j = 0; j < this.columnIndex; j++) { + row.put(this.columns[j].getName(), this.data[i][j]); + } + dataRows[i] = row; + } + return dataRows; + } + + /** + * 按列获取所有的单元格 + * + * @return 获取数据列的Map。 + */ + public HashMap> getDataColumns() { + HashMap> columns = new HashMap<>(); + for (int i = 0; i < this.columnIndex; i++) { + List list = new ArrayList<>(); + for (int j = 0; j < this.rowIndex; j++) { + list.add(data[j][i]); + } + columns.put(this.columns[i].getName(), list); + } + return columns; + } + + /** + * 添加一行单元格。当数据量超过定义大小的一半时,会扩大容量至之前的1.5倍。 + * + * @param row 一行记录 + */ + public void addRow(DataRow row) { + /* 如果占用了一半以上,进行扩容 */ + if (this.rowIndex >= MAX_ROW_NUMBER / 2) { + expandRow(); + } + for (int i = 0; i < this.columnIndex; i++) { + Cell cell = row.get(this.columns[i].getName()); + if (null != cell) { + this.setCell(this.rowIndex, i, cell); + int width = StringUtil.getByteLength(cell.getValue()); + if (width > this.getColumns()[i].getCellWidth()) { + if (width > 100) { + width = 100; + } + this.getColumns()[i].setCellWidth(width); + } + } + } + this.rowIndex++; + } + + /** + * 添加一列表头信息,会进行查重。当列数超过定义大小的一半时,会扩大容量至之前的1.5倍。 + * + * @param column 要加入的表头信息 + */ + public void addColumn(Column column) { + /* 如果占用了一半以上,进行扩容 */ + if (this.columnIndex >= MAX_COLUMN_NUMBER / 2) { + expandColumn(); + } + boolean exist = false; + column.setName(column.getName().replace("*", "")); //删除标题中的星号 + column.setName(column.getName().replace(" ", "")); //删除标题中的空格 + for (int i = 0; i < this.columnIndex; i++) { + if (column.getName().equals(this.getColumns()[i].getName())) { + exist = true; + } + } + if (!exist) { + this.columns[this.columnIndex++] = column; + } else { + throw new ExistedColumnNameException("已存在名称为" + column.getName() + "的列"); + } + } + + /** + * 当表空间列数不足时,扩大表和表头的列数。 + */ + protected void expandColumn() { + MAX_COLUMN_NUMBER *= (3 / 2) + 1; + /* 扩展表头 */ + Column[] temp = new Column[MAX_COLUMN_NUMBER]; + System.arraycopy(columns, 0, temp, 0, columns.length); + columns = temp; + expand(); + } + + /** + * 当表空间行数不足时,扩大表的行数。 + */ + protected void expandRow() { + int begin = MAX_ROW_NUMBER; + MAX_ROW_NUMBER *= (3 / 2) + 1; + for (int i = 0; i < (MAX_ROW_NUMBER - begin); i++) { + errorLists.add(new ArrayList()); + } + expand(); + } + + /** + * 在扩大表的大小后调用。
+ * 会先把数据复制到临时数组中,再把临时数组指向data + */ + protected void expand() { + Cell[][] temp = new Cell[MAX_ROW_NUMBER][MAX_COLUMN_NUMBER]; + for (int i = 0; i < data.length; i++) { + System.arraycopy(data[i], 0, temp[i], 0, data[0].length); + } + data = temp; + } + + /** + * 转换某行为一个对象 + * + * @param clazz 类型 + * @param rowIndex 行号 + * @return 对象 + * @throws IllegalAccessException + * @throws InstantiationException + * @throws NoSuchMethodException + * @throws InvocationTargetException + */ + public T transferOneObject(Class clazz, int rowIndex) + throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + T object = clazz.newInstance(); + ParentFirst parentFirstAnnotation = clazz.getAnnotation(ParentFirst.class); + boolean parentFirst = parentFirstAnnotation != null && parentFirstAnnotation.value(); + //Field[] fields = clazz.getDeclaredFields(); + Field[] fields = ClassUtil.getFields(clazz, parentFirst); + Set set = new HashSet<>(); + for (Field field : fields) { + if (field.isAnnotationPresent(HeaderName.class)) { + set.add(field); + } + } + + for (int j = 0; j < this.getColumnIndex(); j++) { + if (this.getColumns()[j].isHidden()) { + continue; + } + + String key = this.getColumns()[j].getName(); + if (key.equals(CHECK_STATUS_NAME) || key.equals(CHECK_STATUS_RESULT)) { + continue; + } + + for (Field field : set) { + HeaderName fieldHeaderName = field.getAnnotation(HeaderName.class); + + if (key.equals(fieldHeaderName.value())) { + + String att = StringUtil.upperFirstWord(field.getName()); + String value; + Cell cell = this.getCell(rowIndex, j); + if (null != cell) { + value = cell.getValue(); + Method method = clazz.getMethod("set" + att, field.getType()); + if (field.isAnnotationPresent(Enum.class)) { + Enum e = field.getAnnotation(Enum.class); + String sValue = EnumUtil.getKey(e.target(), value); + if (field.getType() == String.class) { + method.invoke(object, sValue); + } else { + method.invoke(object, EnumUtil.valueOf(e.target(), sValue)); + } + } else if (field.isAnnotationPresent(Type.class)) { + Type type = field.getAnnotation(Type.class); + switch (type.value()) { + case DATETIME: + case DATE: { + Date date = TransferUtil.transferDate(value); + method.invoke(object, date); + break; + } + case DATEMINUTE: { + Date date = TransferUtil.transferDateminute(value); + method.invoke(object, date); + break; + } + case DECIMAL: + Double d = TransferUtil.transferDouble(value); + method.invoke(object, d); + break; + + case NUMBER: + Integer integer = TransferUtil.transferInteger(value); + method.invoke(object, integer); + break; + + case BOOLEAN: + Boolean b = TransferUtil.transferBoolean(value); + method.invoke(object, b); + break; + + case LONG: + Long l = TransferUtil.transferLong(value); + method.invoke(object, l); + break; + default: + method.invoke(object, value); + break; + } + } else { + method.invoke(object, value); + } + } + break; + } + } + } + return object; + } + + /** + * 将DataTable转为T型的List

+ * 如果你试图这么做,请确保在每个字段上都加上了@Name注解
+ * 并确保该注解的值与DataTable中列的名字一致。
+ * 注解的值在这里作为唯一的标识。 + * + * @return T型列表 + * @see Column 列名称 + */ + public List transferList(Class clazz) + throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + List list = new ArrayList<>(); + + for (int i = 0; i < this.getRowIndex(); i++) { + T object = transferOneObject(clazz, i); + list.add(object); + } + return list; + } + + /** + * 获取表名 + * + * @return 表名 + */ + public String getName() { + return name; + } + + /** + * 设置表名 + * + * @param name 表名 + */ + public void setName(String name) { + this.name = name; + } + + /** + * 获取当前总行数。 + * + * @return 总行数 + */ + public int getRowIndex() { + return rowIndex; + } + + /** + * 获取当前总列数。 + * + * @return 总列数 + */ + public int getColumnIndex() { + return columnIndex; + } + + public final String toCSV() { + StringBuilder sb = new StringBuilder(); + + for (Column column : this.getColumns()) { + if (column != null) { + sb.append(column.getName()).append(","); + } + } + sb.append("\n"); + + for (int i = 0; i < this.getRowIndex(); i++) { + for (int j = 0; j < this.getColumnIndex(); j++) { + Cell cell = this.getCell(i, j); + if (this.getColumns()[j].getDataType().equals(DataType.STRING) + || this.getColumns()[j].getDataType().equals(DataType.DATE) + || this.getColumns()[j].getDataType().equals(DataType.DATETIME) + || this.getColumns()[j].getDataType().equals(DataType.DATEMINUTE)) { + sb.append("\"\t").append(cell.getValue()).append("\","); + } else { + sb.append(cell.getValue()).append(","); + } + } + sb.append("\n"); + } + + return sb.toString(); + } + + @Override + public final String toString() { + for (int i = 0; i < columnIndex; i++) { + for (int j = 0; j < rowIndex; j++) { + int length = StringUtil.getByteLength(this.getCell(j, i).getValue()); + if (columns[i].getCellWidth() < length) { + if (length > 100) { + length = 100; + } + columns[i].setCellWidth(length); + } + } + } + StringBuilder sb = new StringBuilder(""); + int sumWidth = 0; + + /* 打印表头 */ + + for (int i = 0; i < this.getColumnIndex(); i++) { + Column column = this.getColumns()[i]; + int width = column.getCellWidth() - StringUtil.getByteLength(column.getName()) + 4; + int left = width / 2; + int right = width - left; + + for (int j = 0; j < left; j++) { + sb.append(" "); + } + sb.append(column.getName()); + for (int j = 0; j < right; j++) { + sb.append(" "); + } + sumWidth += column.getCellWidth(); + } + + sb.append(CHECK_STATUS_NAME); + sb.append(" "); + sb.append(CHECK_STATUS_RESULT); + sb.append("\n"); + for (int i = 0; i < sumWidth + (4 * this.getColumnIndex()) + 18; i++) { + sb.append("="); + } + sb.append("\n"); + + /* 打印数据 */ + for (int i = 0; i < this.getRowIndex(); i++) { + for (int j = 0; j < this.getColumnIndex(); j++) { + int cellWidth = this.getColumns()[j].getCellWidth(); + Cell cell = null; + try { + cell = this.getCell(i, j); + } catch (Exception e) { + e.printStackTrace(); + } + if (null != cell) { + Object obj = cell.getValue(); + int width = cellWidth - StringUtil.getByteLength(obj.toString()) + 4; + int left = width / 2; + int right = width - left; + + for (int k = 0; k < left; k++) { + sb.append(" "); + } + sb.append(obj); + if (Status.PASS != cell.getStatus()) { + sb.append("*"); + if (right > 1) { + right--; + } + } + for (int k = 0; k < right; k++) { + sb.append(" "); + } + } else { + for (int k = 0; k < cellWidth + 4; k++) { + sb.append(" "); + } + } + } + if (errorLists.get(i).size() == 0) { + sb.append(" 通过 "); + } else { + sb.append(" 不通过 "); + for (Error error : errorLists.get(i)) { + sb.append(error.getMessage()); + } + } + sb.append("\n"); + } + return sb.toString(); + } + + /** + * 获取Table内所有的错误消息 + * + * @return 所有的错误集合 + */ + public List getErrorList() { + return errorList; + } + + /** + * 获取某一行的错误消息 + * + * @param rowNumber 要获取错误消息的行数 + * @return 该行的错误消息 + * @throws IndexOutOfBoundsException 下标越界 + */ + public String getRowError(int rowNumber) throws IndexOutOfBoundsException { + if (rowNumber > this.rowIndex) { + throw new IndexOutOfBoundsException("不存在的行数:" + rowIndex); + } + StringBuilder stringBuilder = new StringBuilder(); + if (this.errorLists.get(rowNumber).size() > 0) { + for (Error error : this.errorLists.get(rowNumber)) { + stringBuilder.append(error.getMessage()); + } + return stringBuilder.toString(); + } + return null; + } + + /** + * 添加错误信息 + * + * @param rowNumber 错误出现的行数 + * @param message 错误消息 + * @throws IndexOutOfBoundsException 下标越界 + */ + public void appendError(int rowNumber, String message) throws IndexOutOfBoundsException { + if (rowNumber > this.rowIndex) { + throw new IndexOutOfBoundsException("不存在的行数:" + rowNumber); + } + if (errorLists.get(rowNumber) == null) { + errorLists.set(rowNumber, new ArrayList()); + } + Error rowError = new Error(ErrorType.INVALID_PARAMETER, message); + Error error = new Error(ErrorType.INVALID_PARAMETER, "第" + (rowNumber + 2) + "行:" + message); + errorLists.get(rowNumber).add(rowError); + errorList.add(error); + } + + /** + * 判断DataTable是否包含错误信息 + * + * @return 是否包含错误. + */ + public final boolean hasError() { + return this.errorList.size() > 0; + } + + @Deprecated + public final String getErrorMessage() { + StringBuilder sb = new StringBuilder(); + for (Error error : this.errorList) { + sb.append(error.getMessage()); + } + return sb.toString(); + } + + public List> getErrorLists() { + return errorLists; + } + + public void setErrorLists(List> errorLists) { + this.errorLists = errorLists; + } +} diff --git a/src/main/java/com/wb/excel/api/datatable/ExcelImport.java b/src/main/java/com/wb/excel/api/datatable/ExcelImport.java new file mode 100644 index 0000000..42c10fa --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/ExcelImport.java @@ -0,0 +1,601 @@ +package com.wb.excel.api.datatable; + +import com.wb.excel.api.annotation.HeaderDescription; +import com.wb.excel.api.annotation.ExcelCollection; +import com.wb.excel.api.annotation.ExcelVerify; +import com.wb.excel.api.annotation.IsDuplicated; +import com.wb.excel.api.entity.*; +import com.wb.excel.api.style.ErrorCellStyle; +import com.wb.excel.api.util.ClassUtil; +import com.wb.excel.api.util.EnumUtil; +import com.wb.excel.api.util.StringUtils; +import com.wb.excel.api.util.VerifyDataUtil; +import org.apache.poi.POIXMLDocument; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.formula.functions.T; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import com.wb.excel.api.annotation.HeaderName; +import com.wb.excel.api.annotation.Enum; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.sql.Time; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:
+ * ***************************************************************
+ * 
+ */ +public class ExcelImport { + /** + * 异常数据styler + */ + private CellStyle errorMessageStyle; + private boolean verfiyFail = false; + private VerifyDataUtil verifyDataUtil = new VerifyDataUtil(); + private Map verifyResultMap = new HashMap<>(); + private CellStyle errorcellStyle; + + /** + * 根据数据流解析Excel + * + * @param inputstream + * @param pojoClass + * @return + */ + public ExcelImportResult importExcelByIs(InputStream inputstream, Class pojoClass, ImportParams importParams) throws Exception { + List result = new ArrayList(); + Workbook book = null; + if (!(inputstream.markSupported())) { + inputstream = new PushbackInputStream(inputstream, 8); + } + if (POIFSFileSystem.hasPOIFSHeader(inputstream)) { + book = new HSSFWorkbook(inputstream); +// isXSSFWorkbook = false; + } else if (POIXMLDocument.hasOOXMLHeader(inputstream)) { + book = new XSSFWorkbook(OPCPackage.open(inputstream)); + } +// createErrorCellStyle(book); + errorcellStyle = new ErrorCellStyle(book).getStyle(); + for (int i = 0; i < importParams.getSheetNum(); i++) { + result.addAll(importExcel(result, book.getSheetAt(i), pojoClass, importParams)); + } + return new ExcelImportResult(result, verfiyFail, book, verifyResultMap); + } + + /** + * @param result + * @param sheet + * @param pojoClass + * @param + * @return + */ + private Collection importExcel(List result, Sheet sheet, Class pojoClass, ImportParams importParams) throws Exception { + List collection = new ArrayList(); + //Excel Field 对象 + Map excelParams = new HashMap(); + //Excel Line 对象 + List excelCollection = new ArrayList(); + if (!Map.class.equals(pojoClass)) { + //获取所有的参数信息 + Field fields[] = ClassUtil.getClassFields(pojoClass); + getAllExcelField(fields, excelParams, excelCollection, pojoClass, null); + } + Iterator rows = sheet.rowIterator(); + Map titlemap = null; + Row row = null; + Object object = null; + if (rows.hasNext()) { + row = rows.next();// 排除标题信息 + titlemap = getTitleMap(row, excelParams, excelCollection); + } + while (rows.hasNext() && (row == null || sheet.getLastRowNum() - row.getRowNum() > 0)) { + row = rows.next();//获取某一行信息 + // 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象 + if (isLineRow(row, excelParams, titlemap) && object != null) { + for (ExcelCollectionEntity param : excelCollection) { + addListContinue(object, param, row, titlemap, importParams); + } + } else { + object = ClassUtil.createObject(pojoClass); + try { + for (int i = row.getFirstCellNum(), le = row.getLastCellNum(); i < le; i++) { + Cell cell = row.getCell(i) == null ? row.createCell(i) : row.getCell(i); + String titleString = (String) titlemap.get(i); + if (excelParams.containsKey(titleString) || Map.class.equals(pojoClass)) { + saveFieldValue(object, cell, excelParams, titleString, row, importParams); + } + } + for (ExcelCollectionEntity param : excelCollection) { + addListContinue(object, param, row, titlemap, importParams); + } + collection.add(object); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return collection; + } + + + /** + * 获取列数据,根据列属性 + * + * @param cell + * @return + */ + private Object getCellValue(Cell cell) { + Object result = null; + if (cell != null) { + if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) { + result = cell.getNumericCellValue(); + } else if (Cell.CELL_TYPE_BOOLEAN == cell.getCellType()) { + result = cell.getBooleanCellValue(); + } else { + result = cell.getStringCellValue(); + } + } + result = result == null ? "" : result; + return result; + } + + /** + * 保存数据 + * + * @param object + * @param cell + * @param excelParams + * @param titleString + * @param row + */ + private void saveFieldValue(Object object, Cell cell, Map excelParams, String titleString, Row row, ImportParams importParams) throws Exception { + ExcelImportEntity entity = excelParams.get(titleString); + String xclass = "class java.lang.Object"; + if (!(object instanceof Map)) { + + Method setMethod = entity.getMethods() != null && entity.getMethods().size() > 0 ? entity + .getMethods().get(entity.getMethods().size() - 1) : entity.getMethod(); + java.lang.reflect.Type[] ts = setMethod.getGenericParameterTypes(); + xclass = ts[0].toString(); + } + Object result = getCellValue(xclass, cell, entity); + +// if (entity != null) { + // 做值处理 +// result = replaceValue(entity., result); +// } + if (entity != null && entity.getEnum() != null) { + boolean ischeck = EnumUtil.check(entity.getEnum(), String.valueOf(result)); + if (!ischeck) { + DataVerifyResult verifyResult = new DataVerifyResult(); + verifyResult.setSuccess(false); + verifyResult.setMsg("参数[" + entity.getShowname() + "," + result + "]未匹配相应的值信息"); + verifyResultMap.put(row.getRowNum(), verifyResult); + } else { + result = EnumUtil.getKey(entity.getEnum(), String.valueOf(result)); + setValues(entity, object, result); + } + } + if (result instanceof Map) { + ((Map) object).put(titleString, result); + } else { + //可以做值校验 + DataVerifyResult verifyResult = verifyDataUtil.verifyData(object, result, entity.getFiledName(), entity.getShowname(), entity.getVerify(), importParams.getVerifyHanlder()); + //设置校验结果(第一列) + if (verifyResult.isSuccess()) { + setValues(entity, object, result); + } else { + Integer rowNum = Integer.valueOf(row.getRowNum()); + if (verifyResultMap.containsKey(rowNum)) { + // 如果有错误信息,则添加错误数据 + DataVerifyResult tempresult = verifyResultMap.get(rowNum); + tempresult.setMsg(tempresult.getMsg() + " " + verifyResult.getMsg()); + verifyResultMap.put(rowNum, tempresult); + } else { + verifyResultMap.put(rowNum, verifyResult); + } + verfiyFail = true; + } + } + } + + public void setValues(ExcelImportEntity entity, Object object, Object value) throws Exception { + if (entity.getMethods() != null) { + setFieldBySomeMethod(entity.getMethods(), object, value); + } else { + /* + if (String.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, value); + } else if (Long.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Long.valueOf(value.toString())); + } else if (int.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Integer.valueOf(value.toString())); + } else if (boolean.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Boolean.valueOf(value.toString())); + } else if (Boolean.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Boolean.valueOf(value.toString())); + } else if (Double.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Double.valueOf(value.toString())); + } else if (Integer.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Integer.valueOf(value.toString())); + } else if (Long.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Long.valueOf(value.toString())); + } else if (Float.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Float.valueOf(value.toString())); + } else if (Short.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, Short.valueOf(value.toString())); + } else if (Number.class.isAssignableFrom(entity.getMethod().getParameterTypes()[0])) { + entity.getMethod().invoke(object, (Number) value); + } else { + + }*/ + entity.getMethod().invoke(object, value); + } + } + + public void setFieldBySomeMethod(List setMethods, Object object, Object value) + throws Exception { + Object t = getFieldBySomeMethod(setMethods, object); + setMethods.get(setMethods.size() - 1).invoke(t, value); + } + + public Object getFieldBySomeMethod(List list, Object t) throws Exception { + Method m; + for (int i = 0; i < list.size() - 1; i++) { + m = list.get(i); + t = m.invoke(t, new Object[]{}); + } + return t; + } + + /** + * 获取单元格内的值 + * + * @param xclass + * @param cell + * @param entity + * @return + */ + private Object getCellValue(String xclass, Cell cell, ExcelImportEntity entity) { + if (cell == null) { + return ""; + } + Object result = null; + // 日期格式比较特殊,和cell格式不一致 + if ("class java.util.Date".equals(xclass) || ("class java.sql.Time").equals(xclass)) { + if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) { + // 日期格式 + result = cell.getDateCellValue(); + } else { + cell.setCellType(Cell.CELL_TYPE_STRING); + result = getDateData(entity, cell.getStringCellValue()); + } + if (("class java.sql.Time").equals(xclass)) { + result = new Time(((Date) result).getTime()); + } + } else if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) { + result = cell.getNumericCellValue(); + } else if (Cell.CELL_TYPE_BOOLEAN == cell.getCellType()) { + result = cell.getBooleanCellValue(); + } else { + result = cell.getStringCellValue(); + } + if ("class java.lang.String".equals(xclass)) { + result = String.valueOf(result); + } + return result; + } + + /** + * 获取日期类型数据 + * + * @param entity + * @param value + * @return + * @Author JueYue + * @date 2013年11月26日 + */ + private Date getDateData(ExcelImportEntity entity, String value) { + if (StringUtils.isNotEmpty(entity.getDateFormat()) && StringUtils.isNotEmpty(value)) { + SimpleDateFormat format = new SimpleDateFormat(entity.getDateFormat()); + try { + return format.parse(value); + } catch (ParseException e) { +// LOGGER.error("时间格式化失败,格式化:" + entity.getDateFormat() + ",值:" + value); + e.printStackTrace(); + } + } + return null; + } + + /** + * 向List 里面添加元素 + * + * @param object + * @param param + * @param row + * @param titlemap + */ + private void addListContinue(Object object, ExcelCollectionEntity param, Row row, Map titlemap, ImportParams importParams) throws Exception { + Collection collection = (Collection) ClassUtil.getMethod(param.getName(), + object.getClass()).invoke(object, new Object[]{}); + Object entity = ClassUtil.createObject(param.getType()); + boolean isUsed = false;// 是否需要加上这个对象 + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) { + Cell cell = row.getCell(i); + String titleString = (String) titlemap.get(i); + if (param.getExcelParams().containsKey(titleString)) { + saveFieldValue(entity, cell, param.getExcelParams(), titleString, row, importParams); + isUsed = true; + } + } + if (isUsed) { + collection.add(entity); + } + + } + + /** + * 查看某些列的数据,是否存在 + * + * @param row + * @param excelParams + * @return + */ + private Boolean isLineRow(Row row, Map excelParams, Map titlemap) { + Boolean isLineRow = true; + for (Integer index : titlemap.keySet()) { + String titleName = titlemap.get(index); + if (excelParams.containsKey(titleName)) { + Cell cell = row.getCell(index); + Object value = getCellValue("", cell, excelParams.get(titleName)); + if (!StringUtils.isEmpty(String.valueOf(value))) { + isLineRow = false; + break; + } + } + } + return isLineRow; + } + + /** + * 获取Title 与Index 关系 + * + * @param row + * @param excelParams + * @param excelCollection + * @return + */ + private Map getTitleMap(Row row, Map excelParams, List excelCollection) throws Exception { + Map titlemap = new HashMap(); + Iterator cellTitle = row.cellIterator(); + while (cellTitle.hasNext()) { + Cell cell = cellTitle.next(); + String value = getKeyValue(cell).replace("*", "").replace("\n", ""); + int i = cell.getColumnIndex(); + //支持重名导入 + if (StringUtils.isNotEmpty(value)) { + //判断当前列索引,是否为明细值 + if (!excelParams.containsKey(value)) { + if (excelCollection != null && !excelCollection.isEmpty()) { + for (ExcelCollectionEntity entity : excelCollection) { + if (entity.getExcelParams().containsKey(entity.getExcelName() + "_" + value)) { + ExcelImportEntity excelImportEntity = entity.getExcelParams().get(entity.getExcelName() + "_" + value); + excelImportEntity.setFiledName(entity.getName() + "_" + excelImportEntity.getFiledName()); + titlemap.put(i, entity.getExcelName() + "_" + value); + break; + } + } + } + } else { + titlemap.put(i, value); + } + } + } + //判断是否所有的列都满足,不满足抛Exception + //1判断主要信息 + Set params = excelParams.keySet(); + StringBuffer sb = new StringBuffer(); + for (String key : params) { + if (!titlemap.containsValue(key)) { + sb.append(key).append(" "); + } + } + for (ExcelCollectionEntity entity : excelCollection) { + Set eparams = entity.getExcelParams().keySet(); + for (String key : eparams) { + if (!titlemap.containsValue(key)) { + sb.append(key).append(" "); + } + } + } + if (sb.length() > 0) { + throw new Exception("不匹配的Excel文件,缺少如下标题:" + sb.toString()); + } + return titlemap; + } + + /** + * 获取key的值,针对不同类型获取不同的值 + * + * @param cell + * @return + * @Author JueYue + * @date 2013-11-21 + */ + private String getKeyValue(Cell cell) { + Object obj = null; + switch (cell.getCellType()) { + case Cell.CELL_TYPE_STRING: + obj = cell.getStringCellValue(); + break; + case Cell.CELL_TYPE_BOOLEAN: + obj = cell.getBooleanCellValue(); + break; + case Cell.CELL_TYPE_NUMERIC: + obj = cell.getNumericCellValue(); + break; + } + return obj == null ? null : obj.toString().trim(); + } + + /** + * 解析获取Excel 信息 + * + * @param fields + * @param excelParams + * @param excelCollection + * @param pojoClass + * @param getMethods + */ + private void getAllExcelField(Field[] fields, Map excelParams, List excelCollection, Class pojoClass, List getMethods) throws Exception { + ExcelImportEntity excelEntity = null; + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + // 判断是否有注解,没有注解,不需要解析 + HeaderName headerName = field.getAnnotation(HeaderName.class); + ExcelCollection collectionannotation = field.getAnnotation(ExcelCollection.class); + if (headerName != null || collectionannotation != null) { + //如果是List 类型 + if (ClassUtil.isCollection(field.getType())) { + // 集合对象设置属性 + ExcelCollectionEntity collection = new ExcelCollectionEntity(); + collection.setName(field.getName()); + Map temp = new HashMap(); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class clz = (Class) pt.getActualTypeArguments()[0]; + collection.setType(clz); + getExcelFieldList(ClassUtil.getClassFields(clz), clz, temp, null); + collection.setExcelParams(temp); + collection.setExcelName(field.getAnnotation(ExcelCollection.class).value()); + additionalCollectionName(collection); + excelCollection.add(collection); + } else if (ClassUtil.isJavaClass(field)) { + addEntityToMap(field, excelEntity, pojoClass, getMethods, excelParams); + } else { + List newMethods = new ArrayList(); + if (getMethods != null) { + newMethods.addAll(getMethods); + } + newMethods.add(ClassUtil.getMethod(field.getName(), pojoClass)); + getAllExcelField(ClassUtil.getClassFields(field.getType()), + excelParams, excelCollection, field.getType(), newMethods); + } + } + } + + + } + + private void addEntityToMap(Field field, ExcelImportEntity excelEntity, Class pojoClass, List getMethods, Map temp) throws Exception { + HeaderName excel = field.getAnnotation(HeaderName.class); + if (excel != null) { + excelEntity = new ExcelImportEntity(); + excelEntity.setShowname(excel.value()); + excelEntity.setFiledName(field.getName()); + Enum targetEnum = field.getAnnotation(Enum.class); + if (targetEnum != null) { + excelEntity.setEnum(targetEnum.target()); + } + excelEntity.setVerify(getImportVerify(field)); + HeaderDescription headerDescription = field.getAnnotation(HeaderDescription.class); + excelEntity.setDescription(headerDescription == null ? "" : headerDescription.value()); + IsDuplicated isDuplicated = field.getAnnotation(IsDuplicated.class); + if (isDuplicated != null) { + excelEntity.setIsDuplicated(isDuplicated.value()); + } + getExcelField(field, excelEntity, excel, pojoClass); + if (getMethods != null) { + List newMethods = new ArrayList(); + newMethods.addAll(getMethods); + newMethods.add(excelEntity.getMethod()); + excelEntity.setMethods(newMethods); + } + temp.put(excelEntity.getShowname(), excelEntity); + } + } + + /** + * 获取导入校验参数 + * + * @param field + * @return + */ + public ExcelVerifyEntity getImportVerify(Field field) { + ExcelVerify verify = field.getAnnotation(ExcelVerify.class); + if (verify != null) { + ExcelVerifyEntity entity = new ExcelVerifyEntity(); + entity.setEmail(verify.isEmail()); + entity.setInterHandler(verify.interHandler()); + entity.setMaxLength(verify.maxLength()); + entity.setMinLength(verify.minLength()); + entity.setMobile(verify.isMobile()); + entity.setNotNull(verify.notNull()); + entity.setRegex(verify.regex()); + entity.setRegexTip(verify.regexTip()); + entity.setTel(verify.isTel()); + return entity; + } + return null; + } + + /** + * 获取Excel 列信息 + * + * @param field + * @param excelEntity + * @param excel + * @param pojoClass + */ + private void getExcelField(Field field, ExcelImportEntity excelEntity, HeaderName excel, Class pojoClass) throws Exception { + String fieldname = field.getName(); + excelEntity.setMethod(ClassUtil.getMethod(fieldname, pojoClass, field.getType())); + if (StringUtils.isNotEmpty(excel.dateFormat())) { + excelEntity.setDateFormat(excel.dateFormat()); + } + } + + private void additionalCollectionName(ExcelCollectionEntity collection) { + Set keys = new HashSet(); + keys.addAll(collection.getExcelParams().keySet()); + for (String key : keys) { + collection.getExcelParams().put(collection.getExcelName() + "_" + key, + collection.getExcelParams().get(key)); + collection.getExcelParams().remove(key); + } + } + + private void getExcelFieldList(Field[] fields, Class pojoClass, Map temp, List getMethods) throws Exception { + ExcelImportEntity excelEntity = null; + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (ClassUtil.isJavaClass(field)) { + addEntityToMap(field, excelEntity, pojoClass, getMethods, temp); + } else { + List newMethods = new ArrayList(); + if (getMethods != null) { + newMethods.addAll(getMethods); + } + newMethods.add(ClassUtil.getMethod(field.getName(), pojoClass, field.getType())); + getExcelFieldList(ClassUtil.getClassFields(field.getType()), + field.getType(), temp, newMethods); + } + } + } + + +} diff --git a/src/main/java/com/wb/excel/api/datatable/ImportParams.java b/src/main/java/com/wb/excel/api/datatable/ImportParams.java new file mode 100644 index 0000000..244583a --- /dev/null +++ b/src/main/java/com/wb/excel/api/datatable/ImportParams.java @@ -0,0 +1,62 @@ +package com.wb.excel.api.datatable; + +import com.wb.excel.api.interfaces.IExcelVerifyHandler; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:导入参数设置
+ * ***************************************************************
+ * 
+ */ +public class ImportParams { +// /** +// * 表格标题行数,默认0 +// */ +// private int titleRows = 0; +// /** +// * 表头行数,默认1 +// */ +// private int headRows = 1; +// /** +// * 字段真正值和列标题之间的距离 默认0 +// */ +// private int startRows = 0; +// /** +// * 主键设置,如何这个cell没有值,就跳过 或者认为这个是list的下面的值 +// */ +// private int keyIndex = 0; + /** + * 上传表格需要读取的sheet 数量,默认为1 + */ + private int sheetNum = 1; + + /** + * 校验处理接口 + */ + private IExcelVerifyHandler verifyHanlder; +// /** +// * 最后的无效行数 +// */ +// private int lastOfInvalidRow = 0; + + + public int getSheetNum() { + return sheetNum; + } + + public void setSheetNum(int sheetNum) { + this.sheetNum = sheetNum; + } + + public IExcelVerifyHandler getVerifyHanlder() { + return verifyHanlder; + } + + public void setVerifyHanlder(IExcelVerifyHandler verifyHanlder) { + this.verifyHanlder = verifyHanlder; + } + +} diff --git a/src/main/java/com/wb/excel/api/entity/DataVerifyResult.java b/src/main/java/com/wb/excel/api/entity/DataVerifyResult.java new file mode 100644 index 0000000..9fb9ed9 --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/DataVerifyResult.java @@ -0,0 +1,51 @@ +package com.wb.excel.api.entity; + +import java.io.Serializable; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:数据校验结果
+ * ***************************************************************
+ * 
+ */ +public class DataVerifyResult implements Serializable { + /** + * 是否正确 + */ + private boolean success; + /** + * 错误信息 + */ + private String msg; + + public DataVerifyResult() { + } + + public DataVerifyResult(boolean issuccess) { + this.success = issuccess; + } + + public DataVerifyResult(boolean success, String msg) { + this.success = success; + this.msg = msg; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/src/main/java/com/wb/excel/api/entity/ExcelCollectionEntity.java b/src/main/java/com/wb/excel/api/entity/ExcelCollectionEntity.java new file mode 100644 index 0000000..f3b676a --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/ExcelCollectionEntity.java @@ -0,0 +1,61 @@ +package com.wb.excel.api.entity; + +import java.util.Map; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:Excel 集合对象
+ * ***************************************************************
+ * 
+ */ +public class ExcelCollectionEntity { + /** + * 集合对应的名称 + */ + private String name; + /** + * Excel 列名称 + */ + private String excelName; + /** + * 实体对象 + */ + private Class type; + + private Map excelParams; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getExcelName() { + return excelName; + } + + public void setExcelName(String excelName) { + this.excelName = excelName; + } + + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } + + public Map getExcelParams() { + return excelParams; + } + + public void setExcelParams(Map excelParams) { + this.excelParams = excelParams; + } +} diff --git a/src/main/java/com/wb/excel/api/entity/ExcelEntity.java b/src/main/java/com/wb/excel/api/entity/ExcelEntity.java new file mode 100644 index 0000000..64370ba --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/ExcelEntity.java @@ -0,0 +1,124 @@ +package com.wb.excel.api.entity; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:
+ * ***************************************************************
+ * 
+ */ +public class ExcelEntity { + /** + * 参数名称 + */ + protected String filedName; + /** + * 对应name + */ + protected String showname; + /** + * 对应的枚举类型 + */ + protected Class Enum; + /** + * 对应的数据格式化 + */ + protected String split; + + /** + * 注释 + */ + protected String description; + /** + * 是否重复 + */ + protected Boolean isDuplicated; + /** + * 日期格式化 + */ + protected String dateFormat = "yyyy-MM-dd"; + + /** + * set/get方法 + */ + private Method method; + private List methods; + + public String getFiledName() { + return filedName; + } + + public void setFiledName(String filedName) { + this.filedName = filedName; + } + + public String getShowname() { + return showname; + } + + public void setShowname(String showname) { + this.showname = showname; + } + + public Class getEnum() { + return Enum; + } + + public void setEnum(Class anEnum) { + Enum = anEnum; + } + + public String getSplit() { + return split; + } + + public void setSplit(String split) { + this.split = split; + } + + + public Method getMethod() { + return method; + } + + public void setMethod(Method method) { + this.method = method; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getIsDuplicated() { + return isDuplicated; + } + + public void setIsDuplicated(Boolean isDuplicated) { + this.isDuplicated = isDuplicated; + } + + public List getMethods() { + return methods; + } + + public void setMethods(List methods) { + this.methods = methods; + } + + public String getDateFormat() { + return dateFormat; + } + + public void setDateFormat(String dateFormat) { + this.dateFormat = dateFormat; + } +} diff --git a/src/main/java/com/wb/excel/api/entity/ExcelImportEntity.java b/src/main/java/com/wb/excel/api/entity/ExcelImportEntity.java new file mode 100644 index 0000000..996eca0 --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/ExcelImportEntity.java @@ -0,0 +1,37 @@ +package com.wb.excel.api.entity; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:导入的实体信息
+ * ***************************************************************
+ * 
+ */ +public class ExcelImportEntity extends ExcelEntity { + /** + * 校驗參數 + */ + private ExcelVerifyEntity verify; + + /** + * 校验参数名称 + */ +// private String verifyFieldName ; + public ExcelVerifyEntity getVerify() { + return verify; + } + + public void setVerify(ExcelVerifyEntity verify) { + this.verify = verify; + } + +// public String getVerifyFieldName() { +// return verifyFieldName; +// } +// +// public void setVerifyFieldName(String verifyFieldName) { +// this.verifyFieldName = verifyFieldName; +// } +} diff --git a/src/main/java/com/wb/excel/api/entity/ExcelImportResult.java b/src/main/java/com/wb/excel/api/entity/ExcelImportResult.java new file mode 100644 index 0000000..d130099 --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/ExcelImportResult.java @@ -0,0 +1,183 @@ +package com.wb.excel.api.entity; + +import com.wb.excel.api.style.ErrorCellStyle; +import org.apache.poi.ss.usermodel.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:导入返回结果
+ * ***************************************************************
+ * 
+ */ +public class ExcelImportResult { + /** + * 结果集 + */ + private List list; + /** + * 是否存在校验失败 + */ + private boolean verfiyFail; + + private Map verifyResult; + + /** + * 数据源 + */ + private Workbook workbook; + private CellStyle errorMessageStyle; + private ErrorCellStyle errorCellStyle; + + public ExcelImportResult(List list, boolean verfiyFail, Workbook workbook, Map verifyResult) { + this.list = list; + this.verfiyFail = verfiyFail; + this.workbook = workbook; + this.verifyResult = verifyResult; + this.createErrorCellStyle(workbook); + errorCellStyle = new ErrorCellStyle(workbook); + } + + public List getList() { + return list; + } + + public Workbook getWorkbook() { + //循环添加错误信息 + Sheet sheet = workbook.getSheetAt(0); + Iterator rows = sheet.rowIterator(); + //行信息,添加校验结果 + Row titleRow = rows.next(); + addValidateTitleInfo(titleRow); + //循环,给行添加错误信息 + Row row = null; + while (rows.hasNext() && (row == null || sheet.getLastRowNum() - row.getRowNum() > 0)) { + row = rows.next(); + addValidateInfo(row, verifyResult.get(row.getRowNum())); + } + return workbook; + } + + public byte[] getBytes() throws IOException { + Workbook tempworkbook = this.getWorkbook(); + if (tempworkbook != null) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + tempworkbook.write(outputStream); + return outputStream.toByteArray(); + } + return null; + } + + /** + * 添加校验信息 + * + * @param row + */ + private void addValidateTitleInfo(Row row) { + Map temptitle = new HashMap(); + for (int i = row.getFirstCellNum(), le = row.getLastCellNum(); i < le; i++) { + temptitle.put(i, row.getCell(i).getStringCellValue()); + } + for (int i = row.getFirstCellNum(), le = row.getLastCellNum(); i < le; i++) { + row.createCell(i + 1).setCellValue(temptitle.get(i)); + } + row.createCell(0).setCellValue("检查状态"); + row.createCell(row.getLastCellNum()).setCellValue("错误信息"); + } + + /** + * 添加错误行信息 + * + * @param row + * @param dataVerifyResult + */ + private void addValidateInfo(Row row, DataVerifyResult dataVerifyResult) { + Map temptitle = new HashMap(); + for (int i = row.getFirstCellNum(), le = row.getLastCellNum(); i < le; i++) { + temptitle.put(i, String.valueOf(getCellValue(row.getCell(i)))); + } + for (int i = row.getFirstCellNum(), le = row.getLastCellNum(); i < le; i++) { + row.createCell(i + 1).setCellValue(temptitle.get(i)); + } + Boolean result = (dataVerifyResult == null || dataVerifyResult.isSuccess()) ? true : false; + Cell statusCell = row.createCell(0); + if (!result) { + statusCell.setCellStyle(errorCellStyle.getStyle()); + } + statusCell.setCellValue(result ? "通过" : "不通过"); + Cell errorcell = row.createCell(row.getLastCellNum()); + errorcell.setCellStyle(errorMessageStyle); + errorcell.setCellValue(dataVerifyResult == null ? "" : dataVerifyResult.getMsg()); + } + + /** + * 获取列数据,根据列属性 + * + * @param cell + * @return + */ + private Object getCellValue(Cell cell) { + Object result = null; + if (cell != null) { + if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) { + result = cell.getNumericCellValue(); + } else if (Cell.CELL_TYPE_BOOLEAN == cell.getCellType()) { + result = cell.getBooleanCellValue(); + } else { + result = cell.getStringCellValue(); + } + } + result = result == null ? "" : result; + return result; + } + + public boolean isVerfiyFail() { + return verfiyFail; + } + + public void setList(List list) { + this.list = list; + } + + public void setVerfiyFail(boolean verfiyFail) { + this.verfiyFail = verfiyFail; + } + + public void setWorkbook(Workbook workbook) { + this.workbook = workbook; + } + + public void setVerifyResult(Map verifyResult) { + Iterator keys = verifyResult.keySet().iterator(); + while (keys.hasNext()) { + Integer key = keys.next(); + if (this.verifyResult == null) { + this.verifyResult = new HashMap<>(); + } + if (this.verifyResult.containsKey(key)) { + DataVerifyResult result = this.verifyResult.get(key); + result.setMsg(result.getMsg() + " " + verifyResult.get(key).getMsg()); + result.setSuccess(verifyResult.get(key).isSuccess()); + this.verifyResult.put(key, result); + } else { + this.verifyResult.put(key, verifyResult.get(key)); + } + } + } + + private void createErrorCellStyle(Workbook workbook) { + errorMessageStyle = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setColor(Font.COLOR_RED); + errorMessageStyle.setFont(font); + } +} diff --git a/src/main/java/com/wb/excel/api/entity/ExcelVerifyEntity.java b/src/main/java/com/wb/excel/api/entity/ExcelVerifyEntity.java new file mode 100644 index 0000000..a3dd496 --- /dev/null +++ b/src/main/java/com/wb/excel/api/entity/ExcelVerifyEntity.java @@ -0,0 +1,141 @@ +package com.wb.excel.api.entity; + +/** + * Excel 校验对象 + */ +public class ExcelVerifyEntity { + + /** + * 接口校验 + * + * @return + */ + private boolean interHandler; + + /** + * 不允许空 + * + * @return + */ + private boolean notNull; + + /** + * 是13位移动电话 + * + * @return + */ + private boolean isMobile; + /** + * 是座机号码 + * + * @return + */ + private boolean isTel; + + /** + * 是电子邮件 + * + * @return + */ + private boolean isEmail; + + /** + * 最小长度 + * + * @return + */ + private int minLength; + + /** + * 最大长度 + * + * @return + */ + private int maxLength; + + /** + * 正在表达式 + * + * @return + */ + private String regex; + /** + * 正在表达式,错误提示信息 + * + * @return + */ + private String regexTip; + + public int getMaxLength() { + return maxLength; + } + + public int getMinLength() { + return minLength; + } + + public String getRegex() { + return regex; + } + + public String getRegexTip() { + return regexTip; + } + + public boolean isEmail() { + return isEmail; + } + + public boolean isInterHandler() { + return interHandler; + } + + public boolean isMobile() { + return isMobile; + } + + public boolean isNotNull() { + return notNull; + } + + public boolean isTel() { + return isTel; + } + + public void setEmail(boolean isEmail) { + this.isEmail = isEmail; + } + + public void setInterHandler(boolean interHandler) { + this.interHandler = interHandler; + } + + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } + + public void setMinLength(int minLength) { + this.minLength = minLength; + } + + public void setMobile(boolean isMobile) { + this.isMobile = isMobile; + } + + public void setNotNull(boolean notNull) { + this.notNull = notNull; + } + + public void setRegex(String regex) { + this.regex = regex; + } + + public void setRegexTip(String regexTip) { + this.regexTip = regexTip; + } + + public void setTel(boolean isTel) { + this.isTel = isTel; + } + +} diff --git a/src/main/java/com/wb/excel/api/enumeration/DataType.java b/src/main/java/com/wb/excel/api/enumeration/DataType.java new file mode 100644 index 0000000..f7b51e6 --- /dev/null +++ b/src/main/java/com/wb/excel/api/enumeration/DataType.java @@ -0,0 +1,119 @@ +package com.wb.excel.api.enumeration; + +import com.wb.excel.api.annotation.HeaderDescription; +import com.wb.excel.api.annotation.HeaderName; +import com.wb.excel.api.datatable.Cell; +import com.wb.excel.api.util.EnumUtil; +import com.wb.excel.api.util.StringUtil; +import com.wb.excel.api.util.ValidationUtil; + +/** + * 数据类型枚举类。包含了目前DataTable支持验证的11种类型。
+ * DataTable会对指定的类型进行格式上的验证。 + * Created on 2014/9/19/. + * + * @author + * @version v1.0.0.0 + */ +public enum DataType { + @HeaderName("字符型") + @HeaderDescription("普通的字符串类型,例如:abc123.,!@#") + STRING, + @HeaderName("整数型") + @HeaderDescription("整数类型,小数点后的数字会被抹去(不是四舍五入),例如:11,200,4000") + NUMBER, + @HeaderName("数字类型") + @HeaderDescription("可以带小数点的数字类型,例如:1.00,1.01") + DECIMAL, + @HeaderName("网络地址型") + @HeaderDescription("网址,文件地址等。") + URL, + @HeaderName("邮箱型") + @HeaderDescription("邮箱地址,例如:test@xxx.com , test@xxx.com.cn") + EMAIL, + @HeaderName("手机号码型") + @HeaderDescription("手机号码。仅限用于大陆手机号中。如:13300010002") + PHONE, + @HeaderName("日期型") + @HeaderDescription("普通的日期类型,例如:2014-10-01") + DATE, + @HeaderName("时间日期型(秒)") + @HeaderDescription("时间精确到秒的日期类型,例如:2014-10-01 10:30:00") + DATETIME, + @HeaderName("时间日期型(分钟)") + @HeaderDescription("时间精确到分钟的日期类型,例如:2014-10-01 10:30") + DATEMINUTE, + @HeaderName("是否型") + @HeaderDescription("指定是或者否的类型,例如:是,否") + BOOLEAN, + @HeaderName("大数型") + @HeaderDescription("用于较大的数字类型,会忽略小数点以后的内容") + LONG; + + /** + * 匹配格式. + * + * @param type 要判断的类型 + * @param cell 需要判断类型的单元格(可能会有改变值的情况发生,所以需要传入此值) + * @param value 已被简单处理过的需要判断的值 + * @return 匹配结果。true,符合;false,不符合 + */ + public static boolean check(DataType type, Cell cell, String value) { + boolean typeFlag = true; + if (value.length() > 0) { + switch (type) { + case EMAIL: + typeFlag = ValidationUtil.checkEmail(value); + break; + case PHONE: + typeFlag = ValidationUtil.checkPhone(value); + break; + case URL: + typeFlag = ValidationUtil.checkUrl(value); + break; + case DECIMAL: + typeFlag = ValidationUtil.checkDouble(value); + break; + case NUMBER: + typeFlag = ValidationUtil.checkInteger(value); + if (typeFlag) { + cell.setValue(StringUtil.transferInteger(value)); + } + break; + case DATE: + typeFlag = ValidationUtil.checkDate(value); + if (typeFlag) { + cell.setValue(StringUtil.transferDate(value)); + } + break; + case DATETIME: + typeFlag = ValidationUtil.checkDatetime(value); + if (typeFlag) { + cell.setValue(StringUtil.transferDatetime(value)); + } + break; + case DATEMINUTE: + typeFlag = ValidationUtil.checkDatetime(value); + if (typeFlag) { + cell.setValue(StringUtil.transferDateminute(value)); + } + break; + case BOOLEAN: + typeFlag = EnumUtil.check(YesNo.class, value); + if (typeFlag) { + cell.setValue(StringUtil.transferBoolean(value)); + } + break; + case LONG: + typeFlag = ValidationUtil.checkLong(value); + if (typeFlag) { + cell.setValue(StringUtil.transferLong(value)); + } + break; + default: + break; + } + } + return typeFlag; + } +} diff --git a/src/main/java/com/wb/excel/api/enumeration/Gender.java b/src/main/java/com/wb/excel/api/enumeration/Gender.java new file mode 100644 index 0000000..c70cab3 --- /dev/null +++ b/src/main/java/com/wb/excel/api/enumeration/Gender.java @@ -0,0 +1,18 @@ +package com.wb.excel.api.enumeration; + +import com.wb.excel.api.annotation.EnumValue; + +/** + * Created on 2014/9/26. + * + * @author + * @version 0.1.0 + */ +public enum Gender { + @EnumValue({"男", "male", "m"}) + M, + @EnumValue({"女", "female", "f"}) + F, + @EnumValue({"未知", "其它", "其他", "u"}) + U +} diff --git a/src/main/java/com/wb/excel/api/enumeration/Status.java b/src/main/java/com/wb/excel/api/enumeration/Status.java new file mode 100644 index 0000000..9623c52 --- /dev/null +++ b/src/main/java/com/wb/excel/api/enumeration/Status.java @@ -0,0 +1,50 @@ +package com.wb.excel.api.enumeration; + +/** + * Created on 2014/9/23. + * + * @author + * @version v1.0.0.0 + */ +public enum Status { + /** + * 数据库中已存在 + */ + EXIST, + /** + * 数据库中不存在 + */ + NOTEXIST, + /** + * 不符合的枚举值 + */ + ERROR_VALUE, + /** + * 验证通过 + */ + PASS, + /** + * 不允许重复的列发生了重复 + */ + REPEAT, + /** + * 格式不正确 + */ + FORMAT, + /** + * 长度不符合要求 + */ + LENGTH, + /** + * 不允许为空的列出现了空 + */ + EMPTY, + /** + * 数字类型的值过小 + */ + TOO_SMALL, + /** + * 数字类型的值过大 + */ + TOO_BIG +} diff --git a/src/main/java/com/wb/excel/api/enumeration/YesNo.java b/src/main/java/com/wb/excel/api/enumeration/YesNo.java new file mode 100644 index 0000000..97ef556 --- /dev/null +++ b/src/main/java/com/wb/excel/api/enumeration/YesNo.java @@ -0,0 +1,18 @@ +package com.wb.excel.api.enumeration; + +import com.wb.excel.api.annotation.EnumValue; + +/** + * 用于判断Boolean型的值。仅供DataTable判断Boolean类型时使用。

+ * 不建议使用。

+ * Created on 2014/9/27. + * + * @author + * @version 0.1.0 + */ +public enum YesNo { + @EnumValue({"是", "yes", "y", "true"}) + Y, + @EnumValue({"否", "no", "n", "false"}) + N +} diff --git a/src/main/java/com/wb/excel/api/exception/ColumnNameNotExistException.java b/src/main/java/com/wb/excel/api/exception/ColumnNameNotExistException.java new file mode 100644 index 0000000..01c004f --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/ColumnNameNotExistException.java @@ -0,0 +1,32 @@ +package com.wb.excel.api.exception; + +/** + * Created on 2014/10/12. + * + * @author + * @version 0.1.0 + */ +public class ColumnNameNotExistException extends RuntimeException { + private static final long serialVersionUID = 234122996006212387L; + + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public ColumnNameNotExistException() { + super(); + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public ColumnNameNotExistException(String message) { + super(message); + } +} diff --git a/src/main/java/com/wb/excel/api/exception/Error.java b/src/main/java/com/wb/excel/api/exception/Error.java new file mode 100644 index 0000000..ee1dd24 --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/Error.java @@ -0,0 +1,52 @@ +package com.wb.excel.api.exception; + +import java.io.Serializable; + +public class Error implements Serializable { + + private static final long serialVersionUID = 3L; + + private String code; + + private ErrorType type; + + private String message; + + public Error() { + } + + public Error(String code, String message) { + this.code = code; + this.message = message; + } + + public Error(ErrorType type, String message) { + this.type = type; + this.code = type.toString(); + this.message = message; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public ErrorType getType() { + return type; + } + + public void setType(ErrorType type) { + this.type = type; + } +} diff --git a/src/main/java/com/wb/excel/api/exception/ErrorType.java b/src/main/java/com/wb/excel/api/exception/ErrorType.java new file mode 100644 index 0000000..ca0cad6 --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/ErrorType.java @@ -0,0 +1,38 @@ +package com.wb.excel.api.exception; + +/** + * Created on 2014/10/15. + * + * @author + * @version 0.1.0 + */ +public class ErrorType { + /** + * 唯一性错误,出现了不允许重复的内容 + */ + public static String UNIQUENESS_ERROR = "UNIQUENESS_ERROR"; + /** + * 期待值为空 找不到想要的对象 + */ + public static String EXPECTATION_NULL = "EXPECTATION_NULL"; + /** + * 业务错误 不符合业务逻辑的情况发生 + */ + public static String BUSINESS_ERROR = "BUSINESS_ERROR"; + /** + * 系统错误 JDBC的错误等 + */ + public static String SYSTEM_ERROR = "SYSTEM_ERROR"; + /** + * 非法的参数 无效,格式不对、非法值、越界等 + */ + public static String INVALID_PARAMETER = "INVALID_PARAMETER"; + /** + * 其它未归类错误 + */ + public static String OTHER = "OTHER"; + /** + * 异常信息Dump + */ + public static String STACK_DUMP = "STACK_DUMP"; +} diff --git a/src/main/java/com/wb/excel/api/exception/ExistedColumnNameException.java b/src/main/java/com/wb/excel/api/exception/ExistedColumnNameException.java new file mode 100644 index 0000000..1c62a8c --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/ExistedColumnNameException.java @@ -0,0 +1,32 @@ +package com.wb.excel.api.exception; + +/** + * Created on 2014/10/12. + * + * @author + * @version 0.1.0 + */ +public class ExistedColumnNameException extends RuntimeException { + private static final long serialVersionUID = 234122996006212387L; + + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public ExistedColumnNameException() { + super(); + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public ExistedColumnNameException(String message) { + super(message); + } +} diff --git a/src/main/java/com/wb/excel/api/exception/IllegalParameterException.java b/src/main/java/com/wb/excel/api/exception/IllegalParameterException.java new file mode 100644 index 0000000..e9907b2 --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/IllegalParameterException.java @@ -0,0 +1,32 @@ +package com.wb.excel.api.exception; + +/** + * Created on 2014/10/12. + * + * @author + * @version 0.1.0 + */ +public class IllegalParameterException extends RuntimeException { + private static final long serialVersionUID = 234122996006212387L; + + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public IllegalParameterException() { + super(); + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public IllegalParameterException(String message) { + super(message); + } +} diff --git a/src/main/java/com/wb/excel/api/exception/TemplateNotMatchException.java b/src/main/java/com/wb/excel/api/exception/TemplateNotMatchException.java new file mode 100644 index 0000000..969c4ee --- /dev/null +++ b/src/main/java/com/wb/excel/api/exception/TemplateNotMatchException.java @@ -0,0 +1,29 @@ +package com.wb.excel.api.exception; + +/** + * Created on 2014/10/12. + * + * @author + * @version 0.1.0 + */ +public class TemplateNotMatchException extends Exception { + /** + * Constructs a new exception with {@code null} as its detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + */ + public TemplateNotMatchException() { + } + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public TemplateNotMatchException(String message) { + super(message); + } +} diff --git a/src/main/java/com/wb/excel/api/interfaces/EnumSupport.java b/src/main/java/com/wb/excel/api/interfaces/EnumSupport.java new file mode 100644 index 0000000..97421b0 --- /dev/null +++ b/src/main/java/com/wb/excel/api/interfaces/EnumSupport.java @@ -0,0 +1,38 @@ +package com.wb.excel.api.interfaces; + +/** + * 自定义枚举的基础类。 + * Created on 2014/9/27. + * + * @author + * @version 0.1.0 + */ +@Deprecated +public interface EnumSupport { + /** + * 每个实现类自身都要实现检查方法。
+ * 用于判断输入的值是否属于枚举内容。 + * + * @param str 要判断的值 + * @return true || false / 符合||不符合 + */ + public Boolean check(String str); + + /** + * 通过Value来获取Key。
+ * 例如性别: 输入男、Male、male都返回F(F为数据库中存储的值) + * + * @param value + * @return Key。最终存储至数据库中的值。 + */ + public Object getKey(String value); + + /** + * 通过Key来获取Value
+ * 例如性别:输入F,返回男 + * + * @param key + * @return Value。最终要展现给用户看的值。 + */ + public String getValue(Object key); +} diff --git a/src/main/java/com/wb/excel/api/interfaces/IExcelVerifyHandler.java b/src/main/java/com/wb/excel/api/interfaces/IExcelVerifyHandler.java new file mode 100644 index 0000000..2cbf4ad --- /dev/null +++ b/src/main/java/com/wb/excel/api/interfaces/IExcelVerifyHandler.java @@ -0,0 +1,34 @@ +package com.wb.excel.api.interfaces; + +import com.wb.excel.api.entity.DataVerifyResult; + +/** + * 导入校验接口 + */ +public interface IExcelVerifyHandler { + +// /** +// * 获取需要处理的字段,导入和导出统一处理了, 减少书写的字段 +// * +// * @return +// */ +// public String[] getNeedVerifyFields(); +// +// /** +// * 获取需要处理的字段,导入和导出统一处理了, 减少书写的字段 +// * +// * @return +// */ +// public void setNeedVerifyFields(String[] arr); + + /** + * 数据校验 + * + * @param obj 当前对象 + * @param name 当前字段名称 + * @param value 当前值 + * @return + */ + public DataVerifyResult verifyHandler(Object obj, String name, Object value); + +} diff --git a/src/main/java/com/wb/excel/api/style/BaseCellStyle.java b/src/main/java/com/wb/excel/api/style/BaseCellStyle.java new file mode 100644 index 0000000..b76f82b --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/BaseCellStyle.java @@ -0,0 +1,29 @@ +package com.wb.excel.api.style; + +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class BaseCellStyle { + /** + * 样式 + */ + protected CellStyle style; + + public BaseCellStyle(Workbook workbook) { + style = workbook.createCellStyle(); + } + + public CellStyle getStyle() { + return style; + } + + public void setStyle(CellStyle style) { + this.style = style; + } +} diff --git a/src/main/java/com/wb/excel/api/style/BaseFont.java b/src/main/java/com/wb/excel/api/style/BaseFont.java new file mode 100644 index 0000000..430c4dc --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/BaseFont.java @@ -0,0 +1,29 @@ +package com.wb.excel.api.style; + +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class BaseFont { + /** + * 字体 + */ + protected Font font; + + public BaseFont(Workbook workbook) { + font = workbook.createFont(); + } + + public Font getFont() { + return font; + } + + public void setFont(Font font) { + this.font = font; + } +} diff --git a/src/main/java/com/wb/excel/api/style/CheckFailureCellStyle.java b/src/main/java/com/wb/excel/api/style/CheckFailureCellStyle.java new file mode 100644 index 0000000..b84b512 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/CheckFailureCellStyle.java @@ -0,0 +1,44 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class CheckFailureCellStyle extends BaseCellStyle { + public CheckFailureCellStyle(Workbook workbook) { + super(workbook); + Font font = workbook.createFont(); // 单元格的字体 + font.setColor(HSSFColor.WHITE.index); // 字体颜色-白色 + CellStyle style = workbook.createCellStyle(); // 单元格的样式 + style.setFillForegroundColor(HSSFColor.RED.index); // 背景颜色-红色 + style.setFillPattern(CellStyle.SOLID_FOREGROUND); // 设置单元格填充样式 + style.setAlignment(CellStyle.ALIGN_CENTER); // 居中 + style.setFont(font); + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //上下居中 + + //下边框 + style.setBorderBottom(CellStyle.SOLID_FOREGROUND); + //下边框颜色 + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); + //左边框 + style.setBorderLeft(CellStyle.SOLID_FOREGROUND); + //左边框颜色 + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); + //右边框 + style.setBorderRight(CellStyle.SOLID_FOREGROUND); + //右边框颜色 + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); + //上边框 + style.setBorderTop(CellStyle.SOLID_FOREGROUND); + //上边框颜色 + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); + } +} diff --git a/src/main/java/com/wb/excel/api/style/CheckMessageCellStyle.java b/src/main/java/com/wb/excel/api/style/CheckMessageCellStyle.java new file mode 100644 index 0000000..3759662 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/CheckMessageCellStyle.java @@ -0,0 +1,24 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class CheckMessageCellStyle extends BaseCellStyle { + public CheckMessageCellStyle(Workbook workbook) { + super(workbook); + Font font = workbook.createFont(); // 单元格的字体 + font.setColor(HSSFColor.BLACK.index); // 字体颜色-黑色 + CellStyle style = workbook.createCellStyle(); // 单元格的样式 + style.setFillPattern(CellStyle.NO_FILL); // 设置单元格无填充 + style.setFont(font); + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //上下居中 + } +} diff --git a/src/main/java/com/wb/excel/api/style/CheckSuccessCellStyle.java b/src/main/java/com/wb/excel/api/style/CheckSuccessCellStyle.java new file mode 100644 index 0000000..a6a2e02 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/CheckSuccessCellStyle.java @@ -0,0 +1,40 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class CheckSuccessCellStyle extends BaseCellStyle { + public CheckSuccessCellStyle(Workbook workbook) { + super(workbook); + style.setFillForegroundColor(HSSFColor.LIME.index); // 背景颜色-绿色 + style.setFillPattern(CellStyle.SOLID_FOREGROUND); // 设置单元格填充样式 + style.setAlignment(CellStyle.ALIGN_CENTER); // 居中 + //style.setFont(font); + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //上下居中 + + //下边框 + style.setBorderBottom(CellStyle.SOLID_FOREGROUND); + //下边框颜色 + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); + //左边框 + style.setBorderLeft(CellStyle.SOLID_FOREGROUND); + //左边框颜色 + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); + //右边框 + style.setBorderRight(CellStyle.SOLID_FOREGROUND); + //右边框颜色 + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); + //上边框 + style.setBorderTop(CellStyle.SOLID_FOREGROUND); + //上边框颜色 + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); + } +} diff --git a/src/main/java/com/wb/excel/api/style/ErrorCellStyle.java b/src/main/java/com/wb/excel/api/style/ErrorCellStyle.java new file mode 100644 index 0000000..9eea4b1 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/ErrorCellStyle.java @@ -0,0 +1,39 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class ErrorCellStyle extends BaseCellStyle { + public ErrorCellStyle(Workbook workbook) { + super(workbook); + style.setFillForegroundColor(HSSFColor.ORANGE.index); //背景颜色-紫罗兰色 + style.setFillPattern(CellStyle.SOLID_FOREGROUND); //设置单元格填充样式 + //style.setFont(font); //设置单元格字体 + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//上下居中 + + //下边框 + style.setBorderBottom(CellStyle.SOLID_FOREGROUND); + //下边框颜色 + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); + //左边框 + style.setBorderLeft(CellStyle.SOLID_FOREGROUND); + //左边框颜色 + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); + //右边框 + style.setBorderRight(CellStyle.SOLID_FOREGROUND); + //右边框颜色 + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); + //上边框 + style.setBorderTop(CellStyle.SOLID_FOREGROUND); + //上边框颜色 + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); + } +} diff --git a/src/main/java/com/wb/excel/api/style/ErrorNumberCellStyle.java b/src/main/java/com/wb/excel/api/style/ErrorNumberCellStyle.java new file mode 100644 index 0000000..3d5ebb5 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/ErrorNumberCellStyle.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.style; + +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class ErrorNumberCellStyle extends ErrorCellStyle { + public ErrorNumberCellStyle(Workbook workbook) { + super(workbook); + style.setAlignment(CellStyle.ALIGN_RIGHT); + } +} diff --git a/src/main/java/com/wb/excel/api/style/HeadCellStyle.java b/src/main/java/com/wb/excel/api/style/HeadCellStyle.java new file mode 100644 index 0000000..2e668c9 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/HeadCellStyle.java @@ -0,0 +1,39 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class HeadCellStyle extends BaseCellStyle { + public HeadCellStyle(Workbook workbook) { + super(workbook); + style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); //背景颜色-灰色 + style.setFillPattern(CellStyle.SOLID_FOREGROUND); // 设置单元格填充样式 + style.setAlignment(CellStyle.ALIGN_CENTER); // 居中 + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//上下居中 + + //下边框 + style.setBorderBottom(CellStyle.SOLID_FOREGROUND); + //下边框颜色 + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); + //左边框 + style.setBorderLeft(CellStyle.SOLID_FOREGROUND); + //左边框颜色 + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); + //右边框 + style.setBorderRight(CellStyle.SOLID_FOREGROUND); + //右边框颜色 + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); + //上边框 + style.setBorderTop(CellStyle.SOLID_FOREGROUND); + //上边框颜色 + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); + } +} diff --git a/src/main/java/com/wb/excel/api/style/NormalCellStyle.java b/src/main/java/com/wb/excel/api/style/NormalCellStyle.java new file mode 100644 index 0000000..27e62c3 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/NormalCellStyle.java @@ -0,0 +1,28 @@ +package com.wb.excel.api.style; + +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class NormalCellStyle extends BaseCellStyle { + public NormalCellStyle(Workbook workbook) { + super(workbook); + style.setFillPattern(CellStyle.NO_FILL); //单元格不填充 + //style.setFont(font); //设置单元格字体 + style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //上下居中 + style.setBorderBottom(CellStyle.SOLID_FOREGROUND); //下边框 + style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); //下边框颜色 + style.setBorderLeft(CellStyle.SOLID_FOREGROUND); //左边框 + style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); //左边框颜色 + style.setBorderRight(CellStyle.SOLID_FOREGROUND); //右边框 + style.setRightBorderColor(IndexedColors.BLACK.getIndex()); //右边框颜色 + style.setBorderTop(CellStyle.SOLID_FOREGROUND); //上边框 + style.setTopBorderColor(IndexedColors.BLACK.getIndex()); //上边框颜色 + } +} diff --git a/src/main/java/com/wb/excel/api/style/NormalFont.java b/src/main/java/com/wb/excel/api/style/NormalFont.java new file mode 100644 index 0000000..f6cbb71 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/NormalFont.java @@ -0,0 +1,18 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * 普通字体.颜色黑 + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class NormalFont extends BaseFont { + public NormalFont(Workbook workbook) { + super(workbook); + font.setColor(HSSFColor.BLACK.index); //字体颜色-黑色 + } +} diff --git a/src/main/java/com/wb/excel/api/style/NormalNumberCellStyle.java b/src/main/java/com/wb/excel/api/style/NormalNumberCellStyle.java new file mode 100644 index 0000000..b2f6513 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/NormalNumberCellStyle.java @@ -0,0 +1,17 @@ +package com.wb.excel.api.style; + +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class NormalNumberCellStyle extends NormalCellStyle { + public NormalNumberCellStyle(Workbook workbook) { + super(workbook); + style.setAlignment(CellStyle.ALIGN_RIGHT); + } +} diff --git a/src/main/java/com/wb/excel/api/style/RedFont.java b/src/main/java/com/wb/excel/api/style/RedFont.java new file mode 100644 index 0000000..2d2fdc6 --- /dev/null +++ b/src/main/java/com/wb/excel/api/style/RedFont.java @@ -0,0 +1,18 @@ +package com.wb.excel.api.style; + +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * 普通字体.颜色黑 + * Created on 2015/1/29. + * + * @author + * @since 2.0.0 + */ +public class RedFont extends BaseFont { + public RedFont(Workbook workbook) { + super(workbook); + font.setColor(HSSFColor.RED.index); //字体颜色-黑色 + } +} diff --git a/src/main/java/com/wb/excel/api/util/BaseVerifyUtil.java b/src/main/java/com/wb/excel/api/util/BaseVerifyUtil.java new file mode 100644 index 0000000..29685a3 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/BaseVerifyUtil.java @@ -0,0 +1,135 @@ +package com.wb.excel.api.util; + + +import com.wb.excel.api.entity.DataVerifyResult; + +import java.util.regex.Pattern; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:数据基础校验
+ * ***************************************************************
+ * 
+ */ +public class BaseVerifyUtil { + private static String NOT_NULL = "不允许为空"; + private static String IS_MOBILE = "不是手机号"; + private static String IS_TEL = "不是电话号码"; + private static String IS_EMAIL = "不是邮箱地址"; + private static String MIN_LENGHT = "小于规定长度"; + private static String MAX_LENGHT = "超过规定长度"; + + private static Pattern mobilePattern = Pattern.compile("^[1][3,4,5,8,7][0-9]{9}$"); + + private static Pattern telPattern = Pattern.compile("^([0][1-9]{2,3}-)?[0-9]{5,10}$"); + + private static Pattern emailPattern = Pattern + .compile("^([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$"); + + + /** + * email校验 + * + * @param name + * @param val + * @return + */ + public static DataVerifyResult isEmail(String name, Object val) { + if (!emailPattern.matcher(String.valueOf(val)).matches()) { + return new DataVerifyResult(false, name + IS_EMAIL); + } + return new DataVerifyResult(true); + } + + /** + * 手机校验 + * + * @param name + * @param val + * @return + */ + public static DataVerifyResult isMobile(String name, Object val) { + if (!mobilePattern.matcher(String.valueOf(val)).matches()) { + return new DataVerifyResult(false, name + IS_MOBILE); + } + return new DataVerifyResult(true); + } + + /** + * 电话校验 + * + * @param name + * @param val + * @return + */ + public static DataVerifyResult isTel(String name, Object val) { + if (!telPattern.matcher(String.valueOf(val)).matches()) { + return new DataVerifyResult(false, name + IS_TEL); + } + return new DataVerifyResult(true); + } + + /** + * 最大长度校验 + * + * @param name + * @param val + * @return + */ + public static DataVerifyResult maxLength(String name, Object val, int maxLength) { + if (notNull(name, val).isSuccess() && String.valueOf(val).length() > maxLength) { + return new DataVerifyResult(false, name + MAX_LENGHT); + } + return new DataVerifyResult(true); + } + + /** + * 最小长度校验 + * + * @param name + * @param val + * @param minLength + * @return + */ + public static DataVerifyResult minLength(String name, Object val, int minLength) { + if (notNull(name, val).isSuccess() && String.valueOf(val).length() < minLength) { + return new DataVerifyResult(false, name + MIN_LENGHT); + } + return new DataVerifyResult(true); + } + + /** + * 非空校验 + * + * @param name + * @param val + * @return + */ + public static DataVerifyResult notNull(String name, Object val) { + if (val == null || val.toString().equals("")) { + return new DataVerifyResult(false, name + NOT_NULL); + } + return new DataVerifyResult(true); + } + + /** + * 正则表达式校验 + * + * @param name + * @param val + * @param regex + * @param regexTip + * @return + */ + public static DataVerifyResult regex(String name, Object val, String regex, + String regexTip) { + Pattern pattern = Pattern.compile(regex); + if (!pattern.matcher(String.valueOf(val)).matches()) { + return new DataVerifyResult(false, name + regexTip); + } + return new DataVerifyResult(true); + } +} diff --git a/src/main/java/com/wb/excel/api/util/ClassUtil.java b/src/main/java/com/wb/excel/api/util/ClassUtil.java new file mode 100644 index 0000000..0db27a9 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/ClassUtil.java @@ -0,0 +1,195 @@ +package com.wb.excel.api.util; + + +import com.wb.excel.api.annotation.ExcelCollection; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; + +/** + * Created on 2015/5/28. + * + * @author 金洋 + * @version 2.1.0 + */ +public class ClassUtil { + + public static Field[] getFields(Class clazz, boolean parentFirst) { + List returnList = new ArrayList<>(); + Set nameSet = new HashSet<>(); + + Field[] fields = clazz.getDeclaredFields(); + + for (Field field : fields) { + returnList.add(field); + nameSet.add(field.getName()); + } + List parentList = getParentFields(clazz.getSuperclass(), nameSet, parentFirst); + if (parentFirst) { + parentList.addAll(returnList); + returnList = parentList; + } else { + returnList.addAll(parentList); + } + + fields = new Field[returnList.size()]; + + int index = 0; + for (Field field : returnList) { + fields[index++] = field; + } + return fields; + + } + + /** + * 获取class的 包括父类的 + * + * @param clazz + * @return + */ + public static Field[] getClassFields(Class clazz) { + List list = new ArrayList(); + Field[] fields; + do { + fields = clazz.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + list.add(fields[i]); + } + clazz = clazz.getSuperclass(); + } while (clazz != Object.class && clazz != null); + return list.toArray(fields); + } + + /** + * 判断是不是集合的实现类 + * + * @param clazz + * @return + */ + public static boolean isCollection(Class clazz) { + return Collection.class.isAssignableFrom(clazz); + } + + /** + * 获取GET方法 + * + * @param name + * @param pojoClass + * @return + * @throws Exception + */ + public static Method getMethod(String name, Class pojoClass) throws Exception { + StringBuffer getMethodName = new StringBuffer("get"); + getMethodName.append(name.substring(0, 1).toUpperCase()); + getMethodName.append(name.substring(1)); + Method method = null; + try { + method = pojoClass.getMethod(getMethodName.toString(), new Class[]{}); + } catch (Exception e) { + method = pojoClass.getMethod( + getMethodName.toString().replace("get", "is"), + new Class[]{}); + } + return method; + } + + /** + * 获取SET方法 + * + * @param name + * @param pojoClass + * @param type + * @return + * @throws Exception + */ + public static Method getMethod(String name, Class pojoClass, Class type) throws Exception { + StringBuffer getMethodName = new StringBuffer("set"); + getMethodName.append(name.substring(0, 1).toUpperCase()); + getMethodName.append(name.substring(1)); + return pojoClass.getMethod(getMethodName.toString(), new Class[]{type}); + } + + /** + * 是不是java基础类 + * + * @param field + * @return + */ + public static boolean isJavaClass(Field field) { + Class fieldType = field.getType(); + boolean isBaseClass = false; + if (fieldType.isArray()) { + isBaseClass = false; + } else if (fieldType.isPrimitive() || fieldType.getPackage() == null + || fieldType.getPackage().getName().equals("java.lang") + || fieldType.getPackage().getName().equals("java.math") + || fieldType.getPackage().getName().equals("java.sql") + || fieldType.getPackage().getName().equals("java.util")) { + isBaseClass = true; + } + return isBaseClass; + } + + /** + * 通过指定的类型获取所有的成员变量 + * + * @param clazz + * @return + */ + public static Field[] getFields(Class clazz) { + return getFields(clazz, false); + } + + private static List getParentFields(Class parentClazz, Set nameSet, boolean parentFirst) { + List fieldList = new ArrayList<>(); + + if (parentClazz != null) { + Field[] parentList = parentClazz.getDeclaredFields(); + int index = 0; + for (Field field : parentList) { + int beginSize = nameSet.size(); + nameSet.add(field.getName()); + int endSize = nameSet.size(); + + if (endSize > beginSize) { + if (parentFirst) { + fieldList.add(index++, field); + } else { + fieldList.add(field); + } + } + } + fieldList.addAll(getParentFields(parentClazz.getSuperclass(), nameSet, parentFirst)); + } + return fieldList; + } + + public static Object createObject(Class clazz) { + Object obj = null; + Method setMethod; + try { + if (clazz.equals(Map.class)) { + return new HashMap(); + } + obj = clazz.newInstance(); + Field[] fields = getClassFields(clazz); + for (Field field : fields) { + if (isCollection(field.getType())) { + ExcelCollection collection = field.getAnnotation(ExcelCollection.class); + setMethod = getMethod(field.getName(), clazz, field.getType()); + setMethod.invoke(obj, collection.type().newInstance()); + } else if (!isJavaClass(field)) { + setMethod = getMethod(field.getName(), clazz, field.getType()); + setMethod.invoke(obj, createObject(field.getType())); + } + } + + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("创建对象异常"); + } + return obj; + } +} diff --git a/src/main/java/com/wb/excel/api/util/DataTableUtil.java b/src/main/java/com/wb/excel/api/util/DataTableUtil.java new file mode 100644 index 0000000..d55891f --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/DataTableUtil.java @@ -0,0 +1,46 @@ +package com.wb.excel.api.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created on 2014/10/12. + * + * @author + * @version 0.1.0 + */ +public class DataTableUtil { + + /** + * 测试用方法。从本地文件读取字节数据。 + * + * @param url 本地文件路径 + * @return 读取文件的byte数组 + * @throws java.io.IOException 读取文件中可能会抛出异常 + */ + public static byte[] readFile(String url) throws IOException { + File file = new File(url); + InputStream is = new FileInputStream(file); + Long length = file.length(); + if (length > Integer.MAX_VALUE) { + throw new IOException("文件过大,无法读取"); + } + + byte[] bytes = new byte[length.intValue()]; + int offset = 0; + int numRead; + while (offset < bytes.length + && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { + offset += numRead; + } + + //如果得到的字节长度和file实际的长度不一致就可能出错了 + if (offset < bytes.length) { + System.out.println("文件长度不一致"); + } + is.close(); + return bytes; + } +} diff --git a/src/main/java/com/wb/excel/api/util/EnumUtil.java b/src/main/java/com/wb/excel/api/util/EnumUtil.java new file mode 100644 index 0000000..b8cb4dd --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/EnumUtil.java @@ -0,0 +1,127 @@ +package com.wb.excel.api.util; + + +import com.wb.excel.api.annotation.EnumValue; + +import java.lang.reflect.Field; + +/** + * Created on 2014/10/10. + * + * @author + * @version 0.1.0 + */ +public class EnumUtil { + /** + * 用于判断输入的值是否属于枚举内容。 + * + * @param clazz + * @param value 要判断的值 + * @return true || false / 符合||不符合 + */ + public static Boolean check(Class clazz, String value) { + if (clazz.isEnum() && value.length() > 0) { + value = value.toLowerCase(); + Field[] fields = clazz.getFields(); + for (Field field : fields) { + if (!field.isAnnotationPresent(EnumValue.class)) { + continue; + } + EnumValue enumValue = field.getAnnotation(EnumValue.class); + String[] enumValues = enumValue.value(); + for (String temp : enumValues) { + if (temp.equals(value)) { + return true; + } + } + } + return false; + } + return true; + } + + /** + * 通过指定的枚举类和value值,返回key值(未找到key时返回空字符串) + * + * @param clazz + * @param value + * @return + */ + public static String getKey(Class clazz, String value) { + if (clazz.isEnum()) { + value = value.toLowerCase(); + Field[] fields = clazz.getFields(); + for (Field field : fields) { + if (!field.isAnnotationPresent(EnumValue.class)) { + continue; + } + EnumValue enumValue = field.getAnnotation(EnumValue.class); + String[] enumValues = enumValue.value(); + for (String temp : enumValues) { + if (temp.equals(value)) { + return field.getName(); + } + } + } + } + return ""; + } + + /** + * 通过指定的枚举类和key值,返回第一个value值(未指定value时会返回key的值) + * + * @param clazz 要获取值的枚举类 + * @param key 枚举的key + * @return 对应的value + */ + public static String getValue(Class clazz, String key) { + if (clazz.isEnum()) { + Field[] fields = clazz.getFields(); + for (Field field : fields) { + if (!field.isAnnotationPresent(EnumValue.class)) { + continue; + } + EnumValue enumValue = field.getAnnotation(EnumValue.class); + String[] enumValues = enumValue.value(); + + /* 如果找到了key */ + if (field.getName().equals(key)) { + /* 如果没有注明枚举的内容,直接返回key */ + if (enumValues.length == 1 && enumValues[0].equals("")) { + enumValues[0] = key; + } + /* 返回 */ + return enumValues[0]; + } + } + } + return ""; + } + + /** + * 根据索引获取 + * + * @param + * @param clazz + * @param ordinal + * @return + */ + public static > T valueOf(Class clazz, int ordinal) { + return clazz.getEnumConstants()[ordinal]; + } + + /** + * 根据name获取 + * + * @param + * @param enumType + * @param name + * @return + */ + public static > T valueOf(Class enumType, String name) { + if (name != null && !"".equals(name)) { + return Enum.valueOf(enumType, name); + } + return null; + } +} diff --git a/src/main/java/com/wb/excel/api/util/ExcelUtil.java b/src/main/java/com/wb/excel/api/util/ExcelUtil.java new file mode 100644 index 0000000..22625e7 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/ExcelUtil.java @@ -0,0 +1,32 @@ +package com.wb.excel.api.util; + +import org.apache.poi.ss.usermodel.Cell; + +/** + * Excel工具类. + * Created on 2014/9/1. + * + * @author + * @since 0.1.0 + */ +public class ExcelUtil { + + /** + * 获取单元格的值 + * + * @param cell 要获取值的单元格 + * @return 单元格的值 + */ + public static String getValue(Cell cell) { + if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { + // 返回布尔类型的值 + return String.valueOf(cell.getBooleanCellValue()); + } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { + // 返回数值类型的值 + return String.valueOf(cell.getNumericCellValue()); + } else { + // 返回字符串类型的值 + return String.valueOf(cell.getStringCellValue()); + } + } +} diff --git a/src/main/java/com/wb/excel/api/util/StringUtil.java b/src/main/java/com/wb/excel/api/util/StringUtil.java new file mode 100644 index 0000000..9634cb9 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/StringUtil.java @@ -0,0 +1,206 @@ +package com.wb.excel.api.util; + +import com.wb.excel.api.enumeration.YesNo; +import org.apache.poi.hssf.usermodel.HSSFDateUtil; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by DEV001 on 2014/9/1. + */ +public class StringUtil { + + public static int getByteLength(String str) { + int length = str.replaceAll("[^\\x00-\\xff]", "**").length(); + return length; + } + + public static String upperFirstWord(String str) { + String temp = str.substring(0, 1); + return temp.toUpperCase() + str.substring(1); + } + + /** + * TODO + * + * @param str + * @param reg + * @param index + * @return + */ + public static String split(String str, String reg, int index) { + if (reg.length() == 0) { + return str; + } + String[] strings = str.split(reg); + if (index < 0) { + index = 0; + } + if (index >= strings.length) { + index = strings.length - 1; + } + return strings[index]; + } + + public static String substring(String str, int start, int end) { + if (0 >= start || start >= str.length()) { + end = str.length() - 1; + } + if (0 >= end || end >= str.length()) { + end = str.length() - 1; + } + return str.substring(start, end); + } + + public static String transferDate(String value) { + Double d = TransferUtil.transferDouble(value); + Date date = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + if (d == null) { + try { + date = sdf.parse(value); + } catch (ParseException e) { + e.printStackTrace(); + } + } else { + date = HSSFDateUtil.getJavaDate(d); + } + return sdf.format(date); + } + + public static String transferDatetime(String value) { + Double d = TransferUtil.transferDouble(value); + Date date = null; + + List sdfList = new ArrayList<>(); + sdfList.add("yyyy-MM-dd HH:mm:ss"); + sdfList.add("yyyy-MM-dd hh:mm:ss"); + sdfList.add("yyyy/MM/dd HH:mm:ss"); + sdfList.add("yyyy/MM/dd hh:mm:ss"); + + SimpleDateFormat stdFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + if (d == null) { + for (String sdfValue : sdfList) { + SimpleDateFormat sdf = new SimpleDateFormat(sdfValue); + try { + date = sdf.parse(value); + break; + } catch (ParseException ignored) { + } + } + } else { + date = HSSFDateUtil.getJavaDate(d); + } + return stdFormat.format(date); + } + + public static String transferDateminute(String value) { + Double d = TransferUtil.transferDouble(value); + Date date = null; + + List sdfList = new ArrayList<>(); + sdfList.add("yyyy-MM-dd HH:mm:ss"); + sdfList.add("yyyy-MM-dd hh:mm:ss"); + sdfList.add("yyyy/MM/dd HH:mm:ss"); + sdfList.add("yyyy/MM/dd hh:mm:ss"); + + SimpleDateFormat stdFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + if (d == null) { + for (String sdfValue : sdfList) { + SimpleDateFormat sdf = new SimpleDateFormat(sdfValue); + try { + date = sdf.parse(value); + break; + } catch (ParseException ignored) { + } + } + } else { + date = HSSFDateUtil.getJavaDate(d); + } + return stdFormat.format(date); + } + + public static String transferInteger(String value) { + try { + Double d = Double.parseDouble(value); + int i = d.intValue(); + if (d != i) { + return null; + } else { + return "" + i; + } + } catch (Exception e) { + return null; + } + } + + public static String transferBoolean(String value) { + String key = EnumUtil.getKey(YesNo.class, value); + if (key.equals("Y")) { + return "是"; + } else if (key.equals("N")) { + return "否"; + } + return ""; + } + + public static String transferLong(String value) { + try { + Double d = Double.parseDouble(value); + long i = d.longValue(); + if (d != i) { + return null; + } else { + return "" + i; + } + } catch (Exception e) { + return null; + } + } + + /** + * 将字符串加密处理,例:sample@passionnetwork.com → samp***********.com + * + * @param input 想要加密的字符串 + * @param startLength 加密开始位置 + * @param endLength 加密结束位置 + * @param isAbsolute 是否保持原来长度 + * @return 加密后的字符串 + */ + public static String encryptString(String input, int startLength, int endLength, boolean isAbsolute) { + int length = input.length(); + int endIndex = length - endLength; + if (startLength > length || endLength > length) { + return input; + } + + String start = input.substring(0, startLength); + String end = input.substring(endIndex); + String out = start; + + if (isAbsolute) { + for (int i = startLength; i < endIndex; i++) { + out += "*"; + } + } else { + out += "****"; + } + out += end; + + return out; + } + + public static String fixNumberLength(int number, int length) { + String fixedNumber = "" + String.valueOf(number); + while (fixedNumber.length() < length) { + fixedNumber = "0" + fixedNumber; + } + return fixedNumber; + } +} diff --git a/src/main/java/com/wb/excel/api/util/StringUtils.java b/src/main/java/com/wb/excel/api/util/StringUtils.java new file mode 100644 index 0000000..d76add6 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/StringUtils.java @@ -0,0 +1,146 @@ +package com.wb.excel.api.util; + +import org.apache.poi.hpsf.Constants; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:
+ * ***************************************************************
+ * 
+ */ +public class StringUtils { + private StringUtils() { + } + + /** + * 检查指定的字符串是否为空。 + *
    + *
  • SysUtils.isEmpty(null) = true
  • + *
  • SysUtils.isEmpty("") = true
  • + *
  • SysUtils.isEmpty(" ") = true
  • + *
  • SysUtils.isEmpty("abc") = false
  • + *
+ * + * @param value 待检查的字符串 + * @return true/false + */ + public static boolean isEmpty(String value) { + int strLen; + if(value == null || (strLen = value.length()) == 0) { + return true; + } + for(int i = 0; i < strLen; i++) { + if((Character.isWhitespace(value.charAt(i)) == false)) { + return false; + } + } + return true; + } + public static boolean isNotEmpty(String value) { + int strLen; + if(value == null || (strLen = value.length()) == 0) { + return false; + } + for(int i = 0; i < strLen; i++) { + if((Character.isWhitespace(value.charAt(i)) == false)) { + return true; + } + } + return false; + } + + /** + * 检查对象是否为数字型字符串,包含负数开头的。 + */ + public static boolean isNumeric(Object obj) { + if(obj == null) { + return false; + } + char[] chars = obj.toString().toCharArray(); + int length = chars.length; + if(length < 1) + return false; + + int i = 0; + if(length > 1 && chars[0] == '-') + i = 1; + + for(; i < length; i++) { + if(!Character.isDigit(chars[i])) { + return false; + } + } + return true; + } + + /** + * 检查指定的字符串列表是否不为空。 + */ + public static boolean areNotEmpty(String... values) { + boolean result = true; + if(values == null || values.length == 0) { + result = false; + } else { + for(String value : values) { + result &= !isEmpty(value); + } + } + return result; + } + + /** + * 把通用字符编码的字符串转化为汉字编码。 + */ + public static String unicodeToChinese(String unicode) { + StringBuilder out = new StringBuilder(); + if(!isEmpty(unicode)) { + for(int i = 0; i < unicode.length(); i++) { + out.append(unicode.charAt(i)); + } + } + return out.toString(); + } + + public static String toUnderlineStyle(String name) { + StringBuilder newName = new StringBuilder(); + for(int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if(Character.isUpperCase(c)) { + if(i > 0) { + newName.append("_"); + } + newName.append(Character.toLowerCase(c)); + } else { + newName.append(c); + } + } + return newName.toString(); + } +// +// public static String convertString(byte[] data, int offset, int length) { +// if(data == null) { +// return null; +// } else { +// try { +// return new String(data, offset, length, Constants.CHARSET_UTF8); +// } catch(Exception e) { +// throw new RuntimeException(e); +// } +// } +// } +// +// public static byte[] convertBytes(String data) { +// if(data == null) { +// return null; +// } else { +// try { +// return data.getBytes(Constants.CHARSET_UTF8); +// } catch(Exception e) { +// throw new RuntimeException(e); +// } +// } +// } +} diff --git a/src/main/java/com/wb/excel/api/util/TransferUtil.java b/src/main/java/com/wb/excel/api/util/TransferUtil.java new file mode 100644 index 0000000..021c7f6 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/TransferUtil.java @@ -0,0 +1,101 @@ +package com.wb.excel.api.util; + + +import com.wb.excel.api.enumeration.YesNo; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created on 2014/9/27. + * + * @author + * @version 0.1.0 + */ +public class TransferUtil { + public static Date transferDate(String value) { + Date date = null; + try { + if (value.length() == 10) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + date = sdf.parse(value); + } else if (value.length() > 10) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + date = sdf.parse(value); + } + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + } + + public static Date transferDatetime(String value) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = null; + try { + date = sdf.parse(value); + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + } + + public static Date transferDateminute(String value) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = null; + try { + date = sdf.parse(value); + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + } + + public static Integer transferInteger(String value) { + try { + Double d = Double.parseDouble(value); + int i = d.intValue(); + if (d != i) { + return null; + } else { + return i; + } + } catch (Exception e) { + return null; + } + } + + public static Double transferDouble(String value) { + try { + return Double.parseDouble(value); + } catch (Exception e) { + return null; + } + } + + public static Boolean transferBoolean(String value) { + String key = EnumUtil.getKey(YesNo.class, value); + if (key.equals("Y")) { + return true; + } else if (key.equals("N")) { + return false; + } else { + return null; + } + } + + public static Long transferLong(String value) { + try { + Double d = Double.parseDouble(value); + long i = d.longValue(); + if (d != i) { + return null; + } else { + return i; + } + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/com/wb/excel/api/util/ValidationUtil.java b/src/main/java/com/wb/excel/api/util/ValidationUtil.java new file mode 100644 index 0000000..e54c0b7 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/ValidationUtil.java @@ -0,0 +1,241 @@ +package com.wb.excel.api.util; + + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 验证工具类。提供一些通用简单的数据验证功能。 + * Created by DEV001 on 2014/8/1. + */ +public class ValidationUtil { + + private static Validator validator; + + /** + * 检查ID是否合法 + * + * @param id 要检查的ID + * @return true, ID合法 + */ + public static Boolean checkId(Long id) { + return !(null == id || id < 1); + } + + public static Boolean checkDate(String value) { + try { + Double.valueOf(value); + } catch (Exception e) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + sdf.parse(value); + return true; + } catch (ParseException e1) { + e1.printStackTrace(); + } + return false; + } + return true; + } + + public static Boolean checkDatetime(String value) { + try { + Double.valueOf(value); + } catch (Exception e) { + List sdfList = new ArrayList<>(); + sdfList.add("yyyy-MM-dd HH:mm:ss"); + sdfList.add("yyyy-MM-dd hh:mm:ss"); + sdfList.add("yyyy/MM/dd HH:mm:ss"); + sdfList.add("yyyy/MM/dd hh:mm:ss"); + + for (int i = 0; i < sdfList.size(); i++) { + String sdfValue = sdfList.get(i); + SimpleDateFormat sdf = new SimpleDateFormat(sdfValue); + try { + sdf.parse(value); + return true; + } catch (ParseException ignored) { + } + } + return false; + } + return true; + } + + public static Boolean checkDouble(String value) { + try { + Double.parseDouble(value); + } catch (Exception e) { + return false; + } + return true; + } + + /** + * 检查一个字符串是否可以转为整数。 + * + * @param value 要检查的字符串 + * @return true || false + */ + public static Boolean checkInteger(String value) { + try { + Double d = Double.parseDouble(value); + int i = d.intValue(); + return d == i; + } catch (Exception e) { + return false; + } + } + + /** + * 检查一个字符串是否可以转为长整数。 + * + * @param value 要检查的字符串 + * @return true || false + */ + public static boolean checkLong(String value) { + try { + Double d = Double.parseDouble(value); + long l = d.longValue(); + return d == l; + } catch (Exception e) { + return false; + } + } + + /** + * 检查用户ID的列表是否合法 + * + * @param ids 要检查的ID列表 + * @return true, 输入的ID列表合法 + */ + public static Boolean checkIdList(List ids) { + return !(null == ids || ids.size() == 0); + } + + /** + * 检查字符串。不为空返回true;为空返回false。
+ * 内容为空也认为是空 + * + * @param str 要检查的字符串 + * @return 检查的结果。true,检查通过;false,检查不通过。 + */ + public static Boolean checkString(String str) { + return !(null == str || 0 == str.trim().length()); + } + + /** + * 检查字符串的长度是否符合要求。
该方法不会删除字符串前后的空格 + * + * @param str 要进行判断的字符串 + * @param minLength 字符串限制的最小长度(包含) + * @param maxLength 字符串限制的最大长度(包含) + * @return 例如:限制长度 2,50。字符串为"aa"返回true,字符串为"a"返回false + */ + public static Boolean checkStringLength(String str, int minLength, int maxLength) { + if (null == str) { + return false; + } else { + if (str.length() >= minLength && str.length() <= maxLength) { + return true; + } + } + return false; + } + + /** + * 检查邮箱格式是否正确
+ * + * @param email 要检查的邮箱地址 + * @return true, 格式正确;false,格式不正确
+ * 例如:
+ * 0123-abcd_ABCD@0123-abcd_ABCD.00aaBB--__.cc true
+ * a@a.a true
+ * tony@sina@qq.com false + */ + public static Boolean checkEmail(String email) { + //验证邮箱地址的正则表达式 + Pattern p; + p = Pattern.compile( + "^([a-zA-Z0-9]+[_|_|-|-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|-|-|.]?)*[a-zA-Z0-9]+.[a-zA-Z]{2,3}$"); + Matcher m = p.matcher(email); + return m.matches(); + } + + + /** + * 检查文件路径格式是否正确
+ * + * @param filePath 要检查的文件路径 + * @return true, 格式正确;false,格式不正确
+ * 例如:
+ * C:\b.txt true
+ * C:\abc\a.txt true
+ * C:\windows\sys<\mfc.dll false + */ + public static Boolean checkFilePath(String filePath) { + //验证文件路径格式的正则表达式 + Pattern p = Pattern.compile("^(?(?:[a-zA-Z]:)?\\\\(?:[^\\\\\\?\\/\\*\\|<>:\"]+\\\\)+)(?(?[^\\\\\\?\\/\\*\\|<>:\"]+?)\\.(?[^.\\\\\\?\\/\\*\\|<>:\"]+))$"); + Matcher m = p.matcher(filePath); + return m.matches(); + } + + /** + * 检查电话号码格式是否正确。 + * + * @param phone 要检查的电话号码 + * @return true, 格式正确;false,格式不正确
+ * 例如:
+ * 13345661234 true
+ * 16812341234 false
+ * 0512-123456 false
+ * 0512-2345678 true
+ * 12345678 false
+ * 22345678 true + */ + public static Boolean checkPhone(String phone) { + List list = new LinkedList<>(); + list.add(Pattern.compile("^[1][3,4,5,8][0-9]{9}$")); //验证手机号 + list.add(Pattern.compile("^[0][1-9]{1,2}[0-9]-[2-9][0-9]{6,7}$")); //验证带区号固定电话,区号后加“-” + list.add(Pattern.compile("^[2-9][0-9]{6,7}$")); //验证不带区号的固定电话 + list.add(Pattern.compile("([0][1-9]{1,2}[0-9])[2-9][0-9]{6,7}$")); + + Matcher matcher; + Boolean result = false; + for (Pattern pattern : list) { + matcher = pattern.matcher(phone); //遍历匹配 + result |= matcher.matches(); //对所有的匹配结果做或运算。 + } + return result; + } + + /** + * 检查URL是否正确 + * + * @param url + * @return + */ + public static Boolean checkUrl(String url) { + List list = new LinkedList<>(); + list.add(Pattern.compile("^(http|www|ftp|)?(://)?(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*((:\\d+)?)(/(\\w+(-\\w+)*))*(\\.?(\\w)*)(\\?)?(((\\w*%)*(\\w*\\?)*(\\w*:)*(\\w*\\+)*(\\w*\\.)*(\\w*&)*(\\w*-)*(\\w*=)*(\\w*%)*(\\w*\\?)*(\\w*:)*(\\w*\\+)*(\\w*\\.)*(\\w*&)*(\\w*-)*(\\w*=)*)*(\\w*)*)$")); + + Matcher matcher; + Boolean result = false; + for (Pattern pattern : list) { + matcher = pattern.matcher(url); //遍历匹配 + result |= matcher.matches(); //对所有的匹配结果做或运算。 + } + return result; + } + +} diff --git a/src/main/java/com/wb/excel/api/util/VerifyDataUtil.java b/src/main/java/com/wb/excel/api/util/VerifyDataUtil.java new file mode 100644 index 0000000..3107441 --- /dev/null +++ b/src/main/java/com/wb/excel/api/util/VerifyDataUtil.java @@ -0,0 +1,64 @@ +package com.wb.excel.api.util; + +import com.wb.excel.api.entity.DataVerifyResult; +import com.wb.excel.api.entity.ExcelVerifyEntity; +import com.wb.excel.api.interfaces.IExcelVerifyHandler; + +/** + * *************************************************************** + *

+ *

+ * Copyright (c) 2014 –
+ *  HeaderDescription:
+ * ***************************************************************
+ * 
+ */ +public class VerifyDataUtil { + private final static DataVerifyResult DEFAULT_RESULT = new DataVerifyResult( + true); + + private void addVerifyResult(DataVerifyResult hanlderResult, + DataVerifyResult result) { + if (!hanlderResult.isSuccess()) { + result.setSuccess(false); + result.setMsg((StringUtils.isEmpty(result.getMsg()) ? "" : result.getMsg() + " , ") + + hanlderResult.getMsg()); + } + } + + public DataVerifyResult verifyData(Object object, Object value, String name, String showName, + ExcelVerifyEntity verify, IExcelVerifyHandler excelVerifyHandler) { + if (verify == null) { + return DEFAULT_RESULT; + } + DataVerifyResult result = new DataVerifyResult(true, ""); + if (verify.isNotNull()) { + addVerifyResult(BaseVerifyUtil.notNull(showName, value), result); + } + if (verify.isEmail()) { + addVerifyResult(BaseVerifyUtil.isEmail(showName, value), result); + } + if (verify.isMobile()) { + addVerifyResult(BaseVerifyUtil.isMobile(showName, value), result); + } + if (verify.isTel()) { + addVerifyResult(BaseVerifyUtil.isTel(showName, value), result); + } + if (verify.getMaxLength() != -1) { + addVerifyResult(BaseVerifyUtil.maxLength(showName, value, verify.getMaxLength()), result); + } + if (verify.getMinLength() != -1) { + addVerifyResult(BaseVerifyUtil.minLength(showName, value, verify.getMinLength()), result); + } + if (StringUtils.isNotEmpty(verify.getRegex())) { + addVerifyResult( + BaseVerifyUtil.regex(showName, value, verify.getRegex(), verify.getRegexTip()), + result); + } + if (verify.isInterHandler()) { + addVerifyResult(excelVerifyHandler.verifyHandler(object, name, value), result); + } + return result; + + } +} diff --git a/src/test/java/ExampleTest.java b/src/test/java/ExampleTest.java new file mode 100644 index 0000000..a2e86e7 --- /dev/null +++ b/src/test/java/ExampleTest.java @@ -0,0 +1,109 @@ +import com.wb.excel.api.Excel; +import com.wb.excel.api.datatable.DataTable; +import com.wb.excel.api.enumeration.YesNo; +import com.wb.excel.api.exception.TemplateNotMatchException; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** + * 实例 + */ +public class ExampleTest { + + public static void main(String[] args) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + testExport(); + testImport(); + } + + public static void testExport() { + + try { + //第一步,准备数据模型及数据,模型需要打上注解 + List pos = new ArrayList(); + + User user = new User("张三", "zs123", "123123"); + user.setSex(YesNo.Y); + pos.add(user); + pos.add(user); + + //第二步,初始化数据 + DataTable dataTable = new DataTable(pos); + + //第三步,初始化Excel + Excel excel = new Excel(dataTable); + + //第四步,导出xlsx文件 + output("user.xlsx", excel.getBytes()); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + + } + + public static void testImport() { + try { + File file = new File("user.xlsx"); + FileInputStream stream = new FileInputStream(file); + + byte[] bytes = new byte[stream.available()]; + stream.read(bytes); + + DataTable dataTable = new DataTable(bytes, User.class); + + if (dataTable.hasError()) { + Excel excel = new Excel(true, dataTable); + output("user_err.xlsx", excel.getBytes()); + } else { + List list = dataTable.transferList(User.class); + System.out.println("本次读取数据" + list.size() + "条!"); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (TemplateNotMatchException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + public static void output(String path, byte[] bytes) { + try { + File file = new File(path); + file.createNewFile(); + + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(file); + fileOutputStream.write(bytes); + } finally { + try { + fileOutputStream.flush(); + fileOutputStream.close(); + } catch (Exception e) { + + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/src/test/java/User.java b/src/test/java/User.java new file mode 100644 index 0000000..1e361b9 --- /dev/null +++ b/src/test/java/User.java @@ -0,0 +1,55 @@ +import com.wb.excel.api.annotation.Enum; +import com.wb.excel.api.annotation.EnumValue; +import com.wb.excel.api.enumeration.YesNo; + + +public class User { + + private String name; + private String password; + private String qq; + + @Enum(target = YesNo.class) + private YesNo sex; + + public User() { + } + + public User(String name, String password, String qq) { + this.name = name; + this.password = password; + this.qq = qq; + } + + public YesNo getSex() { + return sex; + } + + public void setSex(YesNo sex) { + this.sex = sex; + } + + public String getQq() { + return qq; + } + + public void setQq(String qq) { + this.qq = qq; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +}