EasyExcel操作

EasyExcel是一個基於Java的簡單、省內存的讀寫Excel的開源項目。在儘可能節約內存的情況下支持讀寫百M的Excel。 github地址:https://github.com/alibaba/easyexcel

https://www.yuque.com/easyexcel/doc/easyexcel

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.5</version>
        </dependency>

上傳下載示例:

 /**
     * 文件下載(失敗了會返回一個有部分數據的Excel)
     * <p>1. 創建excel對應的實體對象 參照{@link DownloadData}
     * <p>2. 設置返回的 參數
     * <p>3. 直接寫,這裏注意,finish的時候會自動關閉OutputStream,當然你外面再關閉流問題不大
     */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        // 這裏注意 有同學反應使用swagger 會導致各種問題,請直接用瀏覽器或者用postman
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 這裏URLEncoder.encode可以防止中文亂碼 當然和easyexcel沒有關係
        String fileName = URLEncoder.encode("測試", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
    }

    /**
     * 文件上傳
     * <p>1. 創建excel對應的實體對象 參照{@link UploadData}
     * <p>2. 由於默認一行行的讀取excel,所以需要創建excel一行一行的回調監聽器,參照{@link UploadDataListener}
     * <p>3. 直接讀即可
     */
    @PostMapping("upload")
    @ResponseBody
    public String upload(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();
        return "success";
    }

動態單元格使合併

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 單元格合併
 *
 */
@SuppressWarnings("rawtypes")
@Data
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
	/**
	 * 合併字段的下標
	 */
	private int[] mergeColumnIndex;
	/**
	 * 合併幾行
	 */
	private int mergeRowIndex;
	
	/**
	 * 作爲唯一的合併條件
	 */
	private Integer unqiueColumnIndex;

	public ExcelFillCellMergeStrategy() {
	}

	public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
		this.mergeRowIndex = mergeRowIndex;
		this.mergeColumnIndex = mergeColumnIndex;
	}
	public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex,Integer unqiueColumnIndex) {
		this.mergeRowIndex = mergeRowIndex;
		this.mergeColumnIndex = mergeColumnIndex;
		this.unqiueColumnIndex = unqiueColumnIndex;
	}

	@Override
	public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
	                             Head head, Integer integer, Integer integer1, Boolean aBoolean) {

	}

	@Override
	public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
	                            Head head, Integer integer, Boolean aBoolean) {

	}


	@Override
	public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
	                                   CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

	}

	@Override
	public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
	                             List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
//當前行
		int curRowIndex = cell.getRowIndex();
		//當前列
		int curColIndex = cell.getColumnIndex();

		if (curRowIndex > mergeRowIndex) {
			for (int i = 0; i < mergeColumnIndex.length; i++) {
				if (curColIndex == mergeColumnIndex[i]) {
					mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
					break;
				}
			}
		}
	}

	private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
		String currentPrexValue ="";
		String prexPrexValue ="";
	    	if(this.unqiueColumnIndex!=null) {
	    	    Cell currentPrexCell=cell.getSheet().getRow(curRowIndex).getCell(unqiueColumnIndex);
	    	   if(currentPrexCell!=null) {
	    	       currentPrexValue= currentPrexCell.getCellTypeEnum() == CellType.STRING ?currentPrexCell.getStringCellValue():String.valueOf(currentPrexCell.getNumericCellValue());
	    	   }
	    	   
	    	    Cell prexPrexCell=cell.getSheet().getRow(curRowIndex-1).getCell(unqiueColumnIndex);
	    	    prexPrexValue= prexPrexCell.getCellTypeEnum() == CellType.STRING ?prexPrexCell.getStringCellValue():String.valueOf(prexPrexCell.getNumericCellValue());
	    	    
	    	}
	    	//獲取當前行的當前列的數據和上一行的當前列列數據,通過上一行數據是否相同進行合併
	    
		Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
				cell.getNumericCellValue();
		Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
		Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
				preCell.getNumericCellValue();
		// 比較當前行的第一列的單元格與上一行是否相同,相同合併當前單元格與上一行
		//
		if (curData.equals(preData) && currentPrexValue.equals(prexPrexValue)) {
			Sheet sheet = writeSheetHolder.getSheet();
			List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
			boolean isMerged = false;
			for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
				CellRangeAddress cellRangeAddr = mergeRegions.get(i);
				// 若上一個單元格已經被合併,則先移出原有的合併單元,再重新添加合併單元
				if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
					sheet.removeMergedRegion(i);
					cellRangeAddr.setLastRow(curRowIndex);
					sheet.addMergedRegion(cellRangeAddr);
					isMerged = true;
				}
			}
			// 若上一個單元格未被合併,則新增合併單元
			if (!isMerged) {
				CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
						curColIndex);
				sheet.addMergedRegion(cellRangeAddress);
			}
		}
	}
}

 

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