标签:urlencode 依赖 图片 alt jar variable get exp 集中
PS:这几天项目中用到poi导出数据至excel,这里将poi导出excel再回忆下。
一、创建空的springboot项目,在pom文件中加入操作Excel所需要的jar
org.apache.poi
poi-ooxml
3.15
此处注意 org.apache.poi下有很多依赖包,我们选择我们此次操作excel(.xls、.XLSX)所需要的依赖,选择poi-ooxml即可。
此处附上官网说明(http://poi.apache.org/components/)
二、工具类
在POI中操作Excel大致分为两种,2003版本和2007版本及以上,前者最大支持65536行,后者最大支持1048576行,两种所使用的工具类是不一样的(例如03使用HSSFWorkbook,07使用XSSFWorkbook)。
2003版的最大不能超过65535行,2007版没测出来,内存溢出了
1、 2007版工具方法(无或者只有1行标题)
/**
*@Description:03版后缀.xls,标题可有可无,如无标题则headers传null即可
*@Param: title excel名称,也可当sheet页名称使用
*@Param: headers 标题
*@Param: dataset 数据集
*@Param: out 输出流
*@Param: dataset 数据集,此处必须为Map
*@Param: pattern 如果表格中有时间类型按照这种格式展示
*@Param: keys 数据集中Map的字段名称
*@return:void
*@Author: 张江坤
*@date: 2021/2/24 21:54
*/
public static void exportExcel2003(String title, String[] headers, List
2、2007版工具方法(无或者只有1行标题,较2003版,更替了工具类,逻辑一样,粘贴此处方便使用)
/**
*@Description:07版后缀.xlsx,标题可有可无,如无标题则headers传null即可
*@Param: title excel名称,也可当sheet页名称使用
*@Param: headers 标题
*@Param: dataset 数据集
*@Param: out 输出流
*@Param: dataset 数据集,此处必须为Map
*@Param: pattern 如果表格中有时间类型按照这种格式展示
*@Param: keys 数据集中Map的字段名称
*@return:void
*@Author: 张江坤
*@date: 2021/2/24 21:54
*/
public static void exportExcel2007(String title, String[] headers, List> dataset, OutputStream out, String pattern,List keys) {
// 声明一个工作薄
XSSFWorkbook workbook = new XSSFWorkbook();
// 生成一个表格
XSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
// 生成一个样式
XSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(new XSSFColor(Color.gray));
style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
style.setBorderRight(XSSFCellStyle.BORDER_THIN);
style.setBorderTop(XSSFCellStyle.BORDER_THIN);
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
XSSFFont font = workbook.createFont();
font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setColor(new XSSFColor(Color.BLACK));
font.setFontHeightInPoints((short) 11);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
XSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(new XSSFColor(Color.WHITE));
style2.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(XSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(XSSFCellStyle.BORDER_THIN);
style2.setBorderRight(XSSFCellStyle.BORDER_THIN);
style2.setBorderTop(XSSFCellStyle.BORDER_THIN);
style2.setAlignment(XSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体
XSSFFont font2 = workbook.createFont();
font2.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
XSSFRow row;
//有无标题,取决于标题是否在数据集中
if(null != headers){
// 产生表格标题行
row = sheet.createRow(0);
XSSFCell cellHeader;
for (int i = 0;i ) {
cellHeader = row.createCell(i);
cellHeader.setCellStyle(style);
cellHeader.setCellValue(new XSSFRichTextString(headers[i]));
}
}
if(!dataset.isEmpty()) {
// 遍历集合数据,产生数据行
Iterator> it = dataset.iterator();
//如果没有标题,则从第0行开始写数据
int index = null==headers ? -1 : 0;
Map t;
Field field;
XSSFRichTextString richString;
Pattern p = Pattern.compile("^//d+(//.//d+)?$");
Matcher matcher;
XSSFCell cell;
Object value;
String textValue;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
t = (Map) it.next();
for (int i = 0; i ) {
cell = row.createCell(i);
cell.setCellStyle(style2);
try {
value = t.get(keys.get(i));
// 判断值的类型后进行强制类型转换
textValue = null;
if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Float) {
textValue = String.valueOf((Float) value);
cell.setCellValue(textValue);
} else if (value instanceof Double) {
textValue = String.valueOf((Double) value);
cell.setCellValue(textValue);
} else if (value instanceof Long) {
cell.setCellValue((Long) value);
}
if (value instanceof Boolean) {
textValue = "是";
if (!(Boolean) value) {
textValue = "否";
}
} else if (value instanceof Date) {
textValue = sdf.format((Date) value);
} else {
// 其它数据类型都当作字符串简单处理
if (value != null) {
textValue = value.toString();
}
}
if (textValue != null) {
matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
richString = new XSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} finally {
// 清理资源
}
}
}
}
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
调用入口
public void exportExcle(@PathVariable("fileName") String fileName, HttpServletResponse response){
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
try {
response.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8") + ".xls");//03版后缀为.xls 07版后缀为.xlsx
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
List> list = new ArrayList();
for(int i=0;i){
Map map = new HashMap();
map.put("one","第"+(i+1)+"列的值");
map.put("two","第"+(i+1)+"列的值");
map.put("three","第"+(i+1)+"列的值");
map.put("four","第"+(i+1)+"列的值");
map.put("five","第"+(i+1)+"列的值");
map.put("six","第"+(i+1)+"列的值");
list.add(map);
}
//生成的excel中的列名
String[] header = {"第1列","第2列","第3列","第4列","第5列","第6列"};
//数据集中对应的key
List keys = Arrays.asList("one","two","three","four","five","six");
try {
ExportExcelUtil.exportExcel2003(fileName, header, list, response.getOutputStream(), "yyyy-MM-dd hh:mm:ss",keys);
//ExportExcelUtil.exportExcel2007(fileName, null, list, response.getOutputStream(), "yyyy-MM-dd hh:mm:ss",keys);
} catch (IOException e) {
e.printStackTrace();
}
}
无标题截图
有标题截图
3、03版标题合并类型工具方法
/**
*@Description:03版 .xls
*@Param: title excel名称,也可当sheet页名称使用
*@Param: headers_1 未合并的第一部分标题
*@Param: headers_2 合并单元格的大标题
*@Param: headers_3 不合并的第二部分列名
*@Param: headers_4 合并单元格的小标题
*@Param: nums 合并列中每大列占几小列,例如 [3,3]第1,2大列各占3小列
*@Param: keys 数据集中Map的字段名称
*@Param: dataset 数据集,此处必须为Map
*@Param: out 输出流
*@Param: pattern 如果表格中有时间类型按照这种格式展示
*@return:void
*@Author: 张江坤
*@date: 2021/2/23 13:48
*/
public static void exportExcel2003(String title, String[] headers_1,String[] headers_2,String[] headers_3, String[] headers_4, int[] nums, List> dataset, List keys, OutputStream out, String pattern) {
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
// 生成一个样式
HSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
HSSFFont font = workbook.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setColor(HSSFColor.WHITE.index);
font.setFontHeightInPoints((short) 11);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(HSSFColor.WHITE.index);
style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体(标题跟正文分开)
HSSFFont font2 = workbook.createFont();
font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
HSSFRow row = sheet.createRow(0);
//设置未合并的第一部分列的格式
for(int i=0; i){
//占2行1列(因为有合并行,合并列)
CellRangeAddress cra=new CellRangeAddress(0, 1, i, i);
sheet.addMergedRegion(cra);
}
//为未合并行的第一部分列写入标题
for(int i=0; i){
final Cell cell = row.createCell(i);
cell.setCellStyle(style);
cell.setCellValue(headers_1[i]);
}
int sum1 = 0;
int sum2 = 0;
//合并列的大标题
for(int i=0; i//受理数,办结数
sum1 += nums[i];
//占1行,从header_2长度后的那列开始数,画够合并行的宽度
CellRangeAddress cra=new CellRangeAddress(0, 0, headers_1.length+sum2, headers_1.length+sum1-1);
sheet.addMergedRegion(cra);
sum2 += nums[i];
}
int sum = 0;
for(int i=0; i){
//给合并列中的大列写入标题,未合并列第一部分宽度 + 合并列各列中小列的宽度
final Cell cell = row.createCell(headers_1.length+sum);
cell.setCellStyle(style);
cell.setCellValue(headers_2[i]);
sum += nums[i];
}
//未合并列的第二部分列设置格式,占2行1列
for(int i=0; i){
CellRangeAddress cra=new CellRangeAddress(0, 1, headers_1.length+sum2+i, headers_2.length+sum2+i);
sheet.addMergedRegion(cra);
}
//给未合并列的第二部分列写入标题
for(int i=0; i){
final Cell cell = row.createCell(headers_1.length+sum2+i);
cell.setCellStyle(style);
cell.setCellValue(headers_3[i]);
}
//重新创建一行,写入合并列中的小列
row = sheet.createRow(1);
for(int i=0; i){
final Cell cell = row.createCell(headers_1.length+i);
cell.setCellStyle(style);
cell.setCellValue(headers_4[i]);
}
// 遍历集合数据,产生数据行
Iterator> it = dataset.iterator();
int index = 1;
Map t;
HSSFRichTextString richString;
Pattern p = Pattern.compile("^//d+(//.//d+)?$");
Matcher matcher;
HSSFCell cell;
Object value;
String textValue;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
t = (Map) it.next();
for (int i = 0; i ) {
cell = row.createCell(i);
cell.setCellStyle(style2);
try {
value = t.get(keys.get(i));
// 判断值的类型后进行强制类型转换
textValue = null;
if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Float) {
textValue = String.valueOf((Float) value);
cell.setCellValue(textValue);
} else if (value instanceof Double) {
textValue = String.valueOf((Double) value);
cell.setCellValue(textValue);
} else if (value instanceof Long) {
cell.setCellValue((Long) value);
}
if (value instanceof Boolean) {
textValue = "是";
if (!(Boolean) value) {
textValue = "否";
}
} else if (value instanceof Date) {
textValue = sdf.format((Date) value);
} else {
// 其它数据类型都当作字符串简单处理
if (value != null) {
textValue = value.toString();
}
}
if (textValue != null) {
matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
richString = new HSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} finally {
// 清理资源
}
}
}
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
4、07版标题合并类型工具方法
/**
*@Description:07版 .xlsx
*@Param: title excel名称,也可当sheet页名称使用
*@Param: headers_1 未合并的第一部分标题
*@Param: headers_2 合并单元格的大标题
*@Param: headers_3 不合并的第二部分列名
*@Param: headers_4 合并单元格的小标题
*@Param: nums 合并列中每大列占几小列,例如 [3,3]第1,2大列各占3小列
*@Param: keys 数据集中Map的字段名称
*@Param: dataset 数据集,此处必须为Map
*@Param: out 输出流
*@Param: pattern 如果表格中有时间类型按照这种格式展示
*@return:void
*@Author: 张江坤
*@date: 2021/2/23 13:48
*/
public static void exportExcel2007(String title, String[] headers_1,String[] headers_2,String[] headers_3, String[] headers_4, int[] nums, List> dataset, List keys, OutputStream out, String pattern) {
// 声明一个工作薄
XSSFWorkbook workbook = new XSSFWorkbook();
// 生成一个表格
XSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth(20);
// 生成一个样式
XSSFCellStyle style = workbook.createCellStyle();
// 设置这些样式
style.setFillForegroundColor(new XSSFColor(Color.gray));
style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
style.setBorderRight(XSSFCellStyle.BORDER_THIN);
style.setBorderTop(XSSFCellStyle.BORDER_THIN);
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
XSSFFont font = workbook.createFont();
font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setColor(new XSSFColor(Color.BLACK));
font.setFontHeightInPoints((short) 11);
// 把字体应用到当前的样式
style.setFont(font);
// 生成并设置另一个样式
XSSFCellStyle style2 = workbook.createCellStyle();
style2.setFillForegroundColor(new XSSFColor(Color.WHITE));
style2.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
style2.setBorderBottom(XSSFCellStyle.BORDER_THIN);
style2.setBorderLeft(XSSFCellStyle.BORDER_THIN);
style2.setBorderRight(XSSFCellStyle.BORDER_THIN);
style2.setBorderTop(XSSFCellStyle.BORDER_THIN);
style2.setAlignment(XSSFCellStyle.ALIGN_CENTER);
style2.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体(标题跟正文分开)
XSSFFont font2 = workbook.createFont();
font2.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style2.setFont(font2);
XSSFRow row = sheet.createRow(0);
//设置未合并的第一部分列的格式
for(int i=0; i){
//占2行1列(因为有合并行,合并列)
CellRangeAddress cra=new CellRangeAddress(0, 1, i, i);
sheet.addMergedRegion(cra);
}
//为未合并行的第一部分列写入标题
for(int i=0; i){
final Cell cell = row.createCell(i);
cell.setCellStyle(style);
cell.setCellValue(headers_1[i]);
}
int sum1 = 0;
int sum2 = 0;
//合并列的大标题
for(int i=0; i//受理数,办结数
sum1 += nums[i];
//占1行,从header_2长度后的那列开始数,画够合并行的宽度
CellRangeAddress cra=new CellRangeAddress(0, 0, headers_1.length+sum2, headers_1.length+sum1-1);
sheet.addMergedRegion(cra);
sum2 += nums[i];
}
int sum = 0;
for(int i=0; i){
//给合并列中的大列写入标题,未合并列第一部分宽度 + 合并列各列中小列的宽度
final Cell cell = row.createCell(headers_1.length+sum);
cell.setCellStyle(style);
cell.setCellValue(headers_2[i]);
sum += nums[i];
}
//未合并列的第二部分列设置格式,占2行1列
for(int i=0; i){
CellRangeAddress cra=new CellRangeAddress(0, 1, headers_1.length+sum2+i, headers_2.length+sum2+i);
sheet.addMergedRegion(cra);
}
//给未合并列的第二部分列写入标题
for(int i=0; i){
final Cell cell = row.createCell(headers_1.length+sum2+i);
cell.setCellStyle(style);
cell.setCellValue(headers_3[i]);
}
//重新创建一行,写入合并列中的小列
row = sheet.createRow(1);
for(int i=0; i){
final Cell cell = row.createCell(headers_1.length+i);
cell.setCellStyle(style);
cell.setCellValue(headers_4[i]);
}
// 遍历集合数据,产生数据行
Iterator> it = dataset.iterator();
int index = 1;
Map t;
XSSFRichTextString richString;
Pattern p = Pattern.compile("^//d+(//.//d+)?$");
Matcher matcher;
XSSFCell cell;
Object value;
String textValue;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
t = (Map) it.next();
for (int i = 0; i ) {
cell = row.createCell(i);
cell.setCellStyle(style2);
try {
value = t.get(keys.get(i));
// 判断值的类型后进行强制类型转换
textValue = null;
if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Float) {
textValue = String.valueOf((Float) value);
cell.setCellValue(textValue);
} else if (value instanceof Double) {
textValue = String.valueOf((Double) value);
cell.setCellValue(textValue);
} else if (value instanceof Long) {
cell.setCellValue((Long) value);
}
if (value instanceof Boolean) {
textValue = "是";
if (!(Boolean) value) {
textValue = "否";
}
} else if (value instanceof Date) {
textValue = sdf.format((Date) value);
} else {
// 其它数据类型都当作字符串简单处理
if (value != null) {
textValue = value.toString();
}
}
if (textValue != null) {
matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
richString = new XSSFRichTextString(textValue);
cell.setCellValue(richString);
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} finally {
// 清理资源
}
}
}
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
调用入口
@RequestMapping("/exportExcel/{fileName}")
public void exportExcle(@PathVariable("fileName") String fileName, HttpServletResponse response){
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
try {
response.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8") + ".xls");//03版后缀为.xls 07版后缀为.xlsx
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
List> list = new ArrayList();
for(int i=0;i){
Map map = new HashMap();
map.put("one","第"+(i+1)+"行的值");
map.put("two","第"+(i+1)+"行的值");
map.put("three","第"+(i+1)+"行的值");
map.put("four","第"+(i+1)+"行的值");
map.put("five","第"+(i+1)+"行的值");
map.put("six","第"+(i+1)+"行的值");
map.put("seven","第"+(i+1)+"行的值");
map.put("eight","第"+(i+1)+"行的值");
map.put("nine","第"+(i+1)+"行的值");
map.put("ten","第"+(i+1)+"行的值");
list.add(map);
}
List keys2 = Arrays.asList("one","two","three","four","five","six","seven","eight","nine","ten");
String[] headers_1 = {"部门","姓名"};
String[] headers_2 = {"受理量","办结量"};
String[] headers_3 = {"退件","补件"};
String[] headers_4 = {"承诺件","即办件","总量","承诺件","即办件","总量"};
int[] num = {3,3};//合并单元格各占列数
try {
ExportExcelUtil.exportExcel2003(fileName,headers_1,headers_2,headers_3,headers_4,num,list,keys2,response.getOutputStream(),"yyyy-MM-dd hh:mm:ss");
} catch (IOException e) {
e.printStackTrace();
}
}
截图
java通过poi导出excel
标签:urlencode 依赖 图片 alt jar variable get exp 集中
原文地址:https://www.cnblogs.com/lansetuerqi/p/14444491.html