本文章主要是介绍阿里巴巴的easyexcel的使用

1. 首先需要我们导入easyexcel的依赖包

<!-- alibaba/easyexcel 使用高版本,低版本string接收数字丢小数位的bug --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.7</version></dependency>

2. 前期工作准备

编写相关导出模板和导入模板。在项目的resources下创建文件夹,命名为excel

导出模板(此处仅做示例,字段根据自己项目来):

导入模板(导入时需要哪些字段根据自己项目业务来订):

将创建好的模板放置到创建好的resources下的excel文件夹内

3. 编写相关基础工具类

ExcelFillCellMergePrevColUtils.java

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 org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 列合并工具类** @author DaiHaijiao*/
public class ExcelFillCellMergePrevColUtils implements CellWriteHandler {private static final String KEY = "%s-%s";//所有的合并信息都存在了这个map里面Map<String, Integer> mergeInfo = new HashMap<>();public ExcelFillCellMergePrevColUtils() {}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic 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();Integer num = mergeInfo.get(String.format(KEY, curRowIndex, curColIndex));if (null != num) {// 合并最后一行 ,列this.mergeWithPrevCol(writeSheetHolder, cell, curRowIndex, curColIndex, num);}}public void mergeWithPrevCol(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex, int num) {Sheet sheet = writeSheetHolder.getSheet();CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex, curRowIndex, curColIndex, curColIndex + num);sheet.addMergedRegion(cellRangeAddress);}//num从第几列开始增加多少列,(6,2,7)代表的意思就是第6行的第2列至第2+7也就是9列开始合并public void add(int curRowIndex, int curColIndex, int num) {mergeInfo.put(String.format(KEY, curRowIndex, curColIndex), num);}}

ExcelFillCellMergeStrategyUtils.java

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 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;/*** 行合并工具类** @author DaiHaijiao*/
public class ExcelFillCellMergeStrategyUtils implements CellWriteHandler {/*** 合并字段的下标*/private int[] mergeColumnIndex;/*** 合并几行*/private int mergeRowIndex;public ExcelFillCellMergeStrategyUtils(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,Head head, Integer integer, Integer integer1, Boolean aBoolean) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {}@Overridepublic 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]) {this.mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);break;}}}}private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并//获取当前行的第一列Cell firstNowCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex);Object curData = firstNowCell.getCellTypeEnum() == CellType.STRING ? firstNowCell.getStringCellValue() : firstNowCell.getNumericCellValue();Row preRow = cell.getSheet().getRow(curRowIndex - 1);if (preRow == null) {// 当获取不到上一行数据时,使用缓存sheet中数据preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);}Cell preCell = preRow.getCell(curColIndex);Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行if (curData.equals(preData)) {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);}}}
}

