最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java基于POI實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出

 更新時間:2026年02月12日 08:29:58   作者:J_liaty  
Apache POI是Apache軟件基金會提供的開源Java API,用于處理Microsoft Office格式文件,比EasyExcel、Hutool等封裝框架,原始POI提供了最底層的控制能力,適合需要高度定制化的場景,本文給大家介紹了Java基于POI實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出,需要的朋友可以參考下

1. 引言

Apache POI(Poor Obfuscation Implementation)是Apache軟件基金會提供的開源Java API,用于處理Microsoft Office格式文件。其中HSSF處理Excel 97-2003(.xls)格式,XSSF處理Excel 2007+(.xlsx)格式,SXSSF則用于處理大數(shù)據(jù)量的流式寫入。

Excel操作在企業(yè)開發(fā)中的核心應(yīng)用場景:

  • 數(shù)據(jù)報表導(dǎo)出(銷售數(shù)據(jù)、財務(wù)報表、用戶列表等)
  • 批量數(shù)據(jù)導(dǎo)入(商品信息、員工檔案、訂單數(shù)據(jù)等)
  • 數(shù)據(jù)統(tǒng)計分析后的結(jié)果呈現(xiàn)
  • 系統(tǒng)間的數(shù)據(jù)交換與備份

相比EasyExcel、Hutool等封裝框架,原始POI提供了最底層的控制能力,適合需要高度定制化的場景。

2. 環(huán)境準(zhǔn)備

2.1 Maven依賴配置

<dependencies>
    <!-- POI核心依賴 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    
    <!-- 處理.xlsx格式 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    
    <!-- 可選:處理日期工具 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.4</version>
    </dependency>
</dependencies>

版本說明:

  • 建議使用5.x版本,4.x版本存在內(nèi)存泄漏問題
  • 如需支持.xls格式,poi依賴必不可少
  • poi-ooxml包含.xmlbeans和ooxml-security等傳遞依賴

2.2 環(huán)境要求

組件最低版本推薦版本
JDK1.811+
POI3.175.2.3+
Maven3.6+3.8+

3. Excel導(dǎo)出實現(xiàn)

3.1 創(chuàng)建工作簿結(jié)構(gòu)

/**
 * 創(chuàng)建Excel工作簿基礎(chǔ)結(jié)構(gòu)
 */
public static Workbook createWorkbook() {
    // 創(chuàng)建.xlsx格式工作簿
    Workbook workbook = new XSSFWorkbook();
    return workbook;
}

/**
 * 創(chuàng)建工作表并設(shè)置標(biāo)題
 */
public static Sheet createSheet(Workbook workbook, String sheetName) {
    Sheet sheet = workbook.createSheet(sheetName);
    // 設(shè)置列寬(以字符寬度為單位,256為一個字符寬度)
    sheet.setColumnWidth(0, 20 * 256);  // A列寬度為20個字符
    sheet.setColumnWidth(1, 15 * 256);  // B列寬度為15個字符
    return sheet;
}

/**
 * 創(chuàng)建標(biāo)題行
 */
public static Row createHeaderRow(Sheet sheet, String[] headers) {
    Row row = sheet.createRow(0);
    for (int i = 0; i < headers.length; i++) {
        Cell cell = row.createCell(i);
        cell.setCellValue(headers[i]);
    }
    return row;
}

3.2 單元格樣式設(shè)置

/**
 * 創(chuàng)建標(biāo)題樣式(居中、加粗、背景色)
 */
