一、首先配置相關maven包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
二、解析處理大數據Excel文件XLSX2CSV.java類
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.util.CellAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* @author
* @date 2019-09-24 17:43
* @description 讀取文件操作
*/
public class XLSX2CSV {
/**
* Uses the XSSF Event SAX helpers to do most of the work
* of parsing the Sheet XML, and outputs the contents
* as a (basic) CSV.
*/
private class SheetToCSV implements SheetContentsHandler {
private boolean firstCellOfRow = false;
private int currentRow = -1;
private int currentCol = -1;
private void outputMissingRows(int number) {
for (int i = 0; i < number; i++) {
curStr = new ArrayList<String>();
for (int j = 0; j < minColumns; j++) {
curStr.add(null);
}
output.add(curStr);
}
}
@Override
public void startRow(int rowNum) {
curStr = new ArrayList<String>();
// If there were gaps, output the missing rows
outputMissingRows(rowNum - currentRow - 1);
// Prepare for this row
firstCellOfRow = true;
currentRow = rowNum;
currentCol = -1;
}
@Override
public void endRow(int rowNum) {
// Ensure the minimum number of columns
for (int i = currentCol; i < minColumns ; i++) {
curStr.add(null);
}
output.add(curStr);
}
@Override
public void cell(String cellReference, String formattedValue,
XSSFComment comment) {
// gracefully handle missing CellRef here in a similar way as XSSFCell does
if (cellReference == null) {
cellReference = new CellAddress(currentRow, currentCol).formatAsString();
}
// Did we miss any cells?
int thisCol = (new CellReference(cellReference)).getCol();
int missedCols = thisCol - currentCol - 1;
for (int i = 0; i < missedCols; i++) {
curStr.add(null);
}
currentCol = thisCol;
// Number or string?
try {
Double.parseDouble(formattedValue);
curStr.add(formattedValue);
} catch (NumberFormatException e) {
// output.append('"');
curStr.add(formattedValue);
// output.append('"');
}
}
@Override
public void headerFooter(String text, boolean isHeader, String tagName) {
// Skip, no headers or footers in CSV
}
}
private final OPCPackage xlsxPackage;
/**
* Number of columns to read starting with leftmost
*/
private final int minColumns;
/**
* Destination for data
*/
private ArrayList<ArrayList<String>> output;
private ArrayList<String> curStr;
public ArrayList<ArrayList<String>> getOutput(){
return output;
}
/**
* Creates a new XLSX -> CSV converter
* @param pkg The XLSX package to process
* @param minColumns The minimum number of columns to output, or -1 for no minimum
*/
public XLSX2CSV(OPCPackage pkg, int minColumns) {
this.xlsxPackage = pkg;
this.minColumns = minColumns;
}
/**
* Parses and shows the content of one sheet
* using the specified styles and shared-strings tables.
*
* @param styles
* @param strings
* @param sheetInputStream
*/
public void processSheet(
StylesTable styles,
ReadOnlySharedStringsTable strings,
SheetContentsHandler sheetHandler,
InputStream sheetInputStream)
throws ParserConfigurationException, SAXException {
DataFormatter formatter = new DataFormatter();
InputSource sheetSource = new InputSource(sheetInputStream);
try {
XMLReader sheetParser = SAXHelper.newXMLReader();
ContentHandler handler = new XSSFSheetXMLHandler(
styles, null, strings, sheetHandler, formatter, false);
sheetParser.setContentHandler(handler);
sheetParser.parse(sheetSource);
} catch (ParserConfigurationException e) {
throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
} catch (IOException io) {
io.printStackTrace();
}
}
/**
* Initiates the processing of the XLS workbook file to CSV.
*/
public ArrayList<ArrayList<String>> process(String sheetName) {
try{
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
StylesTable styles = xssfReader.getStylesTable();
XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
while (iter.hasNext()) {
output = new ArrayList<ArrayList<String>> ();
InputStream stream = iter.next();
if(iter.getSheetName().equals(sheetName)){
processSheet(styles, strings, new SheetToCSV(), stream);
close(stream);
return output;
}
close(stream);
continue;
}
} catch (OpenXML4JException open) {
open.printStackTrace();
} catch (ParserConfigurationException parser) {
parser.printStackTrace();
} catch (SAXException sax) {
sax.printStackTrace();
} catch (IOException io) {
io.printStackTrace();
}
return null;
}
private void close(InputStream stream){
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
File xlsxFile = new File("F:\\files\\test.xlsx");
if (!xlsxFile.exists()) {
System.err.println("Not found or not a file: " + xlsxFile.getPath());
return;
}
// The package open is instantaneous, as it should be.
OPCPackage p = null;
try {
p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ);
} catch (InvalidFormatException e) {
e.printStackTrace();
}
String[] array = {"序號","名稱","年齡","性別","班級"};
XLSX2CSV xlsx2csv = new XLSX2CSV(p, array.length);
xlsx2csv.process("測試");
ArrayList<ArrayList<String>> data = xlsx2csv.getOutput();
if (!checkFormat(data.get(0),array)) {
System.out.println("文檔標題格式不正確!");
}
try {
p.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 校驗excel表頭是否符合規範
* @param list
* @param array
* @return
*/
private static boolean checkFormat(ArrayList<String> list,String[] array){
if (list == null || array == null) {
return false;
}
String[] data = list.toArray(new String[list.size()]);
for(int i = 0; i < array.length; i++){
if (!data[i].equals(array[i])) {
return false;
}
}
return true;
}
}
三、數據庫配置表excel_sheet,主要根據配置讀取excel文檔指定sheet頁,根據配置獲取對應列的數據插入到數據庫表中
表中數據sort可排序,讀取時使用該值-1 相當於該列在excel文檔的sheet頁中屬於第幾列,使用required字段值判斷是否需要該列的數據插入數據庫
四、根據數據庫配置表獲取excel數據的寫法
/**
* 讀取EXCEL數據併入庫
*/
public void addExcel() throws Exception {
//本地文件讀取
String fileName = "E:\\文檔\\測試數據v1.0.xlsx";
File file = new File(fileName);
// 通過前端傳輸MultipartFile文件流處理方式
// OPCPackage p = OPCPackage.open(file.getInputStream());
OPCPackage p = OPCPackage.open(file);
List<ExcelVo> excels = excelSheetMapper.getExcelSheet("CSCES", null);
List<Map> list = new ArrayList<>();
for (int i = 0; i < excels.size(); i++) {
String sheetName = excels.get(i).getSheetName();
int minColumns = excels.get(i).getColumns().size();
XLSX2CSV xlsx2csv = new XLSX2CSV(p, minColumns);
ArrayList<ArrayList<String>> data = xlsx2csv.process(sheetName);
List<Map> array = readArray(data, excelSheetVos);
list.addAll(array);
}
}
if (list != null && list.size() > 0) {
excelSheetMapper.updateTestData(list);
}
}
private List<Map> readArray(ArrayList<ArrayList<String>> data,
List<ExcelSheetVo> columns) {
List<Map> list = new ArrayList<>();
for (int i = 1; i < data.size(); i++) {
Map map = new HashMap();
ArrayList<String> strings = data.get(i);
for (int j = 0; j < columns.size(); j++) {
ExcelSheetVo sheet = columns.get(j);
if (sheet.getRequired() == 1) {
int index = sheet.getSort() - 1;
if (StringUtils.isNotBlank(strings.get(index))) {
String str = strings.get(index);
// 避免導出數據超出11位數的數字會變成科學計數格式,導入時需去除導出時加上的英文單引號
if (str.contains("'")) {
str = str.replaceAll("'","");
}
map.put(sheet.getFieldName(), str);
}
}
}
list.add(map);
}
return list;
}
相關實體類ExcelVo、ExcelSheetVo
import java.io.Serializable;
import java.util.List;
/**
* @author
* @date 2019-10-16 15:58
* @description
*/
public class ExcelVo implements Serializable {
private static final long serialVersionUID = -4962244768998499760L;
private String typeName;
private String sheetName;
private List<ExcelSheetVo> columns;
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public List<ExcelSheetVo> getColumns() {
return columns;
}
public void setColumns(List<ExcelSheetVo> columns) {
this.columns = columns;
}
}
import java.io.Serializable;
/**
* @author
* @date 2019-10-16 15:59
* @description
*/
public class ExcelSheetVo implements Serializable {
private static final long serialVersionUID = 708244119811817461L;
private String fieldName;
private String fieldValue;
private int sort;
private int required;
private int editable;
private String defaultValue;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldValue() {
return fieldValue;
}
public void setFieldValue(String fieldValue) {
this.fieldValue = fieldValue;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public int getRequired() {
return required;
}
public void setRequired(int required) {
this.required = required;
}
public int getEditable() {
return editable;
}
public void setEditable(int editable) {
this.editable = editable;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
}
Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tool.mapper.ExcelSheetMapper">
<select id="getExcelSheet" resultMap="getSheetMap">
SELECT
type_name AS typeName,sheet_name AS sheetName
FROM excel_config
<where>
is_deleted = 0
<if test="typeName != null and typeName != ''">
AND type_name = #{typeName}
</if>
<if test="sheetName != null and sheetName != ''">
AND sheet_name = #{sheetName}
</if>
</where>
GROUP BY type_name,sheet_name
</select>
<resultMap id="getSheetMap" type="com.tool.vo.ExcelVo">
<collection property="columns" javaType="ArrayList"
column="{typeName=typeName,sheetName=sheetName}"
ofType="com.tool.vo.ExcelSheetVo" select="getColumnList"/>
</resultMap>
<select id="getColumnList" resultType="com.tool.vo.ExcelSheetVo">
SELECT
field_name,field_value,sort,required,editable,default_value
FROM excel_config
<where>
is_deleted = 0
<if test="typeName != null and typeName != ''">
AND type_name = #{typeName}
</if>
<if test="sheetName != null and sheetName != ''">
AND sheet_name = #{sheetName}
</if>
</where>
ORDER BY sort
</select>
<updateid="updateTestData">
INSERT INTO test_data (
id,user_id,user_name,age,email,
create_user,create_time,update_user,update_time,is_deleted
)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},#{item.user_id},#{item.user_name},#{item.age},
#{item.email},#{item.create_user},#{item.create_time},#{item.update_user},
#{item.update_time},#{item.is_deleted}
)
</foreach>
ON DUPLICATE KEY UPDATE
user_id= VALUES(user_id),
user_name= VALUES(user_name),
age= VALUES(age),
update_time= VALUES(update_time),
is_deleted= VALUES(is_deleted)
</update>
<select id="getExportData" resultType="java.util.Map">
SELECT
id,user_id,user_name,age,email,
create_user,create_time,update_user,update_time,is_deleted
FROM test_data
where is_deleted = 0
</select>
</mapper>
JSON轉換成bean工具類
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* @author
* @date 2019-09-24 17:43
* @description
*/
public class JSONUtils {
/**
* bean對象轉換成JSON字符串
* @param object
* @return
*/
public static String beanToJson(Object object) {
try{
if (object != null) {
return JSON.toJSONString(object);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* JSON字符串轉換成bean對象
* @param json
* @param clazz
* @return
*/
public static <T> T jsonToBean(String json, Class<T> clazz) {
try{
if (StringUtils.isNotBlank(json) && clazz != null) {
return JSON.parseObject(json, clazz);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* List轉換成JSON字符串
* @param clazz
* @param <T>
* @return
*/
public static <T> String listToJson(List<T> clazz) {
try {
return JSON.toJSONString(clazz);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* JSON字符串轉換成List
* @param json
* @param clazz
* @param <T>
* @return
*/
public static <T> List<T> jsonToList(String json, Class<T> clazz) {
try {
if (StringUtils.isNotBlank(json) && clazz != null) {
return JSON.parseArray(json, clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
導出數據操作,讀取數據寫入excel
public void exportExcel(TestDto testDto, HttpServletResponse response) {
try{
List<ExcelVo> excelSheet = getExcelSheet("test","測試文檔");
List<ExcelSheetVo> columns = excelSheet.get(0).getColumns();
List<Map> data = excelSheetMapper.getExportData(testDto);
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFCellStyle lock = workbook.createCellStyle();
lock.setLocked(true); // 設置單元格鎖定
lock.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充單元格
lock.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 設置顏色
XSSFCellStyle unLock = workbook.createCellStyle();
unLock.setLocked(false); // 設置單元格未鎖定
// 設置單元格爲文本格式
XSSFCellStyle cellStyle = workbook.createCellStyle();
XSSFDataFormat dataFormat = workbook.createDataFormat();
cellStyle.setDataFormat(dataFormat.getFormat("@"));
XSSFSheet sheet = workbook.createSheet(excelSheet.get(0).getSheetName());
for (int i = 0; i <= data.size(); i++) {
XSSFRow row = sheet.createRow((short) i);// 生成行操作對象
for (int j = 0; j < columns.size(); j++) {
XSSFCell cell = row.createCell((short) j); // 列操作對象
cell.setCellStyle(cellStyle);
cell.setCellType(CellType.STRING);// 表格輸入數據類型
if (i == 0) {
cell.setCellValue(columns.get(j).getFieldValue());
} else {
writeExcel(j, cell, data.get(i-1), columns,lock, unLock);
}
}
}
// 設置自適應寬度,只適用於數字
for (int k = 0; k < columns.size(); k++) {
sheet.autoSizeColumn(k);
}
// 處理中文不能自動調整列寬的問題
setSizeColumn(sheet, columns.size());
// 鎖定指定單元格必須加上這句,不然不生效
sheet.protectSheet("123456");
ExportExcelUtils.exportExcel(workbook,excelSheet.get(0).getSheetName(),response);
} catch (Exception e) {
e.printStackTrace();
}
}
private void writeExcel(int index, XSSFCell cell, Map map,List<ExcelSheetVo> columns,
XSSFCellStyle lock,XSSFCellStyle unLock){
for(int i = 0; i < columns.size(); i++){
ExcelSheetVo sheetVo = columns.get(i);
if (index == (sheetVo.getSort() - 1)) {
setCellValue(sheetVo.getFieldName(), map, cell, sheetVo.getDefaultValue());
if (sheetVo.getEditable() == 0) {
cell.setCellStyle(lock);
} else {
cell.setCellStyle(unLock);
}
break;
}
}
}
private void setCellValue(String key, Map map, XSSFCell cell,String defaultValue){
if (map.containsKey(key)) {
Object value = map.get(key);
if (value == null || StringUtils.isBlank(value.toString())) {
cell.setCellValue(defaultValue);
return;
}
if (value instanceof String) {
cell.setCellValue(String.valueOf(value));
} else if (value instanceof Integer) {
// 由於excel超出11位數的數字會變成科學計數格式,加上英文單引號纔可正確顯示,避免導入時數據有誤
cell.setCellValue("'"+value.toString()+"");
} else if (value instanceof BigDecimal) {
BigDecimal decimal = new BigDecimal(value.toString());
cell.setCellValue(decimal.toString());
} else if (value instanceof java.sql.Date
|| value instanceof Timestamp) {
cell.setCellValue(value.toString());
} else {
cell.setCellValue("");
}
} else {
cell.setCellValue("");
}
}
private void setSizeColumn(XSSFSheet sheet, int size) {
for (int columnNum = 0; columnNum < size; columnNum++) {
int columnWidth = sheet.getColumnWidth(columnNum) / 256;
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
XSSFRow currentRow;
// 當前行未被使用過
if (sheet.getRow(rowNum) == null) {
currentRow = sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(columnNum) != null) {
XSSFCell currentCell = currentRow.getCell(columnNum);
if (currentCell.getCellType() == CellType.STRING) {
int length = currentCell.getStringCellValue().getBytes().length;
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
sheet.setColumnWidth(columnNum, columnWidth * 256);
}
}
根據瀏覽器導出excel文件工具類
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
/**
* @author
* @date 2019-09-03 20:52
* @description 導出Excel數據操作工具類
*/
public class ExportExcelUtils {
public static void exportExcel(XSSFWorkbook workbook, String fileName,
HttpServletResponse response){
OutputStream out = null;
try{
out = response.getOutputStream();
// 設置contentType爲excel格式
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet");
response.setHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
workbook.write(out);
response.flushBuffer();
out.flush();
}catch (Exception io) {
io.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}