1. 程式人生 > >SpringBoot整合poi實現Excel的 匯入/匯出

SpringBoot整合poi實現Excel的 匯入/匯出

  1. 新增依賴
        <!-- excel匯出工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
		  <dependency>
		    <groupId>com.monitorjbl</groupId>
		    <artifactId>xlsx-streamer</artifactId>
		    <version>1.2.0</version>
		  </dependency>
  1. 建立一個返回檔案二進位制流的VO物件(如果不需要返回檔案二進位制流給前端,就無須建立)
package org.sc.api.ps.model.vo;

import java.io.Serializable;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class ExportDataVo  implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/** 檔名稱 **/
    @ApiModelProperty(value = "檔名稱")
    private String fileName;
	
	
    /** 檔案二進位制流 **/
    @ApiModelProperty(value = "檔案二進位制流")
    private byte[] fileByte;

}

  1. 引入WorkbookContext檔案(如果不需要返回檔案二進位制流給前端,就無須引入)
package org.sc.common.utils.poi.api.wookbook;

import org.apache.poi.ss.usermodel.Workbook;
import org.sc.common.utils.poi.api.configuration.ConfigurationProvider;
import org.sc.common.utils.poi.api.sheet.SheetContext;
import org.sc.common.utils.poi.api.style.StyleConfigurable;
import org.sc.common.utils.poi.api.style.StyleConfiguration;
import org.sc.common.utils.poi.api.style.StyleRegistry;
import org.apache.poi.ss.usermodel.CellStyle;
/**
 * Workbook context.
 * 
 * @author i.voshkulat
 *
 */
public interface WorkbookContext extends ConfigurationProvider, StyleRegistry, StyleConfiguration, StyleConfigurable<WorkbookContext> {

	/**
	 * Create new sheet within the current workbook.
	 * 
	 * @param sheetName sheet name
     * @return created {@link SheetContext}
	 */
	public SheetContext createSheet(String sheetName);
	
	/**
	 * Use an existing sheet within the current workbook
	 *
	 * @param sheetName sheet to use
	 * @return existing {@link SheetContext}
	 * @throws java.lang.IllegalArgumentException if a sheet with the given name doesn't exist
	 */
	public SheetContext useSheet(String sheetName); 
		
    /**
     * Retrieve POI workbook referred to by current {@link WorkbookContext}.
     * Please refrain from using the exposed {@link Workbook} directly unless you need functionality of POI not provided by {@link WorkbookContext}.
     * To retrieve a workbook for saving to a file look at {@link #toNativeBytes()} instead.
     * 
     * @return native POI {@link Workbook}
     */	
	public Workbook toNativeWorkbook();
	
	/**
	 * Create .xls file binary representation for current {@link WorkbookContext}
	 * 
	 * @return excel file binary representation
	 */
	public byte[] toNativeBytes();

	/** 
	 * xls and xlsx files have different default fonts 
	 *
	 * @return font name
	 */
	public String getDefaultFontName();
	
	
	public CellStyle createLeftStyleCell(WorkbookContext workbookCtx,boolean wrapText);
	
	
	public CellStyle createCenterStyleCell(WorkbookContext workbookCtx,boolean wrapText);
	
	public CellStyle createRedStyleCell(WorkbookContext workbookCtx,boolean wrapText);
	
	public CellStyle createTopStyleCell(WorkbookContext workbookCtx,boolean wrapText);
	
	public CellStyle createRightStyleCell(WorkbookContext workbookCtx,boolean wrapText);
	
	
}

  1. 介面類
package org.sc.api.ps.service;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.sc.api.ps.model.vo.ExportDataVo;
import org.sc.common.model.vo.Response;
import org.springframework.web.multipart.MultipartFile;

public interface ExcelService {
	
	 /**
     * 以Excel模板表匯入角色資訊
     * 
	 * @throws InvalidFormatException 
	 * @throws EncryptedDocumentException 
	 * @throws Exception 
     */
    Response importRole(MultipartFile file) throws EncryptedDocumentException, InvalidFormatException, Exception;

    /**
     * 匯出角色資訊列表
     * 
     * @return
     * @throws IOException 
     */
    String export() throws IOException;

    /**
     * 匯出角色資訊列表(返回檔案二進位制流)
     * 
     * @return
     */
	ExportDataVo exportFileStreams();


}

  1. 實現類