public static CellStyle createHeaderStyle(Workbook workbook) {
    CellStyle style = workbook.createCellStyle();
    
    // 水平居中
    style.setAlignment(HorizontalAlignment.CENTER);
    // 垂直居中
    style.setVerticalAlignment(VerticalAlignment.CENTER);
    
    // 設(shè)置字體
    Font font = workbook.createFont();
    font.setFontName("微軟雅黑");
    font.setFontHeightInPoints((short) 12);
    font.setBold(true);
    style.setFont(font);
    
    // 設(shè)置背景色(淡藍色)
    style.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
    style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    
    // 設(shè)置邊框
    style.setBorderTop(BorderStyle.THIN);
    style.setBorderBottom(BorderStyle.THIN);
    style.setBorderLeft(BorderStyle.THIN);
    style.setBorderRight(BorderStyle.THIN);
    
    return style;
}

/**
 * 創(chuàng)建數(shù)據(jù)樣式(左對齊、自動換行)
 */
public static CellStyle createDataStyle(Workbook workbook) {
    CellStyle style = workbook.createCellStyle();
    
    style.setAlignment(HorizontalAlignment.LEFT);
    style.setVerticalAlignment(VerticalAlignment.CENTER);
    style.setWrapText(true);  // 自動換行
    
    // 設(shè)置邊框
    style.setBorderTop(BorderStyle.THIN);
    style.setBorderBottom(BorderStyle.THIN);
    style.setBorderLeft(BorderStyle.THIN);
    style.setBorderRight(BorderStyle.THIN);
    
    return style;
}

/**
 * 創(chuàng)建數(shù)字格式樣式(保留兩位小數(shù))
 */
public static CellStyle createNumberStyle(Workbook workbook) {
    CellStyle style = workbook.createCellStyle();
    style.setAlignment(HorizontalAlignment.RIGHT);
    
    // 創(chuàng)建數(shù)字格式
    DataFormat format = workbook.createDataFormat();
    style.setDataFormat(format.getFormat("#,##0.00"));
    
    style.setBorderTop(BorderStyle.THIN);
    style.setBorderBottom(BorderStyle.THIN);
    style.setBorderLeft(BorderStyle.THIN);
    style.setBorderRight(BorderStyle.THIN);
    
    return style;
}

3.3 處理不同數(shù)據(jù)類型

/**
 * 設(shè)置單元格值(支持多種數(shù)據(jù)類型)
 */
public static void setCellValue(Cell cell, Object value) {
    if (value == null) {
        cell.setCellValue("");
        return;
    }
    
    if (value instanceof String) {
        cell.setCellValue((String) value);
    } else if (value instanceof Number) {
        cell.setCellValue(((Number) value).doubleValue());
    } else if (value instanceof Date) {
        cell.setCellValue((Date) value);
    } else if (value instanceof Boolean) {
        cell.setCellValue((Boolean) value);
    } else if (value instanceof Calendar) {
        cell.setCellValue((Calendar) value);
    } else {
        cell.setCellValue(value.toString());
    }
}

/**
 * 設(shè)置日期格式單元格
 */
public static void setDateCellValue(Cell cell, Date date, Workbook workbook) {
    CellStyle dateStyle = workbook.createCellStyle();
    DataFormat format = workbook.createDataFormat();
    dateStyle.setDataFormat(format.getFormat("yyyy年mm月dd日"));
    
    cell.setCellStyle(dateStyle);
    cell.setCellValue(date);
}

3.4 響應(yīng)輸出流處理

/**
 * 導(dǎo)出Excel到HTTP響應(yīng)
 * @param response HttpServletResponse對象
 * @param workbook Excel工作簿
 * @param fileName 導(dǎo)出文件名
 */
public static void exportExcel(HttpServletResponse response, 
                               Workbook workbook, 
                               String fileName) throws IOException {
    // 設(shè)置響應(yīng)頭
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("UTF-8");
    
    // 處理文件名編碼(防止中文亂碼)
    String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
            .replaceAll("\\+", "%20");
    response.setHeader("Content-Disposition", 
                      "attachment;filename*=UTF-8''" + encodedFileName + ".xlsx");
    
    // 寫入輸出流
    try (OutputStream out = response.getOutputStream()) {
        workbook.write(out);
        out.flush();
    } finally {
        // 關(guān)閉工作簿釋放資源
        if (workbook != null) {
            workbook.close();
        }
    }
}

