Java接收解析excel方法及注意事項說明
前言
提示:本文著重講解java如何處理excel:
例如:本文從java接收excel,解析excel,以及業(yè)務(wù)場景中基于阻塞隊列處理大批量的Excel。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、Java接收Excel
示例:pandas 是基于NumPy 的一種工具,該工具是為了解決數(shù)據(jù)分析任務(wù)而創(chuàng)建的。
1.引入庫
pom如下:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.21</version>
</dependency>2.Controller層代碼
提示: 本文MultipartFile接收,請求方式為form表單提交
/**
* 傳入excel
*
* @return
*/
@PostMapping(value = "/inputExcel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation("傳入excel")
public R inputExcel(@RequestPart("file") MultipartFile file) {
InputExcelDTO inputExcelDTO = new InputExcelDTO();
inputExcelDTO.setFile(file);
if (Objects.isNull(inputExcelDTO.getExcelName()) || Objects.isNull(inputExcelDTO.getFile())) {
return R.failed("必填參數(shù)不可為空");
}
return excelService.inputExcel(inputExcelDTO);
}
二、解析excel
1.將MultipartFile 轉(zhuǎn) File作為臨時文件存儲在本地,解析
代碼如下:
工具類 :
package com.byt.form.convert.util;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author: author
* @date: 2021/8/27 8:46
* @description: excel處理工具類
*/
public class ExcelDealUtils {
/**
* MultipartFile 轉(zhuǎn) File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
//獲取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 刪除本地臨時文件
*
* @param file
*/
public static void deleteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
/**
* 處理數(shù)據(jù)
*
* @param str
* @return
*/
public static String getDelDay(String str) {
str = str.trim();
String reg = "[\u4e00-\u9fa5]";
Pattern pat = Pattern.compile(reg);
Matcher mat = pat.matcher(str);
String repickStr = mat.replaceAll("");
return repickStr;
}
}
ServiceImpl實現(xiàn)層
File excel= ExcelDealUtils.multipartFileToFile(inputExcelDTO.getFile());
try {
//excel最后修改時間
String excelTime = modTime;
if (excel.isFile() && excel.exists()) { //判斷文件是否存在
String[] split = excel.getName().split("\\."); //特殊字符轉(zhuǎn)義
Workbook wb;
//根據(jù)文件后綴(xls/xlsx)進行判斷
if ("xls".equals(split[split.length - 1])) {
FileInputStream fis = new FileInputStream(excel); //文件流對象
wb = new HSSFWorkbook(fis);
fis.close();
} else if (("xlsx".equals(split[split.length - 1]))) {
ZipSecureFile.setMinInflateRatio(-1.0d);
FileInputStream fis = new FileInputStream(excel);
wb = new XSSFWorkbook(fis);
fis.close();
} else {
log.info("文件類型錯誤");
return;
}
JSONArray data = new JSONArray();
if (sheet == null) {
return;
}
log.info("處理sheet為{}", sheet.getSheetName());
int firstRowIndex = sheet.getFirstRowNum(); //第一行是列名ABC...字母,所以不讀
int lastRowIndex = sheet.getLastRowNum();
for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { //遍歷行
JSONArray rowArray = new JSONArray();
Row row = sheet.getRow(rIndex);
if (row != null) { //這里只保存了不為空的行
int firstCellIndex = row.getFirstCellNum();
int lastCellIndex = row.getLastCellNum();
for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) { //遍歷列
Cell cell = row.getCell(cIndex);
if (cell != null) {
rowArray.add(getCellFormatValue(cell));
} else {
rowArray.add("");
}
}
}
if (rowArray.size() > 5) {
data.add(rowArray);
}
}
//data為二維數(shù)組,順序與excel一致
wb.close();
} else {
log.info("找不到指定文件");
}
} catch (Exception e) {
log.info("解析錯誤 報表id為{},錯誤日志為{}", excelId, e);
}
/**
* 處理公式數(shù)據(jù),如果是公式直接讀值,excel日期解析到的是數(shù)字,需要轉(zhuǎn)換成日期
*根據(jù)項目情況處理
* @param cell
* @return
*/
public static Object getCellFormatValue(Cell cell) {
Object cellValue = null;
if (cell != null) {
//判斷cell類型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: {
cell.setCellType(Cell.CELL_TYPE_STRING); //數(shù)字型特殊處理,使獲取的整型不帶有小數(shù)點
cellValue = cell.getRichStringCellValue().getString();
// cellValue = String.valueOf(cell.getNumericCellValue());
break;
}
case Cell.CELL_TYPE_FORMULA: {
//非法字符處理
try {
cellValue = cell.getStringCellValue();
} catch (Exception e) {
//特殊處理
}
try {
cellValue = String.valueOf(cell.getNumericCellValue());
} catch (Exception e) {
}
break;
}
case Cell.CELL_TYPE_STRING: {
cellValue = cell.getRichStringCellValue().getString();
break;
}
default:
cellValue = "";
}
} else {
cellValue = "";
}
return cellValue;
}
2.大批量的excel同時丟上來容易內(nèi)存溢出,故用阻塞隊列處理
全局參數(shù):
// 能容納100個文件
final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
// 讀個數(shù)
final AtomicInteger rc = new AtomicInteger();
// final File exitFile = new File("");
HashMap<String, DelFileBO> fileMap = new HashMap<>();
存入阻塞隊列:
/**
*存入阻塞隊列
*/
private void (File file){
//存入Map,主要是為了避免線程同時處理多個,所以用map記錄
fileMap.put(delFile.getName(), file);
//放入阻塞隊列
scanFile(delFile);
}
public void scanFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory()
|| pathname.getPath().endsWith(".java");
}
});
for (File one : files)
scanFile(one);
} else {
try {
int index = rc.incrementAndGet();
queue.put(file);
} catch (InterruptedException e) {
}
}
}
起一個線程從隊列拿數(shù)據(jù)處理
@PostConstruct
public void delExcelFile() {
taskExecutor.execute(() -> {
while (true) {
this.delFile();
}
});
}
public void delFile() {
try {
//從隊列拿文件處理
File file = queue.take();
//業(yè)務(wù)邏輯
} catch (InterruptedException e) {
}
}
總結(jié)
以上就是今天要講的內(nèi)容,本文僅僅簡單介紹了java如何解析excel,針對自身業(yè)務(wù)也可以維護一些其余配置,如報表id以及處理方式等。
這些僅為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之整合Swagger2到通用模塊
這篇文章主要為大家介紹了實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之整合Swagger2到通用模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04
springboot與vue實現(xiàn)簡單的CURD過程詳析
這篇文章主要介紹了springboot與vue實現(xiàn)簡單的CURD過程詳析,圍繞springboot與vue的相關(guān)資料展開實現(xiàn)CURD過程的過程介紹,需要的小伙伴可以參考一下2022-01-01
Mybatis-plus查詢語句加括號(.or(),.and())問題
這篇文章主要介紹了Mybatis-plus查詢語句加括號(.or(),.and())問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
解決springboot configuration processor對maven子模塊不起作用的問題
這篇文章主要介紹了解決springboot configuration processor對maven子模塊不起作用的問題,本文通過圖文實例代碼給大家講解的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09

