SpringBoot通過WorkBook快速實現對Excel的匯入和匯出(包括資料校驗)
阿新 • • 發佈:2018-11-17
之前轉載過一篇對Excel基本操作相關的文章,這篇文章的瀏覽量迅速飆升,以至於在我部落格的熱門文章中排到了第三的位置,不過那篇轉載的文章實用性差並且講解不是很清晰,所以打算趁著今天休息,寫一篇關於SpringBoot通過WorkBook快速實現對Excel的匯入、匯出、資料校驗的文章,也是便於日後查閱。
1、引入依賴
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency>
2、Excel型別列舉
/** * @Description:Excel型別列舉 * @Author:zhangzhixiang * @CreateDate:2018/08/31 13:59:48 * @Version:1.0 */ @Data public enum ExcelTypeEnum { /** * 報備匯入 */ REPORT_TYPE(BatchImportConsts.EXCEL_REPORT_MODEL_TYPE, new BatchImportStruBO(BatchImportConsts.excel_report_titles, new ReportRecordCheck(), SpringHelper.getBeanByClass(ReportInsertServiceImpl.class))), /** * 線索匯入 */ CLUE_TYPE(BatchImportConsts.EXCEL_CLUE_MODEL_TYPE, new BatchImportStruBO(BatchImportConsts.excel_clue_titles, new ClueRecordCheck(), SpringHelper.getBeanByClass(ClueInsertServiceImpl.class))); private String type; private BatchImportStruBO struBO; ExcelTypeEnum(String type, BatchImportStruBO struBO) { this.type = type; this.struBO = struBO; } /** * 判斷key對應的列舉是否存在,若存在,返回此列舉;否則返回null * * @param key * @return */ public static ExcelTypeEnum containKey(String key) { ExcelTypeEnum type = null; switch (key) { case "report": type = ExcelTypeEnum.REPORT_TYPE; break; case "clue": type = ExcelTypeEnum.CLUE_TYPE; break; default: type = null; break; } return type; } }
3、批量匯入Excel資料結構
/** * @Description:批量匯入Excel資料結構資訊 * @Author:zhangzhixiang * @CreateDate:2018/09/05 19:54:32 * @Version:1.0 */ @Data public class BatchImportStruBO { /** * Excel欄位與db欄位關係 */ private List<BaseColumn> importTitles; /** * 記錄校驗器 */ private BaseRecordCheck recordCheck; /** * 入表處理器 */ private BaseInsertService insertHandle; public BatchImportStruBO(List<BaseColumn> importTitles, BaseRecordCheck recordCheck, BaseInsertService insertHandle) { this.importTitles = importTitles; this.recordCheck = recordCheck; this.insertHandle = insertHandle; } }
4、Excel單元格
/**
* @Description:Excel單元格實體
* @Author:zhangzhixaing
* @CreateDate:2018/08/31 16:39:45
* @Version:1.0
*/
@Data
public class BaseColumn {
/**
* 常量定義
*/
public static final Boolean TRUE = true;
public static final Boolean FALSE = false;
/**
* Excel中對應的欄位名稱
*/
protected String excelName;
/**
* Excel欄位值
*/
protected String excelValue;
/**
* 是否必填
*/
protected Boolean isRequired;
/**
* 值得校驗是否成功,預設true
*/
protected boolean checkIsSuccess = true;
/**
* 校驗結果資訊
*/
protected String checkMessage;
public BaseColumn() {
super();
}
public BaseColumn(String excelName, Boolean isRequired) {
super();
this.excelName = excelName;
this.isRequired = isRequired;
}
public BaseColumn(String excelName) {
super();
this.excelName = excelName;
}
}
5、 Excel匯入相關配置
/**
* Excel匯入相關配置
*
* @author zhangzhixiang
* @data 2018/09/18 11:48:59
*/
public class BatchImportConsts {
/**
* Excel匯入模式
*/
public static String EXCEL_CLUE_MODEL_TYPE = "clue";
public static String EXCEL_REPORT_MODEL_TYPE = "report";
/**
* 報備批量匯入Excel標題對映資訊
*/
public static List<BaseColumn> excel_report_titles;
/**
* 線索批量匯入Excel標題對映資訊
*/
public static List<BaseColumn> excel_clue_titles;
/**
* 報備匯入Excel標題
*/
public static final String EXCEL_REPORT_RECORD_COLUMN_PROVINCE = "省";
public static final String EXCEL_REPORT_RECORD_COLUMN_CITY = "市";
public static final String EXCEL_REPORT_RECORD_COLUMN_AREA = "區";
public static final String EXCEL_REPORT_RECORD_COLUMN_CUSTOMER_SOURCE = "客戶來源(單位名稱)";
public static final String EXCEL_REPORT_RECORD_COLUMN_ITEM = "專案歸屬";
public static final String EXCEL_REPORT_RECORD_COLUMN_DATA_CONTENT_DESC = "資料內容描述";
public static final String EXCEL_REPORT_RECORD_COLUMN_DATA_NUM = "資料數量";
public static final String EXCEL_REPORT_RECORD_COLUMN_DATA_PURPOSE = "資料用途";
/**
* 線索匯入Excel標題
*/
public static final String EXCEL_CLUE_RECORD_COLUMN_CLUE_SOURCE = "線索來源地";
public static final String EXCEL_CLUE_RECORD_COLUMN_ITEM = "歸屬專案";
public static final String EXCEL_CLUE_RECORD_COLUMN_TAG = "線索標籤";
public static final String EXCEL_CLUE_RECORD_COLUMN_NAME = "線索名稱";
public static final String EXCEL_CLUE_RECORD_COLUMN_DESC = "線索內容";
public static final String EXCEL_CLUE_RECORD_COLUMN_CLUE_REMARK = "線索備註";
public static final String EXCEL_CLUE_RECORD_COLUMN_PERSON_NUM = "人數";
public static final String EXCEL_CLUE_RECORD_COLUMN_PERSON_NAME = "姓名";
public static final String EXCEL_CLUE_RECORD_COLUMN_ID_CARD = "身份證號";
public static final String EXCEL_CLUE_RECORD_COLUMN_IPHONE = "手機號";
public static final String EXCEL_CLUE_RECORD_COLUMN_SEX = "性別";
public static final String EXCEL_CLUE_RECORD_COLUMN_NATION = "名族";
/**
* 報備配置(標題頭+是否必填)
*/
static {
excel_report_titles = new ArrayList<>();
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_PROVINCE, BaseColumn.TRUE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_CITY, BaseColumn.FALSE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_AREA, BaseColumn.FALSE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_CUSTOMER_SOURCE, BaseColumn.TRUE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_ITEM, BaseColumn.TRUE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_DATA_CONTENT_DESC, BaseColumn.TRUE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_DATA_NUM, BaseColumn.FALSE));
excel_report_titles.add(new BaseColumn(EXCEL_REPORT_RECORD_COLUMN_DATA_PURPOSE, BaseColumn.FALSE));
}
/**
* 線索配置(標題頭+是否必填)
*/
static {
excel_clue_titles = new ArrayList<>();
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_CLUE_SOURCE, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_ITEM, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_TAG, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_NAME, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_DESC, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_CLUE_REMARK, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_PERSON_NUM, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_PERSON_NAME, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_ID_CARD, BaseColumn.TRUE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_IPHONE, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_SEX, BaseColumn.FALSE));
excel_clue_titles.add(new BaseColumn(EXCEL_CLUE_RECORD_COLUMN_NATION, BaseColumn.FALSE));
}
}
6、行校驗介面
/**
* @Description:行校驗介面
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:56:32
* @Version:1.0
*/
public interface BaseRecordCheck {
/**
* 記錄校驗
*
* @param cells
* @return
* @throws Exception
*/
List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception;
}
7、線索行校驗實現
/**
* @Description:線索行校驗
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 12:59:48
* @Version:1.0
*/
public class ClueRecordCheck implements BaseRecordCheck {
@Override
public List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception {
//欄位校驗
for (BaseColumn column : cells) {
switch (column.getExcelName()) {
case BatchImportConsts.EXCEL_CLUE_RECORD_COLUMN_NAME:
new BaseCheck().valueCheck(column);
break;
case BatchImportConsts.EXCEL_CLUE_RECORD_COLUMN_ID_CARD:
new ClueIdcardCheck().valueCheck(column);
break;
case BatchImportConsts.EXCEL_CLUE_RECORD_COLUMN_IPHONE:
new CluePhoneCheck().valueCheck(column);
break;
case BatchImportCONsts.EXCEL_CLUE_RECORD_COLUMN_SEX:
new ClueSexCheck().valueCheck(column);
break;
default:
break;
}
}
return cells;
}
}
8、列校驗介面
/**
* @Description:列校驗介面
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:56:34
* @Version:1.0
*/
public interface BaseColumnCheck {
/**
* 校驗欄位值
*
* @param cell
* @return
* @throws Exception
*/
BaseColumn valueCheck(BaseColumn cell) throws Exception;
/**
* 多欄位聯合校驗
*
* @param cells
* @return
* @throws Exception
*/
List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception;
}
9、線索列校驗實現(基礎非空校驗)
/**
* @Description:基礎非空校驗
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class BaseCheck implements BaseColumnCheck {
private static final String EMPTY_MESSAGE = "不能為空;"
@Override
public BaseColumn valueCheck(BaseColumn cell) throws Exception {
if (StringUtils.isBlank(cell.getExcelValue())) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + EMPTY_MESSAGE);
} else {
cell.setCheckIsSuccess(true);
}
return cell;
}
@Override
public List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception {
return null;
}
}
10、線索列校驗實現(身份證號校驗)
/**
* @Description:身份證號校驗
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class ClueIdcardCheck implements BaseColumnCheck {
private static final String EMPTY_MESSAGE = "不能為空;"
private static final String WRONG_MESSAGE = "格式不對;"
@Override
public BaseColumn valueCheck(BaseColumn cell) throws Exception {
if(cell.getRequired() || (!cell.getRequired() && StringHelper,isNotBlankAnyWay(cell.getExcelValue()))) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + EMPTY_MESSAGE);
} else {
//校驗身份證號合法性
String reg = "^\\d{15}$|^\\d{17}[0-9Xx]$";
if(!cell.getExcelValue.matches(reg)) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + WRONG_MESSAGE);
}
}
return cell;
}
@Override
public List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception {
return null;
}
}
11、線索列校驗實現(手機號校驗)
/**
* @Description:手機號校驗
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class CluePhoneCheck implements BaseColumnCheck {
private static final String EMPTY_MESSAGE = "不能為空;"
private static final String WRONG_MESSAGE = "格式不對;"
private Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$");
@Override
public BaseColumn valueCheck(BaseColumn cell) throws Exception {
if(cell.getRequired() || (!cell.getRequired() && StringHelper,isNotBlankAnyWay(cell.getExcelValue()))) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + EMPTY_MESSAGE);
} else {
//校驗手機號合法性
Matcher m = p.matcher(cell.getExcelValue());
if(!m.matches()) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + WRONG_MESSAGE);
}
}
return cell;
}
@Override
public List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception {
return null;
}
}
12、線索列校驗實現(性別校驗)
/**
* @Description:性別校驗
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class ClueSexCheck implements BaseColumnCheck {
private static final String EMPTY_MESSAGE = "不能為空;"
private static final String WRONG_MESSAGE = "格式不對;"
private String man = "男";
private String women = "女";
@Override
public BaseColumn valueCheck(BaseColumn cell) throws Exception {
if(cell.getRequired() || (!cell.getRequired() && StringHelper,isNotBlankAnyWay(cell.getExcelValue()))) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage() == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + EMPTY_MESSAGE);
} else {
//校驗手機號合法性
Matcher m = p.matcher(cell.getExcelValue());
if(!m.matches()) {
if(!(man.equals(cell.getExcelValue()) || women.equals(cell.getExcelValue()))) {
cell.setCheckIsSuccess(false);
cell.setCheckMessage((cell.getCheckMessage == null ? "" : cell.getCheckMessage()) + cell.getExcelName() + WRONG_MESSAGE);
}
}
}
return cell;
}
@Override
public List<BaseColumn> valueCheck(List<BaseColumn> cells) throws Exception {
return null;
}
}
13、Excel入庫介面
/**
* @Description:Excel入庫介面
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public interface BaseInsertService {
/**
* Excel資料入庫
*
* @param rows Excle資料
* @param isSuccess
* @author zhangzhixiang
* @data 2018/09/19 18:56:43
*/
void insertDB(List<List<BaseColumn>> rows, Boolean isSuccess) throws Exception;
}
14、Excel入庫實現(線索)
/**
* @Description:Excel線索入庫介面
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
@Service
public class ClueInsertServiceImpl implements BaseInsertService {
@Autowired
public ClueInfoDAO clueInfoDAO;
@Override
@Transactional(rollbackFor = Exception.class)
public void insertDB(List<List<BaseColumn>> rows, Boolean isSuccess) throws Exception {
//線索自定義入庫程式碼
}
}
15、Excel公共服務介面(OSS)
/**
* @Description:Excel服務介面(OSS)
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public interface ExcelOperateService {
/**
* Excel檔案匯入
* @param fileName 原檔名
* @param code 檔案唯一標示
* @param model Excel型別標識
* @return 解析結果
* @throws Exception
*/
ExcelParseResultBO excelImport(String code, String model) throws Exception;
/**
* Excel檔案匯出
* @param fileName 原檔名
* @param code 檔案唯一標示
* @param model Excel型別標識
* @return 解析結果
* @throws Exception
*/
void excelExport(HttpServletResponse response, List<List<String>> rows, String fileName, String sheetName) throws Exception;
}
16、Excel公共服務實現(OSS)
/**
* @Description:Excel公共服務實現(OSS)
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
@Service
public class ExcelOperateServiceImpl implements ExcelOperateService {
private static final Logger logger = LoggerFactory.getLogger(ExcelOperateServiceImpl.class);
private static final String SERVICE_ERROR_MESSAGE = "批量匯入失敗";
/**
* Excel檔案匯入
*
* @param code OSS檔案唯一標示
* @param model 業務型別(clue、report)
* @return 解析結果
* @throws Exception
*/
@Override
public ExcelOperateBO excelImport(String code, String model) {
FileClient client = ClientFactory.createClientByType(BootstrapConsts.file_client_type);
ExcelOperateBO resultBO = null;
//1、獲取Excel資料
List<List<String>> excelDatas = null;
excelDatas = ExcelRead.getSheetDataWithTitle(client.getFileStream(code), code, null);
if(null == excelDatas || excelDatas.size() < SimpleConsts.TWO) {
message = "檔案無有效資料";
resultBO = new ExcelOperateBO();
resultBO.setFileOK(false);
resultBO.setMessage(message);
return resultVO;
}
logger.info("記錄數量:" + excelDatas.size());
//2、校驗標題合法性
resultBO = excelTitleCheck(excelDatas.get(0), model);
if(!resultBO.getFileOK) {
return resultBO;
}
//3、將Excel中的每列資料與title名稱繫結
List<List<BaseColumn>> excelRows = null;
excelRows = getExcelData(excelDatas, model);
if(null == excelRows || excelRows.size() == 0) {
resultBO = new ExcelOperateBO();
resultBO.setTotalNum(0);
resultBO.setSuccessNum(0);
resultBO.setFailNum(0);
resultBO.setFileOK(true);
return resultVO;
}
//4、Excel資料校驗
List<List<BaseColumn>> successRows = new ArrayList<>();
List<List<BaseColumn>> failRows = new ArrayList<>();
rowsCheck(excelRows, model, successRows, failRows);
//5、入庫
if(successRows.size() > 0) {
insertdb(successRows, model, true);
}
if(failRows.size() > 0) {
insertdb(failRows, model, false);
}
}
/**
* Excel檔案匯出
*
* @param response
* @param rows 匯出檔案內容(包括標題)
* @param fileName 匯出檔名
* @param sheetName sheet名稱
* @return 解析結果
* @throws Exception
*/
@Override
public void excelExport(HttpServletResponse response, List<List<String>> rows, String fileName, String sheetName) throws Exception {
ExcelWrite.exportExcle(response, rows, fileName, sheetName);
}
/**
* 資料入庫
*
* @param rows 待寫入的資料
* @param model 業務型別(clue、report)
* @param isSuccess 是否成功
*/
private void insertdb(List<List<BaseColumn>> rows, String model, Boolean isSuccess) throws Exception {
BatchImportStruBO struBO = ExcelTypeEnum.containKey(model).getStruBO();
BaseInsertService insertHandle = struBO.getInsertHandle();
insertHandle.insertDB(rows, isSuccess);
}
/**
* Excek資料校驗
*
* @param excelRows 待校驗資料
* @param model 業務型別(clue、report)
* @param successRows 校驗成功的資料
* @param failRows 校驗失敗的資料
*/
private void rowsCheck(List<List<BaseColumn>> rows, String model, List<List<BaseColumn>> successRows, List<List<BaseColumn>> failRows) throws Exception {
BaseRecordCheck recordCheck = ExcelTypeEnum.containKey(model).getStruBO().getRecordCheck();
List<BaseCOlumn> checkedRow = null;
boolean isSuccessCheck = true;
for (List<BaseColumn> rowData : excelRows) {
checkedRow = recordCheck.valueCheck(rowData);
if(checkedRow == null || checkedRow.size() == 0) {
continue;
}
for (BaseColumn cell : checkedRow) {
if (!cell.isCheckIsSuccess()) {
isSuccessCheck = cell.isCheckIsSuccess();
break;
}
}
if(!isSuccessCheck) {
failRows.add(checkRow);
} else {
successRows.add(checkedRow);
}
isSuccessCheck = true;
}
}
/**
* 獲取Excel有效資料(將title與Excel資料繫結)
*
* @param excelRows Excel資料
* @return
* @throws Exception
*/
private List<List<BaseColumn>> getExcelData(List<List<String>> excelDatas, String model) throws Exception {
BatchImportStruBO batchImportStruBO = ExcelTypeEnum.containKey(model).getStruBO();
List<BaseColumn> titles = batchImportStruBO.getImportTitles();
excelDatas.remove(0);
for(int i = 0; i<excelDatas.size(); i++) {
List<String> row = valueTrim(excelDatas.get(i));
excelDatas.set(i, row);
}
List<List<BaseColumn>> excelRows = excelDataTidy(titles, excelDatas);
if (null == excelRows) {
throw new Exception("excelDatas資料轉為excelRows資料報錯");
}
return excelRows;
}
/**
* 將標題和具體的資料組合
*
* @param titles 標題資訊
* @param rowList 記錄資料,其中記錄的欄位索引與對應的標題索引一致
* @return
*/
private List<List<BaseColumn>> excelDataTidy(List<BaseColumn> titles, List<List<String>> rowList) {
List<List<BaseColumn>> datas = new ArrayList<>();
List<BaseColumn> rowData = null;
BaseColumn cellData = null;
List<String> excelRow = null;
for(int i = 0; i < rowList.size(); i++) {
rowData = new ArrayList<>();
excelRow = rowList.get(i);
for(int j = 0; j < excelRow.size(); j++) {
String excelCellValue = excelRow.get(j);
String title = null;
if(j < titles.size()) {
title = titles.get(j).getExcelName();
} else {
break;
}
cellData = new BaseColumn();
cellData.setExcelName(title);
cellData.setRequired(titles.get(j).getRequired());
cellData.setExcelValue(excelCellValue);
rowData.add(cellData);
}
datas.add(rowData);
}
return datas;
}
/**
* 校驗標題是否合規
*
* @param titles 標題資訊
* @param model 業務型別(clue、report)
* @return
*/
private ExcelOperateBO excelTitleCheck(List<String> titles, String model) throws Exception {
BatchImprtStruBO batchImportStruBO = ExcelTypeEnum.containKey(model).getStruBO();
String message = "解析標題報錯";
titles = valueTrim(titles);
List<BaseColumn> orderTitles = batchImportStruBO.getImportTitles();
boolean titleCheck = titleCheck(titles, orderTitles);
if (!titleCheck) {
throw new Exception(message);
}
ExcelOperateBO resultBO= new ExcelOperateBO();
resultBO.setFileOK(true);
return resultBO;
}
/**
* 校驗Excel中標題是否包含所需要的標題
*
* @param titles 標題資訊
* @param orderTitles 要求的標題資訊
* @return
*/
private boolean titleCheck(List<String> titles, List<BaseColumn> orderTitles) {
if (null == titles || titles.size() == 0) {
return false;
}
if(null == orderTitles || orderTitles.size() == 0) {
return false;
}
List<String> names = new ArrayList<>();
for (BaseColumn column : orderTitles) {
names.add(column.getExcelName());
}
for (String name : names) {
if(!titles.contains(name)) {
return false;
}
}
return true;
}
/**
* 去除首尾無效空格
*
* @param values 要去空格的字串
* @return
*/
private List<String> valueTrim(List<String> values) {
if(null == values || values.size() == 0) {
return values;
}
for(int i=0; i < values.size(); i++) {
if(StringUtils.isBlank(values.get(i))) {
values.set(i, null);
continue;
} else {
values.set(i, values.get(i).trim());
}
}
return values;
}
}
17、Excel基礎操作
/**
* @Description:Excel基礎操作
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class ExcelBaseOperate {
pricate static final Logger logger = LoggerFactory.getLogger(ExcelBaseOperate.class);
private static final String SUFFIX_XLS = "xls";
private static final String SUFFIX_XLSX = "xlsx";
/**
* 獲取Excel操作類
*
* @param inputStream
* @param name
* @return
* @throws Exception
*/
public static Workbook getWorkbook(InputStream inputStream, String name) throws Exception {
Workbook wb = null;
if (name.endsWith(SUFFIX_XLSX)) {
wb = new XSSWorkbook(OPCPackage.open(inputStream));
} else if (name.endsWith(SUFFIX_XLS)) {
wb = (HSSFWorkbook)WorkbookFactory.create(inputStream);
} else {
String errorMessage = "無法識別的檔案型別。檔名稱:" + name;
logger.error(errorMessage);
throw new Exception(errorMessage);
}
return wb;
}
}
18、Excel讀取操作
/**
* @Description:Excel讀取操作
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class ExcelRead {
private static final Logger logger = LoggerFactory.getLogger(ExcelRead.class);
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 獲取sheet頁標題
*
* @param inputStream Excel檔案流
* @param excelName Excel檔名
* @param sheetName sheet頁名稱。不輸入則預設取第一個sheet
* @return
*/
public static List<String> getSheetTitle(InputStream inputStream, String excelName, String sheetName) throws Exception {
Workbook workbook = ExcelBaseOperate.getWorkbook(inputStream, excelName);
//沒有輸入sheetname,則預設第一個sheet
if (StringUtils.isBlank(sheetName)) {
sheetName = workbook.getSheetAt(0).getSheetName();
}
List<List<String>> sheetData = parseSheet(workbook, sheetName, 0, 0);
if(null == sheetData || sheetData.size() == 0) {
return null;
}
return sheetData.get(0);
}
/**
* 獲取帶標題的sheet頁資料
*
* @param inputStream Excel檔案流
* @param excelName Excel檔名
* @param sheetName sheet頁名稱。不輸入則預設取第一個sheet
* @return
*/
public static List<String> getSheetTitle(InputStream inputStream, String excelName, String sheetName) throws Exception {
Workbook workbook = ExcelBaseOperate.getWorkbook(inputStream, excelName);
//沒有輸入sheetname,則預設第一個sheet
if (StringUtils.isBlank(sheetName)) {
sheetName = workbook.getSheetAt(0).getSheetName();
}
List<List<String>> sheetData = parseSheet(workbook, sheetName, 0, workbook.getSheet(sheetName).getPhysicalNumberOfRows());
return sheetData;
}
/**
* 解析sheet頁資料
*
* @param wb Excel檔案
* @param sheetName sheet頁名稱
* @param startIndex 解析的起始row,從0開始,包含此row
* @param endIndex 解析的終止row,從0開始,包含此row
* @return 第一層list:row;第二層list:cell
*/
private static List<List<String>> parseSheet(Workbook wb, String sheetName, int start
Index, int endIndex) throws Exception {
String message = null;
Sheet sheet = wb.getSheet(sheetName);
if(null == sheet) {
message = sheetName + ",此sheet頁不存在";
throw new Exception(message);
}
int lastRowNum = sheet.getPhysicalNumberOfRows();
if(startIndex < 0 || endIndex > lastRowNum || startIndex > endIndex) {
message = "輸入的解析row範圍錯誤。startIndex:" + startIndex + ",endIndex:" + endIndex;
throw new Exception(message);
}
List<List<String>> sheetData = new ArrayList<>();
int cellCount = -1;
//row list
for (int i = startIndex; i < endIndex; i++) {
Row row = sheet.getRow(i);
if(null == row) {
continue;
}
List<String> rowData = new ArrayList<>();
cellCount = row.getLastCellNum();
//cell list
for(int j = 0; j < cellCount; j++) {
Cell cell = row.getCell(j);
if(null == cell) {
rowData.add(null);
continue;
}
rowData.add(getCellValue(cell));
}
sheetData.add(rowData);
}
return sheetData;
}
/**
* 獲取cell值
*
* @param cell
* @return
*/
private static String getCellValue(Cell cell) {
CellType type = cell.getCellTypeEnum();
String value = null;
if(CellType.NUMERIC.equals(type)) {
if(DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
value = sdf.format(date);
} else {
cell.setCellType(CellType.STRING);
value = String.valueOf(cell.getStringCellValue());
}
} else if(CellType.BOOLEAN.equals(type)) {
value = String.valueOf(cell.getBooleanCellValue());
} else if(CellType.BLANK.equals(type)) {
value = null;
} else {
value = String.valueOf(cell.getStringCellValue());
}
return value;
}
}
19、Excel寫入操作
/**
* @Description:Excel讀取操作
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 21:59:43
* @Version:1.0
*/
public class ExcelWrite {
private static final Logger logger = LoggerFactory.getLogger(ExcelWrite.class);
public static final String SUFFIX = "xlsx";
/**
* 匯出Excel
*
* @param
* @return void
* @author zhangzhixiang
* @data 2018/09/10 13:59:43
*/
public static void exportExcel(HttpServletResponse response, List<List<String>> rows, String fileName, String sheetName) {
Workbook workbook = createWb();
try(OutputStream out = response.getOutputStream()) {
Sheet sheet = workbook.createSheet(sheetName);
sheetAppendData(rows, sheet);
response.setContentType("application/ms-excel;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
workbook.write(out);
} catch(Exception e) {
logger.error("ExcelWrite--exportExcel throw Exception.fileName:{}", fileName, e);
}
}
/**
* 生成Excel檔案流
*
* @param rows
* @param name
* @return java.io.ByteArrayOutputStream
* @author zhangzhixiang
* @date 2018/09/10 20:54:46
*/
public static ByteArrayOutputStream writeData(List<List<String>> rows, String name) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Workbook workbook = createWb();
Sheet sheet= workbook.createSheet(name);
sheetAppendData(rows, sheet);
try {
workbook.write(out);
out.flush();
return out;
} catch(Exception e) {
logger.error("ExcelWrite-->writeData throw Exception.name:{}.", name, e);
return null;
}
}
/**
* sheet頁填充資料
*
* @param rows
* @param sheet
* @return org.apache.poi.ss.usermodel.Sheet
* @author zhangzhixiang
* @date 2018/09/10 10:59:48
*/
public static Sheet sheetAppendData(List<List<String>> rows, Sheet sheet) {
int lastRowNum = sheet.getPhysicalNumberOfRows();
if(null == rows || rows.size == 0) {
return sheet;
}
Row row = null;
if(List<String> rowData : rows) {
row = sheet.creatRow(lastRowNum);
rowCreateData(rowData, row);
lastRowNum = lastRowNum + 1;
}
return sheet;
}
/**
* 生成row
*
* @param datas
* @param row
* @return org.apache.poi.ss.usermodel.Row
* @author zhangzhixiang
* @date 2018/09/10 20:35:46
*/
private static Row rowCreateData(List<String> datas, Row row) {
Cell cell = null;
for(int i = 0; i < datas.size(); i++) {
cell = row.createCell(i);
cell.setCellType(CellType.STRING);
cell.setCellValue(datas.get(i));
}
return row;
}
/**
* 建立workbook
*
* @param
* @return org.apache.poi.ss.usermodel.Workbook
* @author zhangzhixiang
* @date 2018/09/10 20:35:42
*/
public static Workbook createWb() {
Workbook wb = null;
if(SimpleConsts.EXCEL_EXT.equals(SUFFIX)) {
wb = new XSSFWorkbook();
} else {
wb = new HSSFWorkbook();
}
return wb;
}
}
20、常量類定義
/**
* @Description:簡單常亮定義
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 11:34:56
* @Version:1.0
*/
public class SimpleConsts {
public static final String EXCEL_EXT = "xlsx";
}
21、controller層
/**
* @Description:公共服務介面-controller
* @Author:zhangzhixiang
* @CreateDate:2018/08/31 11:34:56
* @Version:1.0
*/
@RestController
@RequestMapping("/api/ops/common")
public class CommonController extends ExceptionHandlerAdvice {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private ExcelOperateService excelOperateService;
@RequestMapping(value = "/excelImport", method = RequestMethod.POST)
public ResponseResult excelImport(@RequestBody ExcelImportBO excelImportBO) throw Exception {
Boolean flag = paramCheckModule(excelImportBO.getModule());
ExcelOperateResultBO data = excelOperateService.excelImport(excelImportBO.getCode());
return new ResponseResult().setSuccess(true).setData(data).setMessage(ResultCode.SUCCESS.getMessage);
}
@RequestMapping(value = "/excelExport", method = RequestMethod.GET)
public void excelImport(@RequestBody List<List<String>> rows, String fileName, String sheetName, HttpServletResponse response) throw Exception {
excelOperateService.excelExport(response, rows, fileName, sheetName);
}
private boolean paramCheckModule(String module) throws Exception {
ExcelTypeEnum type = ExcelTypeEnum.containKey(module);
if(null == type) {
logger.error("********************No specified module was found.module:{}**********************", module);
return false;
}
return true;
}
}
全篇文章完全純手打,如果覺得對您有幫助,記得加關注給好評喲~~