4. Excel導(dǎo)入實現(xiàn)

4.1 文件上傳與輸入流處理

/**
 * 從MultipartFile讀取Excel文件
 * @param file Spring MVC上傳的文件
 * @return Excel工作簿對象
 */
public static Workbook readExcel(MultipartFile file) throws IOException {
    String fileName = file.getOriginalFilename();
    InputStream inputStream = file.getInputStream();
    
    // 根據(jù)文件后綴判斷版本
    if (fileName.endsWith(".xlsx")) {
        return new XSSFWorkbook(inputStream);
    } else if (fileName.endsWith(".xls")) {
        return new HSSFWorkbook(inputStream);
    } else {
        throw new IllegalArgumentException("不支持的文件格式,僅支持.xlsx和.xls");
    }
}

4.2 工作表讀取與數(shù)據(jù)解析

/**
 * 讀取工作表數(shù)據(jù)(默認讀取第一個工作表)
 */
public static List<List<String>> readSheetData(Sheet sheet) {
    List<List<String>> dataList = new ArrayList<>();
    
    // 從第一行開始讀?。ㄌ^標(biāo)題行可從1開始)
    for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
        Row row = sheet.getRow(rowIndex);
        if (row == null) continue;
        
        List<String> rowData = new ArrayList<>();
        // 遍歷該行的所有單元格
        for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
            Cell cell = row.getCell(cellIndex);
            String cellValue = getCellValueAsString(cell);
            rowData.add(cellValue);
        }
        dataList.add(rowData);
    }
    
    return dataList;
}

4.3 單元格數(shù)據(jù)類型轉(zhuǎn)換

/**
 * 獲取單元格字符串值(處理各種數(shù)據(jù)類型)
 */
public static String getCellValueAsString(Cell cell) {
    if (cell == null) {
        return "";
    }
    
    // 根據(jù)單元格類型進行轉(zhuǎn)換
    switch (cell.getCellType()) {
        case STRING:
            return cell.getStringCellValue().trim();
            
        case NUMERIC:
            // 判斷是否為日期類型
            if (DateUtil.isCellDateFormatted(cell)) {
                Date date = cell.getDateCellValue();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                return sdf.format(date);
            } else {
                // 避免科學(xué)計數(shù)法和精度丟失
                DecimalFormat df = new DecimalFormat("0");
                return df.format(cell.getNumericCellValue());
            }
            
        case BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue());
            
        case FORMULA:
            // 處理公式單元格
            try {
                return String.valueOf(cell.getNumericCellValue());
            } catch (IllegalStateException e) {
                return cell.getStringCellValue();
            }
            
        case BLANK:
            return "";
            
        default:
            return "";
    }
}

/**
 * 獲取指定類型的單元格值
 */
public static <T> T getCellValue(Cell cell, Class<T> clazz) {
    if (cell == null) return null;
    
    if (clazz == String.class) {
        return clazz.cast(getCellValueAsString(cell));
    } else if (clazz == Integer.class || clazz == int.class) {
        return clazz.cast((int) cell.getNumericCellValue());
    } else if (clazz == Long.class || clazz == long.class) {
        return clazz.cast((long) cell.getNumericCellValue());
    } else if (clazz == Double.class || clazz == double.class) {
        return clazz.cast(cell.getNumericCellValue());
    } else if (clazz == Boolean.class || clazz == boolean.class) {
        return clazz.cast(cell.getBooleanCellValue());
    } else if (clazz == Date.class) {
        return clazz.cast(cell.getDateCellValue());
    }
    
    return null;
}

4.4 異常處理與數(shù)據(jù)驗證

/**
 * 導(dǎo)入時進行數(shù)據(jù)驗證
 */
public static class ValidationResult {
    private boolean valid;
    private String errorMessage;
    private int rowIndex;
    private int columnIndex;
    
