版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_28068985/article/details/83035727
针对各个表的数据导出,实现的代码往往相似,出于这个目的,开启自己代码简略之旅。本文是针对.xls的excel文件。
1、思路描述
①、确定各个模板的.xls文件格式
②、定义模板的存在的参数,如第一行的参数,第二行的参数等
③、excel文件中针对行 列定位方式,如 (0, 0, 0,0)
④、处理从数据库获取的数据格式key-value 如 name 小明
如下图,本篇幅就围绕下图展开:
2、代码如下:(向前端返回的下载路径)
controller类的方法
@ApiOperation(value = "导出地址数据")
@PostMapping(value="/exportAddresses")
public ApiResponse<Object> exportAddresses(){
ApiResponse<Object> resp = new ApiResponse<Object>();
// 数据库表对应的字段
String[] titles = new String[] {"id","name","pid","code","description"};
List<Map<String,Object>> objList = new ArrayList<>();
// 数据库表对应的数据
List<AddressVo> list = addressService.exportAddresses();
for(AddressVo item : list){
Map<String,Object> tempMap = new HashMap<>();
tempMap.put("id", item.getId());
tempMap.put("name", item.getName());
tempMap.put("pid", item.getPid());
tempMap.put("code", item.getCode());
tempMap.put("description", item.getDescription());
objList.add(tempMap);
}
String path = FileUtil.exportExcel("地址树",titles,objList);
System.out.println("path="+path);
if(path == null){
resp.error("导出失败!");
}
resp.ok("导出成功!").setData(path);
return resp;
}
FileUtil 类
public class FileUtil <T> {
// 挂在项目的某文件夹下
public static final String REPORT_PATH ="templates"+ File.separator;
/**
* 导出数据
* @auther xuguocai
* @param fileName 文件名
* @param titles 字段名
* @param result 导出数据
* @throws IOException
*/
public static String exportExcel(String fileName,String[] titles,List<Map<String,Object>> result){
HSSFWorkbook wb;
FileOutputStream fos;
String tempName = fileName;
try {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
fileName +="_"+df.format(date)+".xls";
fos = new FileOutputStream(FileUtil.REPORT_PATH + fileName);
wb= new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
// 设置列宽
for(int i = 0; i < titles.length-1; i++){
sh.setColumnWidth( i, 256*15+184);
}
// 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
HSSFRow row = sh.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue(new HSSFRichTextString(tempName));
cell.setCellStyle(fontStyle(wb));
sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));
// 第二行
HSSFRow row3 = sh.createRow(1);
// 第二行的列
for(int i=0; i < titles.length; i++){
cell = row3.createCell(i);
cell.setCellValue(new HSSFRichTextString(titles[i]));
cell.setCellStyle(fontStyle(wb));
}
//填充数据的内容 i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
int i = 2, z = 0;
while (z < result.size()) {
row = sh.createRow(i);
Map<String,Object> map = result.get(z);
for(int j=0;j < titles.length;j++) {
cell = row.createCell(j);
if(map.get(titles[j]) !=null) {
cell.setCellValue(map.get(titles[j]).toString());
}else {
cell.setCellValue("");
}
}
i++;
z++;
}
wb.write(fos);
fos.flush();
fos.close();
return FileUtil.REPORT_PATH + fileName;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
3、向前端返回文件流的形式
controller类
@ApiOperation(value = "导出地址数据")
@PostMapping(value="/exportAddresses")
public ApiResponse<Object> exportAddresses(HttpServletResponse response){
ApiResponse<Object> resp = new ApiResponse<Object>();
String[] titles = new String[] {"id","name","pid","code","description"};
List<Map<String,Object>> objList = new ArrayList<>();
List<AddressVo> list = addressService.exportAddresses();
for(AddressVo item : list){
Map<String,Object> tempMap = new HashMap<>();
tempMap.put("id", item.getId());
tempMap.put("name", item.getName());
tempMap.put("pid", item.getPid());
tempMap.put("code", item.getCode());
tempMap.put("description", item.getDescription());
objList.add(tempMap);
}
try {
FileUtil.exportExcel(response,"地址树",titles,objList);
resp.ok("导出成功!");
}catch (Exception e){
e.printStackTrace();
resp.error("导出失败!");
}
return resp;
}
FileUtil 类
public static void exportExcel(HttpServletResponse response,String fileName,String[] titles,List<Map<String,Object>> result){
HSSFWorkbook wb;
OutputStream output = null;
String tempName = fileName;
try {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
fileName +="_"+df.format(date)+".xls";
wb= new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
// 设置列宽
for(int i = 0; i < titles.length-1; i++){
sh.setColumnWidth( i, 256*15+184);
}
// 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
HSSFRow row = sh.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue(new HSSFRichTextString(tempName));
cell.setCellStyle(fontStyle(wb));
sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));
// 第二行
HSSFRow row3 = sh.createRow(1);
// 第二行的列
for(int i=0; i < titles.length; i++){
cell = row3.createCell(i);
cell.setCellValue(new HSSFRichTextString(titles[i]));
cell.setCellStyle(fontStyle(wb));
}
//填充数据的内容 i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
int i = 2, z = 0;
while (z < result.size()) {
row = sh.createRow(i);
Map<String,Object> map = result.get(z);
for(int j=0;j < titles.length;j++) {
cell = row.createCell(j);
if(map.get(titles[j]) !=null) {
cell.setCellValue(map.get(titles[j]).toString());
}else {
cell.setCellValue("");
}
}
i++;
z++;
}
output = response.getOutputStream();
response.reset();
response.setHeader("Content-disposition", "attachment; filename="+fileName);
response.setContentType("application/msexcel");
wb.write(output);
output.flush();
output.close();
}catch (Exception e){
e.printStackTrace();
}
}
4、下载,后台返回的是文件流
responseType详解
值 | 数据类型 |
---|---|
’ ‘ | DOMString (这个是默认类型),是一个UTF-16字符串。由于JavaScript已经使用了这样的字符串,所以DOMString 直接映射到 一个String 。 |
arraybuffer | ArrayBuffer对象,表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。详解:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer |
blob | Blob对象,表示不可变的类似文件对象的原始数据。Blob表示不一定是JavaScript原生形式的数据 |
document | Document对象,表示任何在浏览器中已经加载好的网页,并作为一个入口去操作网页内容(也就是DOM tree)。DOM tree包括像 <body> 、<table> 这样的还有其他的元素。它提供了全局操作document的功能,像获取网页的URL和在document里创建一个新的元素 |
json | JavaScript object, parsed from a JSON string returned by the server |
text | DOMString |
①、不携带参数请求,
// url 向后台请求的接口 ,fileName 下载赋予的文件名
downloadFile(url , fileName){
this.$ajax.get(url, {responseType: 'arraybuffer'}).then((res) => {
let data = res.data
if (!data) {
return
}
let url = window.URL.createObjectURL(new Blob([data]))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = fileName;
document.body.appendChild(link)
link.click()
window.URL.revokeObjectURL(link.href);
}).catch(err=>{
})
},
②携带参数请求,可以将参数放进请求路径中,如url=/api/department/downloadDepartmentTemplate?isVirtual=0
5、总结
以上简单介绍了动态生成excel文件和向前端传文件路径 向前端传文件流的两种形式。仅供自己学习和代码积累。简简单单,首要原则是方便自己,谢谢。