Java使用poi讀取excel數據轉換成csv再讀取,通過數據庫配置信息導入導出數據

一、首先配置相關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();
            }
        }

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章