    // 構(gòu)造方法、getter和setter省略...
}

/**
 * 驗證導(dǎo)入數(shù)據(jù)
 */
public static ValidationResult validateCell(Cell cell, String fieldName, 
                                           boolean required, 
                                           int max_length) {
    ValidationResult result = new ValidationResult();
    result.setValid(true);
    
    String value = getCellValueAsString(cell);
    
    // 必填驗證
    if (required && (value == null || value.isEmpty())) {
        result.setValid(false);
        result.setErrorMessage(fieldName + "不能為空");
        return result;
    }
    
    // 長度驗證
    if (max_length > 0 && value.length() > max_length) {
        result.setValid(false);
        result.setErrorMessage(fieldName + "長度不能超過" + max_length + "個字符");
        return result;
    }
    
    // 其他業(yè)務(wù)驗證邏輯...
    
    return result;
}

/**
 * 導(dǎo)入Excel并驗證數(shù)據(jù)
 */
public static List<ValidationResult> importExcelWithValidation(
        MultipartFile file, 
        boolean skipHeader) throws IOException {
    
    Workbook workbook = readExcel(file);
    Sheet sheet = workbook.getSheetAt(0);
    List<ValidationResult> errors = new ArrayList<>();
    
    int startRow = skipHeader ? 1 : 0;
    for (int i = startRow; i <= sheet.getLastRowNum(); i++) {
        Row row = sheet.getRow(i);
        if (row == null) continue;
        
        // 示例:驗證第一列(姓名)
        Cell nameCell = row.getCell(0);
        ValidationResult result = validateCell(nameCell, "姓名", true, 50);
        if (!result.isValid()) {
            result.setRowIndex(i + 1);
            result.setColumnIndex(1);
            errors.add(result);
        }
        
        // 驗證第二列(年齡)
        Cell ageCell = row.getCell(1);
        if (ageCell != null) {
            try {
                int age = (int) ageCell.getNumericCellValue();
                if (age < 0 || age > 150) {
                    ValidationResult ageError = new ValidationResult();
                    ageError.setValid(false);
                    ageError.setErrorMessage("年齡必須在0-150之間");
                    ageError.setRowIndex(i + 1);
                    ageError.setColumnIndex(2);
                    errors.add(ageError);
                }
            } catch (Exception e) {
                ValidationResult ageError = new ValidationResult();
                ageError.setValid(false);
                ageError.setErrorMessage("年齡必須是數(shù)字");
                ageError.setRowIndex(i + 1);
                ageError.setColumnIndex(2);
                errors.add(ageError);
            }
        }
    }
    
    workbook.close();
    return errors;
}

5. 完整示例代碼

5.1 Excel導(dǎo)出工具類

package com.example.excel.util;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
 * Excel導(dǎo)出工具類
 */
public class ExcelExportUtil {
    
