Springboot利用poi導出excel下載


demo中用的是反射,因為我覺得這樣代碼能簡潔一些,而且這樣也可以動態導出指定列到Excel。不過我看網上很多文章都是存入一個List中,不知道這兩種數據量大時候哪種更何合適一點,主要是性能方面,或者大佬們有什么更好的方法也請賜教。

pom

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.13</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.13</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Service

import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
@Service
public class StudentService {

    public List<Student> getList(Student student, int index, int size) {
        Student student1 = new Student("張三", 90, 18);
        Student student2 = new Student("李四", 85, 17);
        Student student3 = new Student("王五", 70, 19);
        List<Student> list = new ArrayList<>();
        list.add(student1);
        list.add(student2);
        list.add(student3);
        return list;
    }
}

Student Bean

import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
@Data
public class Student {
    public String name;
    public Integer score;
    public Integer age;
}

Controller

import lombok.Cleanup;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

@RestController
public class StudentController {

    @Autowired
    public StudentService studentService;

    @RequestMapping("/exportStudentExcel")
    public ResponseEntity<byte[]> exportExcel(Student student) {

        // 每次只需要改這幾行,也可做成Controller參數傳入

        List<Student> list = studentService.getList(student, 0, 10); 

        String fileName = "學生成績統計表";
        String[] getters = {"getName", "getScore", "getAge"};
        String[] headers = {"姓名", "分數", "年齡"};

        Workbook wb = ExcelUtils.createWorkBook(list, getters, headers,student.getClass());

        // 每次只需要改這幾行 end

        @Cleanup ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            wb.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] content = os.toByteArray();
        HttpHeaders httpHeaders = new HttpHeaders();
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        httpHeaders.setContentDispositionFormData("attachment", fileName + ".xlsx");
        return new ResponseEntity<byte[]>(content, httpHeaders, HttpStatus.OK);
    }
}

ExcelUtils

public class ExcelUtils {
    /**
     * 創建excel文檔
     *
     * @param getters list中map的key數組集合
     * @param headers excel的列名
     */
    public static Workbook createWorkBook(List list, String[] getters, String[] headers, Class clazz) {

        List<Method> methods = getMethodsByStrs(getters, clazz);

        // 創建.xlsx工作簿
        Workbook wb = new XSSFWorkbook();
        // 創建第一個sheet(頁),並命名
        Sheet sheet = wb.createSheet("sheet1");
        // 手動設置列寬.第一個參數表示要為第幾列設,第二個參數表示列的寬度,n為列高的像素數.

        for (int i = 0; i < getters.length; i++) {
            sheet.setColumnWidth((short) i, (short) (35.7 * 200));
        }

        // 創建第一行
        Row header = sheet.createRow(0);

        // 創建兩種單元格格式
        CellStyle cellStyle1 = wb.createCellStyle();
        CellStyle cellStyle2 = wb.createCellStyle();

        // 創建兩種字體
        Font font1 = wb.createFont(); // 標題字體
        Font font2 = wb.createFont(); // 正文字體

        // 標題加粗
        font1.setBoldweight(Font.BOLDWEIGHT_BOLD);

        // 設置兩種單元格的樣式
        setCellStype(cellStyle1, font1);
        setCellStype(cellStyle2, font2);

        //設置header
        for (int i = 0; i < headers.length; i++) {
            Cell cell = header.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(cellStyle1);
        }

        //設置data
        int headersNum = 1;
        for (int i = 0; i < list.size(); i++) {
            Row row = sheet.createRow(i + headersNum);
            for (int j = 0; j < methods.size(); j++) {
                try {
                    Object invoke = methods.get(j).invoke(list.get(i));
                    if (invoke != null) {
                        row.createCell(j).setCellValue(invoke.toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return wb;
    }

    private static void setCellStype(CellStyle cellStyle, Font font) {
        font.setFontHeightInPoints((short) 10);
        font.setColor(IndexedColors.BLACK.getIndex());
        cellStyle.setFont(font);
        cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
        cellStyle.setBorderRight(CellStyle.BORDER_THIN);
        cellStyle.setBorderTop(CellStyle.BORDER_THIN);
        cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
        cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
    }

    private static List<Method> getMethodsByStrs(String[] getters, Class clazz) {
        List<Method> list = new ArrayList<>();
        for (String getter : getters) {
            try {
                list.add(clazz.getDeclaredMethod(getter));
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return list;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM