Excel操作

Excel操作

.xls 文件:最大256(2的8次方)列,最大65536(2的16次方)行,即横向256个单元格,竖向65536个单元格。

.xlsx 文件:最大16384(2的14次方)列,最大1048576(2的20次方)行,即横向16384个单元格,竖向1048576个单元格。

缓存读取excel

maven

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>com.monitorjbl</groupId>
    <artifactId>xlsx-streamer</artifactId>
    <version>2.1.0</version>
</dependency>

代码片段

// 判断文件是否存在
File file = new File(filePath);
if (!file.exists()) {
    throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
}

-------
    
//缓存读取excel 分批加载到内存中,防止数据量大时引发OOM
        FileInputStream fis = new FileInputStream(filePath);
        Workbook workbook = StreamingReader.builder().rowCacheSize(100) // 缓存到内存中的行数,默认是10
                .bufferSize(4098) // 读取资源时,缓存到内存的字节大小,默认是1024
                .open(fis);

-------
//遍历 并获取excel表头
Sheet sheetAt = workbook.getSheetAt(0);
//excel表头
List<String> excelTitles = new ArrayList<>();
//列名下标
Integer nameIndex = 0;
//--------------  读取表头 start ----------------------
//获取第一行表头:用缓存加载,无法使用sheetAt.getRow(i)方法,只能遍历。
for (Row row : sheetAt) {
    for (int j = 0; j < row.getLastCellNum(); j++) {
        String value = getCellFormatValue(row.getCell(j));
        // 缓存读取,用过一次之后就没了,所有要记录好列名
        excelTitles.add(value);
    }
    break;
}

缓存输出excel

采用阿里开源EasyExcel,详情请参考:

maven

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

代码片段

//获取到的excel表头存这里面
List<String> excelTitles = new ArrayList<>();
//封装成easyExcel所需格式
List<List<String>> titles = new ArrayList<List<String>>();
for (String excelTitle : excelTitles) {
    titles.add(Arrays.asList(excelTitle));
}
 // 生成EXCEL 指定输出路径 设置SHEET 去除默认样式
            writer = EasyExcel.write(outputStream).head(titles).useDefaultStyle(false).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetAt.getSheetName()).build();
......
    List<List<Object>> rows = new ArrayList<>();
    //获取每一行数据
    List<Object> oneRow = new ArrayList<>();
for (int i = 0; i < excelTitles.size(); i++) {
    oneRow.add(getCellValue(row.getCell(i)));
}
rows.add(oneRow);
//写excel
writer.write(rows,writeSheet);
......
//大量数据循环分批请求时,记得清空有数据的容器
rows.clear();
//为避免OOM记得将循环中用到的容器及时置空

......
    finally 中记得:
        writer.finish();//调用该方法后才会将数据写入文件
		System.gc();

ps

获取单元格内容

private  String getCellFormatValue(Cell cell) {
        String cellValue = "";
        if (cell != null) {
            // 判断cell类型
            switch (cell.getCellType()) {
                case NUMERIC: {
                    cellValue = String.valueOf(cell.getNumericCellValue());
                    break;
                }
                case STRING: {
                    cellValue = cell.getRichStringCellValue().getString();
                    break;
                }
                default:
                    cellValue = "";
            }
        }
        return cellValue;
    }

获取单元格内容(对日前进行处理)

import org.apache.poi.hssf.usermodel.HSSFDateUtil;

private  Object getCellValue(Cell cell) {
        String cellValue = "";
        if (cell != null) {
            // 判断cell类型
            switch (cell.getCellType()) {
                case NUMERIC: {
                    //日期格式
                    if(HSSFDateUtil.isCellDateFormatted(cell)){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        return sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue())).toString();
                    }
                    //数字格式
                    return cell.getNumericCellValue();
                }
                case STRING: {
                    return cell.getRichStringCellValue().getString();
                }
                default:
                    cellValue = "";
            }
        }
        return cellValue;
    }

获取单元格内容

 public String getCellValue(Cell cell) {
        Object result = "";  
        if (cell != null) {  
            switch (cell.getCellType()) {  
                case STRING:
                result = cell.getStringCellValue();  
                break;  
                case NUMERIC:
                result = cell.getNumericCellValue();
                break;  
            case BOOLEAN:
                result = cell.getBooleanCellValue();  
                break;  
            case FORMULA:
                result = cell.getCellFormula();  
                break;  
            case ERROR:
                result = cell.getErrorCellValue();  
                break;  
            case BLANK:
                break;  
            default:  
                break;  
            }  
        }  
        return result.toString();  
    }

从mysql中读取大量数据

分页查询

代码案例片段

 Page<xxxDO> xxxDOPage = null;
			// count:查询次数  queryCount:用户所能查询的总数 part:每次查多少条
            Long count =  queryCount/part;
            for (int i = 1; i <= count; i++) {
                page = new Page<XxxDO>(i, part);
                xxxDOPage = xxxService.page(page, queryWrapper);
                xxxDOList = xxxDOPage.getRecords();
                fileNames.add(filePath+"/"+name+i+".xlsx");
                EasyExcel.write(filePath+"/"+name+i+".xlsx", XxxDO.class).useDefaultStyle(false).sheet("数据").doWrite(xxxDOList);
                xxxDOList = null;
                xxxDOPage = null;
                break;
            }
			//对最后一次(余数)进行处理,也可以在上面判断下一次做完
            if (pageList1.getTotal() - count*part > 0 ){
                page = new Page<XxxDO>(count+1, part);
                xxxDOPage = xxxService.page(page, queryWrapper);
                xxxDOList = xxxDOPage.getRecords();
                fileNames.add(filePath+"/"+name+(count+1)+".xlsx");
                EasyExcel.write(filePath+"/"+name+(count+1)+".xlsx", XxxDO.class).useDefaultStyle(false).sheet("数据").doWrite(xxxDOList);
                xxxDOList = null;
                xxxDOPage = null;
            }

流式查询

代码案例片段

public class MyResultHandler implements ResultHandler {
    
    @Override
    public void handleResult(ResultContext resultContext) {
        Object resultObject = resultContext.getResultObject();
        Map<String,Object> map = (Map<String,Object>)resultObject;
        //业务处理...
    }
}
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.session.ResultHandler;
@Mapper
public interface XxxDOMapper  {
    @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
    //@ResultType(XxxDO.class)
    //void query(@Param("params") Map params,ResultHandler<XxxDO> handler);
    void query(@Param("sign") int sign,ResultHandler<Map> handler);
}
@Test
public void test() {
    MyResultHandler handler = new MyResultHandler();
    XxxDOMapper.query(handler);
}
<select id="select" resultType="java.util.Map">
		select * from xxx_post_info where sign = #{sign}
	</select>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值