    /**
     * 導(dǎo)出數(shù)據(jù)到Excel
     * @param headers 表頭數(shù)組
     * @param dataList 數(shù)據(jù)列表(每行數(shù)據(jù)為List<Object>)
     * @param fileName 文件名
     * @param sheetName 工作表名
     */
    public static void exportData(HttpServletResponse response,
                                   String[] headers,
                                   List<List<Object>> dataList,
                                   String fileName,
                                   String sheetName) throws IOException {
        
        // 創(chuàng)建工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(sheetName);
        
        // 創(chuàng)建樣式
        CellStyle headerStyle = createHeaderStyle(workbook);
        CellStyle dataStyle = createDataStyle(workbook);
        CellStyle numberStyle = createNumberStyle(workbook);
        
        // 創(chuàng)建標(biāo)題行
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
        
        // 填充數(shù)據(jù)
        for (int i = 0; i < dataList.size(); i++) {
            Row row = sheet.createRow(i + 1);
            List<Object> rowData = dataList.get(i);
            
            for (int j = 0; j < rowData.size(); j++) {
                Cell cell = row.createCell(j);
                Object value = rowData.get(j);
                
                // 根據(jù)數(shù)據(jù)類型設(shè)置樣式和值
                if (value == null) {
                    cell.setCellValue("");
                    cell.setCellStyle(dataStyle);
                } else if (value instanceof Number) {
                    cell.setCellValue(((Number) value).doubleValue());
                    cell.setCellStyle(numberStyle);
                } else if (value instanceof Date) {
                    CellStyle dateStyle = workbook.createCellStyle();
                    DataFormat format = workbook.createDataFormat();
                    dateStyle.setDataFormat(format.getFormat("yyyy-MM-dd"));
                    dateStyle.setAlignment(HorizontalAlignment.CENTER);
                    dateStyle.setBorderTop(BorderStyle.THIN);
                    dateStyle.setBorderBottom(BorderStyle.THIN);
                    dateStyle.setBorderLeft(BorderStyle.THIN);
                    dateStyle.setBorderRight(BorderStyle.THIN);
                    cell.setCellStyle(dateStyle);
                    cell.setCellValue((Date) value);
                } else {
                    cell.setCellValue(value.toString());
                    cell.setCellStyle(dataStyle);
                }
            }
        }
        
        // 自動調(diào)整列寬
        autoSizeColumns(sheet, headers.length);
        
        // 導(dǎo)出文件
        exportExcel(response, workbook, fileName);
    }
    
    /**
     * 自動調(diào)整列寬
     */
    private static void autoSizeColumns(Sheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            // 設(shè)置最小列寬,防止過窄
            if (sheet.getColumnWidth(i) < 15 * 256) {
                sheet.setColumnWidth(i, 15 * 256);
            }
            // 設(shè)置最大列寬,防止過寬
            if (sheet.getColumnWidth(i) > 50 * 256) {
                sheet.setColumnWidth(i, 50 * 256);
            }
        }
    }
    
    /**
     * 創(chuàng)建標(biāo)題樣式
     */
    public static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        
        Font font = workbook.createFont();
        font.setFontName("微軟雅黑");
        font.setFontHeightInPoints((short) 12);
        font.setBold(true);
        style.setFont(font);
        
        style.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        
        return style;
    }
    
    /**
     * 創(chuàng)建數(shù)據(jù)樣式
     */
    public static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setWrapText(true);
        
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        
        return style;
    }
    
    /**
     * 創(chuàng)建數(shù)字格式樣式
     */
    public static CellStyle createNumberStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.RIGHT);
        
        DataFormat format = workbook.createDataFormat();
        style.setDataFormat(format.getFormat("#,##0.00"));
        
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        
        return style;
    }
    
    /**
     * 導(dǎo)出Excel到HTTP響應(yīng)
     */
    public static void exportExcel(HttpServletResponse response, 
                                   Workbook workbook, String fileName) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");
        
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                .replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", 
                          "attachment;filename*=UTF-8''" + encodedFileName + ".xlsx");
        
        try (OutputStream out = response.getOutputStream()) {
            workbook.write(out);
            out.flush();
        } finally {
            if (workbook != null) {
                workbook.close();
            }
        }
    }
}

5.2 Excel導(dǎo)入工具類

package com.example.excel.util;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Excel導(dǎo)入工具類
 */
public class ExcelImportUtil {
    
    /**
     * 導(dǎo)入Excel文件并返回數(shù)據(jù)
     * @param file 上傳的Excel文件
     * @param skipHeader 是否跳過標(biāo)題行
     * @return 數(shù)據(jù)列表(每行數(shù)據(jù)為List<String>)
     */
    public static List<List<String>> importExcel(MultipartFile file, boolean skipHeader) 
            throws IOException {
        
        Workbook workbook = readExcel(file);
        Sheet sheet = workbook.getSheetAt(0);
        List<List<String>> dataList = new ArrayList<>();
        
        int startRow = skipHeader ? 1 : 0;
        for (int i = startRow; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row == null) continue;
            
            List<String> rowData = new ArrayList<>();
            for (int j = 0; j < row.getLastCellNum(); j++) {
                Cell cell = row.getCell(j);
                String value = getCellValueAsString(cell);
                rowData.add(value);
            }
            dataList.add(rowData);
        }
        