ExcelUtils.java

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;/*** excel导出工具类**/
public class ExcelUtils {/*** 导出数据到指定Excel** @param response                        HttpServletResponse对象* @param excelPath                       Excel模板地址* @param excelFileName                   文件名称* @param outerMap                        头部内容map* @param innerMapList                    表格内容list* @param excelFillCellMergePrevColUtils  列合并参数* @param excelFillCellMergeStrategyUtils 行合并参数* @throws IOException 异常错误*/public static void exportToTemplate(HttpServletResponse response, String excelPath, String excelFileName, Map<String, Object> outerMap, List<Map<String, Object>> innerMapList,ExcelFillCellMergePrevColUtils excelFillCellMergePrevColUtils, ExcelFillCellMergeStrategyUtils excelFillCellMergeStrategyUtils) throws IOException {InputStream inputStream = new ClassPathResource(excelPath).getInputStream();response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode(excelFileName, "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).registerWriteHandler(excelFillCellMergePrevColUtils).registerWriteHandler(excelFillCellMergeStrategyUtils).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();if (null != innerMapList && innerMapList.size() > 0) {FillWrapper listWrapper = new FillWrapper("list", innerMapList);excelWriter.fill(listWrapper, fillConfig, writeSheet);}if (null != outerMap && outerMap.size() > 0) {excelWriter.fill(outerMap, writeSheet);}excelWriter.finish();}/*** 验证并获取excel单元格内的值** @param columnData   列值,object类型* @param rowIndex     行号* @param columnIndex  列号* @param fieldName    字段名称* @param lengthLimit  限制长度数(null时不做判断)* @param ifJudgeEmpty 是否需要判空(默认是)* @return 字符串格式值* @throws Exception 逻辑异常*/public static String checkValue(Object columnData, int rowIndex, int columnIndex, String fieldName, Integer lengthLimit,Boolean ifJudgeEmpty) throws Exception {String value = getStringValue(columnData);ifJudgeEmpty = null == ifJudgeEmpty ? true : ifJudgeEmpty;if (ifJudgeEmpty) {//需要判空if (StringUtils.isEmpty(value)) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列," + fieldName + "不能为空");}}if (null != lengthLimit && lengthLimit > 0) {//需要判断字符长度if (StringUtils.isNotEmpty(value)) {if (value.length() > lengthLimit) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列," + fieldName + "不能超过" + lengthLimit + "个字符");}}}return value;}/*** String => LocalDate* 入参str和pattern格式需要对应** @param str* @return LocalDate*/public static LocalDate str2LocalDate(String str) {if (StringUtils.isEmpty(str)) {return null;}if (str.indexOf("-") != -1 || str.indexOf("/") != -1) {String pattern = str.indexOf("/") != -1 ? "yyyy/MM/dd" : "yyyy-MM-dd";try {//测试日期字符串是否符合日期DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);return LocalDate.parse(str, dateTimeFormatter);} catch (Exception e) {pattern = str.indexOf("/") != -1 ? "yyyy/M/d" : "yyyy-M-d";DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);return LocalDate.parse(str, dateTimeFormatter);}} else {Calendar calendar = new GregorianCalendar(1900, 0, -1);Date date = calendar.getTime();int amount = Integer.parseInt(str);if (amount > 0) {Calendar calendar1 = Calendar.getInstance();calendar1.setTime(date);calendar1.add(Calendar.DAY_OF_YEAR, amount);date = calendar.getTime();}return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();}}/*** 获取String类型的值** @param columnData 列值,object类型* @return 字符串格式值*/public static String getStringValue(Object columnData) {if (columnData == null) {return null;} else {String res = columnData.toString().replace("[\\t\\n\\r]", "").trim();return res;
//            //判断是否是科学计数法  true是科学计数法,false不是科学计数法
//            boolean isMache=SCIENTIFIC_COUNTING_METHOD_PATTERN.matcher(res).matches();
//            if(isMache){
//                BigDecimal resDecimal = new BigDecimal(res);
//                return resDecimal.toPlainString();
//            }else {
//                return res;
//            }}}
}

上面的Excel中牵扯合并相关类,下一个帖子到时候会讲述合并相关用法。

4. 控制层用法

4.1 导出模板

/*** 导出模板** @param response HttpServletResponse对象* @throws Exception 导出异常*/@GetMapping(value = "/exportTemplate", produces = "application/octet-stream")public void exportTemplate(HttpServletResponse response) throws Exception {ExcelUtils.exportToTemplate(response, "excel/某某管理导入模板.xlsx", "某某管理导入模板", null, null, null, null);}

4.2 导出数据

接收导出数据的入参,可以单个单个的接收,也可以直接定义一个对象去接收,此处采用对象来接收的,如需对参数进行校验,可以通过注解的方式进行数据校验