package org.sc.api.ps.service.impl;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.sc.api.ps.model.vo.ExportDataVo;
import org.sc.api.ps.service.ExcelService;
import org.sc.common.model.vo.Response;
import org.sc.common.utils.GetDate;
import org.sc.common.utils.poi.api.row.RowContext;
import org.sc.common.utils.poi.api.sheet.SheetContext;
import org.sc.common.utils.poi.api.wookbook.WorkbookContext;
import org.sc.common.utils.poi.impl.wookbook.WorkbookContextFactory;
import org.sc.common.utils.web.ResponseUtil;
import org.sc.facade.ps.model.table.Role;
import org.sc.facade.ps.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.monitorjbl.xlsx.StreamingReader;

@Service
public class ExcelServiceImpl implements ExcelService {

	@Autowired
	private RoleService roleService;

	@Override
	public Response importRole(MultipartFile file) throws Exception {
		try {
			// 流式的讀取 xlsx 檔案,將一些特別大的檔案拆分成小的檔案去讀。
			Workbook workbook = StreamingReader.builder().rowCacheSize(1000)
					.bufferSize(4096).open(file.getInputStream());
			String value = "";
			int i = 0;
			for (Sheet sheet : workbook) {
				Role answer = null;
				for (Row r : sheet) {
					if (i == 0) {// 遍歷每一行,注意:第 0 行為標題
						i = 1;
						continue;
					}
					int ceIndex = 0;
					answer = new Role();
					for (Cell cell : r) {
						if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
							value = cell.getStringCellValue();
						} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
							if (file.getOriginalFilename().endsWith(".xls")) {
								DataFormatter formatter = new DataFormatter();
								value = formatter.formatCellValue(cell);
							} else {
								value = cell.getStringCellValue();
							}
						}
						switch (ceIndex) {
						case 0:
							answer.setRoleName(value);// 角色名
							break;
						case 1:
							answer.setRoleCode(value);// 角色編號
							break;
						case 2:
							answer.setParentId(value);// 父級id
							break;
						}
						ceIndex++;
					}
					roleService.addRole(answer);// 新增角色
				}
			}
		} catch (IOException e) {
			return ResponseUtil.error(e.getMessage());
		}
		return ResponseUtil.ok();
	}

	@Override
	public String export() throws IOException {

	    HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("角色列表");
        //合併單元格
        sheet.addMergedRegion(new CellRangeAddress(0, 2, 0, 5));
        //設定第一列單元格寬度
        sheet.setColumnWidth(0,100*100);
        //設定第二列單元格寬度
        sheet.setColumnWidth(1,100*100);
        //建立第一行
        HSSFRow row0 = sheet.createRow(0);
        //建立第二行
        HSSFRow row1 = sheet.createRow(1);
        //設定第一行單元格高度
        row0.setHeight((short) 400);
        //建立第一行第一列單元格
        HSSFCell cell0_1 = row0.createCell(0);
        //建立第二行第一列單元格
        HSSFCell cell0_2 = row1.createCell(0);
        //設定單元格的值
        cell0_1.setCellValue("角色列表");
        //改變字型樣式,步驟
        HSSFFont hssfFont = wb.createFont();
        //設定字型,紅色
        hssfFont.setColor(HSSFFont.COLOR_RED);
        //字型粗體顯示
        hssfFont.setBold(true);
        hssfFont.setFontName("宋體");
        // 字型大小
        hssfFont.setFontHeightInPoints((short) 22);
        //設定樣式
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFont(hssfFont);
        //設定單元格背景色
        cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        //設定居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        //設定邊框
        cellStyle.setBorderBottom(BorderStyle.THIN); //下邊框
        cellStyle.setBorderLeft(BorderStyle.DASH_DOT_DOT);//左邊框
        cellStyle.setBorderTop(BorderStyle.THIN);//上邊框
        cellStyle.setBorderRight(BorderStyle.THIN);//右邊框
 
        //3.單元格使用樣式,設定第一行第一列單元格樣式
        cell0_1.setCellStyle(cellStyle);
        cell0_2.setCellStyle(cellStyle);
        //建立表頭
        setTitle(wb, sheet);
        List<Role> roles = roleService.getRoles("");
        //新增資料行,並且設定單元格資料
        int rowNum = 4;
        for (Role role:roles) {
            HSSFRow row = sheet.createRow(rowNum);
            row.createCell(0).setCellValue(role.getRoleName());
            row.createCell(1).setCellValue(role.getRoleCode());
            row.createCell(2).setCellValue(role.getParentId());
            rowNum++;
        }
        //生成excel檔案
        FileOutputStream fileOut = new FileOutputStream("e:\\"+System.currentTimeMillis()+".xls");
        wb.write(fileOut);
        fileOut.close();

		return "1";
	}

	/***
	 * 設定表頭
	 * 
	 * @param workbook
	 * @param sheet
	 */
	private void setTitle(HSSFWorkbook workbook, HSSFSheet sheet) {
		HSSFRow row = sheet.createRow(3);
		
		// 設定列寬,setColumnWidth的第二個引數要乘以256,這個引數的單位是1/256個字元寬度
		sheet.setColumnWidth(0, 10 * 256);
		sheet.setColumnWidth(1, 20 * 256);
		sheet.setColumnWidth(2, 20 * 256);

		// 設定為居中加粗
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFFont font = workbook.createFont();
		font.setBold(true);
		style.setFont(font);

		HSSFCell cell;
		cell = row.createCell(0);
		cell.setCellValue("角色名");
		cell.setCellStyle(style);

		cell = row.createCell(1);
		cell.setCellValue("角色編號");
		cell.setCellStyle(style);

		cell = row.createCell(2);
		cell.setCellValue("父級id");
		cell.setCellStyle(style);
	}

	
	@Override
	public ExportDataVo exportFileStreams() {
		ExportDataVo vo=new ExportDataVo();
		vo.setFileName(System.currentTimeMillis() + ".xls");
		WorkbookContext workbookCtx = WorkbookContextFactory.createWorkbook(true);
		CellStyle center = workbookCtx.toNativeWorkbook().createCellStyle();
		center.setWrapText(true);
        CellStyle left = workbookCtx.toNativeWorkbook().createCellStyle();
        SheetContext sheetCtx = workbookCtx.createSheet("角色列表");
		RowContext top = sheetCtx.nextRow().skipCell().setRowHeight(40);
		top.text("角色名", center).setColumnWidth(10);
		top.text("角色編號", center).setColumnWidth(15);
		top.text("父級id", center).setColumnWidth(15);
		List<Role> roles = roleService.getRoles("");
		for(int i=0;i<roles.size();i++){
			Role role = roles.get(i);
			RowContext tempSkipCell = sheetCtx.nextRow().skipCell().setRowHeight(25);
			tempSkipCell.text(role.getRoleName(),center);
			tempSkipCell.text(role.getRoleCode(),center);
			tempSkipCell.text(role.getParentId(),center);
		}
		
		vo.setFileByte(workbookCtx.toNativeBytes());
		return vo;
	}
}

  1. 控制類