        workbook.close();
        return dataList;
    }
    
    /**
     * 讀取Excel文件
     */
    public static Workbook readExcel(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        InputStream inputStream = file.getInputStream();
        
        if (fileName.endsWith(".xlsx")) {
            return new XSSFWorkbook(inputStream);
        } else if (fileName.endsWith(".xls")) {
            return new HSSFWorkbook(inputStream);
        } else {
            throw new IllegalArgumentException("不支持的文件格式");
        }
    }
    
    /**
     * 獲取單元格字符串值
     */
    public static String getCellValueAsString(Cell cell) {
        if (cell == null) return "";
        
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue().trim();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    return sdf.format(date);
                } else {
                    java.text.DecimalFormat df = new java.text.DecimalFormat("0");
                    return df.format(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return String.valueOf(cell.getNumericCellValue());
                } catch (IllegalStateException e) {
                    return cell.getStringCellValue();
                }
            case BLANK:
                return "";
            default:
                return "";
        }
    }
}

5.3 Controller使用示例

package com.example.excel.controller;

import com.example.excel.util.ExcelExportUtil;
import com.example.excel.util.ExcelImportUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel操作Controller示例
 */
@RestController
@RequestMapping("/excel")
public class ExcelController {
    
    /**
     * 導(dǎo)出示例
     */
    @GetMapping("/export")
    public void exportUserList(HttpServletResponse response) throws IOException {
        // 準(zhǔn)備表頭
        String[] headers = {"用戶ID", "用戶名", "年齡", "注冊日期", "狀態(tài)"};
        
        // 準(zhǔn)備數(shù)據(jù)
        List<List<Object>> dataList = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            List<Object> row = new ArrayList<>();
            row.add(i);
            row.add("用戶" + i);
            row.add(20 + i);
            row.add(new java.util.Date());
            row.add(i % 2 == 0 ? "啟用" : "禁用");
            dataList.add(row);
        }
        
        // 導(dǎo)出
        ExcelExportUtil.exportData(response, headers, dataList, 
                                   "用戶列表", "用戶數(shù)據(jù)");
    }
    
    /**
     * 導(dǎo)入示例
     */
    @PostMapping("/import")
    public String importUserList(@RequestParam("file") MultipartFile file) {
        try {
            List<List<String>> dataList = ExcelImportUtil.importExcel(file, true);
            
            // 處理導(dǎo)入數(shù)據(jù)
            for (List<String> row : dataList) {
                System.out.println("導(dǎo)入數(shù)據(jù):" + row);
                // 數(shù)據(jù)庫操作...
            }
            
            return "導(dǎo)入成功,共導(dǎo)入" + dataList.size() + "條數(shù)據(jù)";
        } catch (IOException e) {
            e.printStackTrace();
            return "導(dǎo)入失敗:" + e.getMessage();
        }
    }
}

6. 常見問題與解決方案

6.1 大文件內(nèi)存溢出問題

問題解決方案實現(xiàn)方式
大文件OOM使用SXSSF流式寫入new SXSSFWorkbook(rowAccessWindowSize)
大文件讀取使用事件模型XSSF and SAX (Event API)
樣式過多復(fù)用樣式對象避免為每個單元格創(chuàng)建新樣式

SXSSF流式寫入示例:

// 設(shè)置內(nèi)存中保留100行,超過后寫入臨時文件
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
Sheet sheet = workbook.createSheet("大數(shù)據(jù)導(dǎo)出");

// 寫入數(shù)據(jù)...
for (int i = 0; i < 100000; i++) {
    Row row = sheet.createRow(i);
    // ...
}