UserExcelParam.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 某某管理导出入参** @author DaiHaijiao*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserExcelParam implements Serializable {private static final long serialVersionUID = 0L;/*** 主键id*/private String dataIds;/*** 所属单位(组织机构表id)*/private String departmentId;/*** 人员名*/private String userName;/*** 证书状态(-1已过期 0即将过期 1正常)*/private Integer status;}
/*** 导出数据** @param excelParam 导出入参* @param response   HttpServletResponse对象* @throws Exception 导出异常*/@GetMapping(value = "/export", produces = "application/octet-stream")public void export(@RequestBody @Validated UserExcelParam excelParam, HttpServletResponse response) throws Exception {// excelParam为入参对象,也可拆成单个参数来接收// 根据入参查询用户数据集合List<User> resultList = userService.list(excelParam);String title = "这个是Excel导出后Excel里面显示的标题";Map<String, Object> outerMap = new HashMap<>(2);outerMap.put("title", title);List<Map<String, Object>> innerMapList = new ArrayList<>();User item;String startDate, endDate;for (int i = 0; i < resultList.size(); ++i) {item = resultList.get(i);Map<String, Object> innerMap = new HashMap<>(16);innerMap.put("index", i + 1);innerMap.put("name", item.getName());innerMap.put("departmentName", item.getDepartmentName());innerMap.put("userName", item.getUserName());// 注意:时间需要转换成字符串形式startDate = DateUtils.localDate2String(item.getStartValidity(), "yyyy-MM-dd");if (null == item.getEndValidity()) {innerMap.put("validityPeriod", startDate + " ~ ");} else {endDate = DateUtils.localDate2String(item.getEndValidity(), "yyyy-MM-dd");innerMap.put("validityPeriod", startDate + " ~ " + endDate);}innerMap.put("someTypeName", item.getSomeTypeName());innerMap.put("statusVal", item.getStatusVal());innerMapList.add(innerMap);}ExcelUtils.exportToTemplate(response, "excel/某某管理导出模板.xlsx", title, outerMap, innerMapList, null, null);}

如果导出模板中字段太多,可以在上述代码的for循环中直接对象转map,对于个别特殊字段手动在处理一次。

4.3 导入数据

这个稍微有点麻烦,首先我们需要创建监听类。监听类中需要对导入的Excel中的每一条数据进行校验,当发现有数据异常时会抛出异常,终止后面的数据校验。数据全部校验完成后会产生一个数据集合,最后执行的批量插入。

UserReadExcelListener.java

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;import java.time.LocalDate;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;/*** 某某管理数据导入监听** @author DaiHaijiao*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class UserReadExcelListener extends AnalysisEventListener {/*** 解析的数据集合*/List<User> dataList = new ArrayList<>();/*** 资质类型字典数据*/static List<DictData> dictDataList;/*** 所属单位*/static String departmentId;public static UserReadExcelListener newBean(List<DictData> dictDatas, String deptId) {dictDataList = dictDatas;departmentId = deptId;return new UserReadExcelListener();}/*** 读取excel每一行都会触发本方法** @param data    行数据* @param context AnalysisContext*/@SneakyThrows@Overridepublic void invoke(Object data, AnalysisContext context) {User excelData = new User();// 当前数据行号,从0开始Integer rowIndex = context.readRowHolder().getRowIndex();LinkedHashMap dataTemp = (LinkedHashMap) data;for (int i = 0; i < dataTemp.size(); i++) {this.parseColumnData(rowIndex, i, dataTemp.get(i), excelData);}// 解析完一行数据后,添加到集合中excelData.setDepartmentId(departmentId);dataList.add(excelData);}/*** 解析列值** @param rowIndex    行号* @param columnIndex 列号* @param columnData  列值,object类型* @param excelData   实例对象* @throws Exception 逻辑异常*/private void parseColumnData(Integer rowIndex, Integer columnIndex, Object columnData, User excelData) throws Exception {// 逐列判断并使用正确的类型接收value,列号从0开始if (columnIndex == 1) {//某编号String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "某编号", 16, null);excelData.setNo(value);} else if (columnIndex == 2) {//某类型String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "某类型", null, null);DictData dictData = dictDataList.stream().filter(item -> value.equals(item.getDictLabel())).findFirst().orElse(null);if (null == dictData) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,某类型有误");}excelData.setSomeType(dictData.getDataId());} else if (columnIndex == 3) {//某单位excelData.setIssuingUnit(ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "某单位", 64, false));} else if (columnIndex == 4) {//有效期之开始时间String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "有效期之开始时间", null, null);try {excelData.setStartValidity(ExcelUtils.str2LocalDate(value));} catch (Exception e) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,有效期之开始时间格式有误");}} else if (columnIndex == 5) {//有效期之结束时间String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "有效期之结束时间", null, false);LocalDate endValidity = null;if (StringUtils.isNotEmpty(value)) {try {endValidity = ExcelUtils.str2LocalDate(value);} catch (Exception e) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,有效期之结束时间格式有误");}long start = DateUtils.localDate2Date(excelData.getStartValidity()).getTime();if (DateUtils.localDate2Date(endValidity).getTime() <= start) {throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,有效期之结束时间必须大于开始时间");}}excelData.setEndValidity(endValidity);}}/*** excel解析后置处理器,在excel解析完成后执行一次*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {System.out.println("excel解析后置处理器");}
}
/*** 导入数据** @param file excel文件* @return 是否成功*/@PostMapping("/import")@ResponseBody
//    @Transactional(rollbackFor = Exception.class)public Object importExcel(@RequestParam("file") @NotNull MultipartFile file) {Map<String, String> map = new HashMap<>(8);// 类型字典数据List<DictData> dictDataList = dictDataService.queryDataByType("A_TYPE");// 获取当前公司idString departmentId = departmentService.getNowUserDepartmentsId();// 将参数传递到读取监听类中UserReadExcelListener excelListener = UserReadExcelListener.newBean(dictDataList, departmentId);try {EasyExcel.read(file.getInputStream()).sheet(0).headRowNumber(1).registerReadListener(excelListener).doRead();} catch (Exception e) {e.printStackTrace();map.put("code", "100");map.put("msg", "请求失败");return map;}List<User> dataList = excelListener.getDataList();if (dataList.size() == 0) {map.put("code", "500");map.put("msg", "导入数据不能为空");return map;}boolean result = true;// 批量插入基数(插入数据量为100时性能还行)int baseY = 100;int y = dataList.size() / baseY + 1;int z = dataList.size() % 100;for (int i = 0; i < y; i++) {if (i != y - 1) {result = userService.insertMore(dataList.subList(i * baseY, (i + 1) * baseY));} else {result = dataList.subList(i * baseY, i * baseY + z).size() == 0 ? true : userService.insertMore(dataList.subList(i * baseY, i * baseY + z));}if (!result) {map.put("code", "500");map.put("msg", "数据导入失败");return map;}}map.put("code", "200");map.put("msg", "请求成功");return map;}

监听类中的校验可能用用到其他的一些数据,而这些数据可以在实例化监听类时通过构造方法进行传递操作,如不需要就不多说了。

Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)相关推荐

  1. 如何把股票数据导出excel?导出股票历史数据到Excel的方法

    共享一个可以把股票数据导出Excel的方法,是一个在线下载股票历史数据,目前可以下载A股.港股.美股所有个股的历史数据,数据是Excel的方便分析查看.做表,最主要是免费... 只要两步就能下载: 填 ...

  2. php页面表格导出excel表格数据类型,php页面表格导出excel表格数据类型-php导出excel是不是导出整个表的?可不可以导出指......

    php 怎么把数据导出到excel表格 昨天项目里有个新需求,客户希望把一些数据能导出成为Excel表格,刚开始用PHP原生输入Excel表格,发现效果不是很理想,于是找到一个比较著名的库:PHPEx ...

  3. js导出EXCEL js导出EXCEL

    参考一:http://wenku.baidu.com/view/7b81f3eb6294dd88d0d26b57.html 参考二: js导出EXCEL js导出EXCEL <html> ...

  4. 分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续2篇-模板导出综合示例)...

    自ExcelUtility类推出以来,经过项目中的实际使用与不断完善,现在又做了许多的优化并增加了许多的功能,本篇不再讲述原理,直接贴出示例代码以及相关的模板.结果图,以便大家快速掌握,另外这些示例说 ...

  5. java关于excel的导出_[转载]关于JAVA导出Excel

    现在正在做的项目中涉及大量的Excel文件导出导入操作,都是使用Java Excel来操作. Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Exce ...

  6. springboot+poi开发excel导出 加载Excel模板导出 Excel批量导出详解

    提到Excel导出功能,可能很多人都使用springmvc框架做过,笔者今天要给大家分享的是基于springBoot开发Excel复杂模板导出功能(所谓复杂模板指在模板里的特定表头里有不同的单元格合并 ...

  7. Java操作Excel并导出

    Java导出Excel表格 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Java导出Excel表格 前言 一.企业excel项目导出演示 二.使用步骤 1.引入Mave ...

  8. exp导出excel oracle_OracleToExcel_Oracle导出excel数据(OracleToExcel)下载 v3.1 官方版 - 121下载站...

    OracleToExcel是一款免费的Oracle导出excel数据软件,可以将Oracle中的数据导出到excel中,支持单个表.所有表和SQL查询数据,支持输出clob和blob字段在Oracle ...

  9. Java中excel的导出导入

    spring boot项目: pom.xml: <?xml version="1.0"?> <project xsi:schemaLocation="h ...

  10. php 导出excel分段导出_php 导出excel 10万数据

    php导出excel 10万数据(此代码主要测试用,没写单元测试 还在修改中 后期加上单元测试) 在工作当中要对一些基本信息和其他信息导出 起初信息比较小无所谓.... 但当信息超出65535的时候 ...

最新文章

  1. 五年循环期限已到,我们又要步入“AI寒冬”了吗?
  2. 综述:NLP中的深度学习优势
  3. 一台计算机有64,在同一台计算机上使用带有32位和64位Altium设计软件的数据库元件库...
  4. python里countsget_在Python中测试访问同一数据的竞争条件的方法
  5. c# 三种异步编程模型EAP(*)、 APM(*)和 TPL
  6. CentOS安装Chrome
  7. Oracle SQL性能优化技巧大总结
  8. Elasticsearch数据库
  9. C#GRPC 服务端与客户端通信,故障排除记录
  10. R in action读书笔记(3)-第六章:基本图形
  11. 测试用例--因果图、判定表法
  12. 团购网站安全性普遍堪忧
  13. 计算机桌面鼠标锁定了怎么办,笔记本鼠标锁住怎么办
  14. Windows2000 安装VMware Tools所需KB835732 补丁包
  15. 信息系统项目管理师(2022年) —— 第 11 章 项目风险管理
  16. Photoshop抠图(磁性钢笔工具)
  17. opencv中图像失焦检测
  18. 中国科学院计算机研究所上级单位,陈援非(中国科学院计算技术研究所高工)_百度百科...
  19. Aspx.Net的Aspx页面和Aspx.cs联用
  20. 如何解决All flavors must now belong to a named flavor dimension.?

热门文章

  1. Spring 中的依赖注入
  2. linux下用cat查看了一个文件, 导致界面乱码
  3. java 一个父类派生两个子类_面向对象 - 1.继承/2.派生/3.继承的实现原理
  4. dongyangcan
  5. 测试工程师,跳槽涨了4k,年总包算下来还降薪了?
  6. 【竞赛记录】kpi异常检测
  7. clock gating check
  8. 宋浩_1_函数映射, 满射/双射/单射/逆映射, 定义域,值域
  9. javascript 添加千分符
  10. 大数据-数仓-数据采集-业务数据(二):全量同步采集【MySQL<-->DataX(全量)<-->HDFS】【每日全量:每天都将业务数据库中全部数据同步到数据仓库,是保证两侧数据同步的最简单方式】