package org.sc.api.ps.controller;

import javax.servlet.http.HttpServletResponse;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import org.sc.api.ps.model.vo.ExportDataVo;
import org.sc.api.ps.service.ExcelService;
import org.sc.common.controller.BaseController;
import org.sc.common.model.vo.Response;
import org.sc.common.utils.web.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * spring boot整合poi實現Excel的匯入匯出
 * 
 * @author lv
 */
@Api(value = "excel",description = "Excel匯入匯出")
@RestController
@RequestMapping(value = "/api/ps/excel")
public class ExcelController  extends BaseController {
	@Autowired
	private ExcelService excelService;
	
	@ApiOperation(value = "以Excel模板表匯入角色資訊")
	@RequestMapping(value="/importRole",method = RequestMethod.POST)
	public Response importRole(@RequestBody MultipartFile file) throws Exception {
        if (file==null) {
            return ResponseUtil.error("file不能為空");
        }
		return excelService.importRole(file);
	}
	
	
	@ApiOperation(value = "匯出角色資訊列表")
	@RequestMapping(value="/export",method = RequestMethod.GET)
	public Response export() throws Exception {
        return ResponseUtil.ok(excelService.export());
	}
	
	
	@ApiOperation(value = "匯出角色資訊列表(返回檔案二進位制流)")
	@RequestMapping(value="/exportFileStreams",method = RequestMethod.GET)
	public ResponseEntity<byte[]> exportFileStreams() throws Exception {
		ExportDataVo vo = excelService.exportFileStreams();
		HttpHeaders headers = new HttpHeaders();
		String fileName = new String(vo.getFileName().getBytes("UTF-8"), "iso-8859-1");
		headers.setContentDispositionFormData("attachment", fileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<>(vo.getFileByte(), headers,HttpStatus.CREATED);
	}
	
	
}

結尾…