// 清理臨時文件
workbook.dispose();

6.2 數(shù)字精度丟失問題

// 錯誤寫法:可能丟失精度
double value = cell.getNumericCellValue();

// 正確寫法:使用BigDecimal
BigDecimal decimal = new BigDecimal(cell.getNumericCellValue())
    .setScale(2, RoundingMode.HALF_UP);

6.3 日期格式問題

// 判斷單元格是否為日期格式
if (DateUtil.isCellDateFormatted(cell)) {
    Date date = cell.getDateCellValue();
    // 處理日期...
} else {
    // 處理數(shù)字...
}

6.4 文件名亂碼問題

// 完整的文件名編碼處理
String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
        .replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", 
                   "attachment;filename*=UTF-8''" + encodedFileName + ".xlsx");

6.5 版本兼容性

// 動態(tài)判斷文件版本
Workbook workbook = null;
String fileName = file.getOriginalFilename();

if (fileName.endsWith(".xlsx")) {
    workbook = new XSSFWorkbook(inputStream);
} else if (fileName.endsWith(".xls")) {
    workbook = new HSSFWorkbook(inputStream);
} else {
    throw new IllegalArgumentException("不支持的文件格式");
}

7. 總結(jié)與擴展

7.1 框架對比

特性Apache POIEasyExcelHutool
學(xué)習(xí)成本
性能一般優(yōu)秀一般
內(nèi)存占用較高較高
功能完整性豐富基礎(chǔ)較全
定制化能力中等

選擇建議:

  • 需要高度定制化樣式和功能 → Apache POI
  • 處理百萬級大數(shù)據(jù)量 → EasyExcel
  • 快速開發(fā)、簡單場景 → Hutool

7.2 性能優(yōu)化要點

  1. 樣式復(fù)用:避免為每個單元格創(chuàng)建新樣式,全局創(chuàng)建并復(fù)用
  2. 流式處理:大數(shù)據(jù)場景使用SXSSF
  3. 批量操作:減少頻繁的IO操作
  4. 及時釋放:使用try-with-resources確保資源釋放

7.3 實際應(yīng)用場景

  • 報表系統(tǒng):銷售報表、財務(wù)報表、數(shù)據(jù)分析結(jié)果導(dǎo)出
  • 數(shù)據(jù)遷移:系統(tǒng)間數(shù)據(jù)交換、歷史數(shù)據(jù)導(dǎo)入
  • 后臺管理:用戶列表、商品管理、訂單導(dǎo)出
  • 數(shù)據(jù)分析:業(yè)務(wù)數(shù)據(jù)統(tǒng)計、趨勢分析報告

7.4 擴展建議

  1. 結(jié)合注解:基于注解實現(xiàn)自動映射(如Excel導(dǎo)入直接轉(zhuǎn)為實體對象)
  2. 異步處理:大文件導(dǎo)出采用異步+通知機制
  3. 模板導(dǎo)出:基于預(yù)先設(shè)計好的Excel模板進行數(shù)據(jù)填充
  4. 多Sheet處理:復(fù)雜報表使用多Sheet組織數(shù)據(jù)

總結(jié):Apache POI提供了完整的Excel處理能力,雖然API相對復(fù)雜,但在需要精細控制和高度定制化的場景下仍是不二之選。通過合理封裝和優(yōu)化,可以構(gòu)建穩(wěn)定高效的Excel處理工具。

以上就是Java基于POI實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出的詳細內(nèi)容,更多關(guān)于Java POI實現(xiàn)Excel導(dǎo)入導(dǎo)出的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot整合redis進行數(shù)據(jù)操作(推薦)

    springboot整合redis進行數(shù)據(jù)操作(推薦)

    springboot整合redis比較簡單,并且使用redistemplate可以讓我們更加方便的對數(shù)據(jù)進行操作。下面通過本文給大家分享springboot整合redis進行數(shù)據(jù)操作的相關(guān)知識,感興趣的朋友一起看看吧
    2017-10-10
  • Java流程控制語句有哪些舉例詳解

    Java流程控制語句有哪些舉例詳解

    這篇文章主要介紹了Java流程控制語句有哪些的相關(guān)資料,包括順序執(zhí)行、分支控制(if/else、switch)及循環(huán)控制(for/while/do-while),需要的朋友可以參考下
    2025-06-06
  • java中ArrayList和LinkedList的區(qū)別詳解

    java中ArrayList和LinkedList的區(qū)別詳解

    這篇文章主要介紹了java中ArrayList和LinkedList的區(qū)別詳解,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-01-01
  • SpringBoot整合Swagger2的步驟詳解

    SpringBoot整合Swagger2的步驟詳解

    這篇文章主要介紹了SpringBoot整合Swagger2的步驟詳解,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot框架,感興趣的朋友可以了解下
    2021-04-04
  • Java通過stmp協(xié)議發(fā)送郵件

    Java通過stmp協(xié)議發(fā)送郵件

    這篇文章主要為大家詳細介紹了Java通過stmp協(xié)議發(fā)送郵件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 淺談Java安全之C3P0的使用

    淺談Java安全之C3P0的使用

    本文主要介紹了淺談Java安全之C3P0的使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java多線程、線程安全、線程池創(chuàng)建方式

    Java多線程、線程安全、線程池創(chuàng)建方式

    本文詳細介紹了多線程的基本概念、創(chuàng)建方式、常用方法、線程安全問題解決以及線程池的使用,通過具體案例和代碼示例,幫助讀者理解多線程在Java中的應(yīng)用和實現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • 一篇文章帶你入門java工廠模式

    一篇文章帶你入門java工廠模式

    這篇文章主要介紹了Java工廠模式,結(jié)合實例形式詳細分析了java基本數(shù)據(jù)類型、數(shù)據(jù)類型轉(zhuǎn)換、算術(shù)運算符、邏輯運算符等相關(guān)原理與操作技巧,需要的朋友可以參考下
    2021-08-08
  • 詳解Spring事件發(fā)布與監(jiān)聽機制

    詳解Spring事件發(fā)布與監(jiān)聽機制

    Spring提供了ApplicationContext事件機制,可以發(fā)布和監(jiān)聽事件,這個特性非常有用。Spring內(nèi)置了一些事件和監(jiān)聽器,例如在Spring容器啟動前,Spring容器啟動后,應(yīng)用啟動失敗后等事件發(fā)生后,監(jiān)聽在這些事件上的監(jiān)聽器會做出相應(yīng)的響應(yīng)處理
    2021-06-06
  • springboot循環(huán)依賴問題案例代碼及解決辦法

    springboot循環(huán)依賴問題案例代碼及解決辦法

    在 Spring Boot 中,如果兩個或多個 Bean之間存在循環(huán)依賴(即 Bean A 依賴 Bean B,而 Bean B 又依賴 Bean A),會導(dǎo)致 Spring 的依賴注入機制無法正確處理,從而拋出異常,下面給大家介紹springboot循環(huán)依賴問題及其解決辦法,感興趣的朋友一起看看吧
    2025-04-04

最新評論

太谷县| 赫章县| 拉萨市| 江陵县| 通辽市| 太谷县| 红安县| 汾西县| 宜君县| 淮南市| 嘉兴市| 讷河市| 灯塔市| 航空| 黑河市| 永福县| 鞍山市| 康马县| 泸定县| 确山县| 夏河县| 晋江市| 金阳县| 花莲县| 通海县| 金寨县| 崇阳县| 沾益县| 诏安县| 开原市| 额济纳旗| 胶州市| 西藏| 封开县| 新宾| 婺源县| 牡丹江市| 朔州市| 高清| 白朗县| 内丘县|