Excel 文件导出
前台导出
前台导出是指使用前台页面的数据导出到本地文件
XML文件和Excel文件之间可以相互转换,因此可将 XML 数据从 Web 服务中导入到 Excel 工作表中。
使用隐藏的Table存放需要导出的数据,构建模板文件(一个html格式文件,可以设置一些属性和格式),将table中的数据添加到模板中,通过base64加密,使用 data:application/vnd.ms-excel;base64 将数据流传送到本地,完成导出功能。
前台导出是将静态页面(包含数据的table)下载到本地
模板:
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<!--[if gte mso 9]>
<xml>
<x:ExcelWorkbook>
<x:ExcelWorksheets>
<x:ExcelWorksheet>
<x:Name>sheet页名称</x:Name>
<x:WorksheetOptions>
<x:DisplayGridlines />
</x:WorksheetOptions>
</x:ExcelWorksheet>
</x:ExcelWorksheets>
</x:ExcelWorkbook>
</xml>
<![endif]-->
</head>
<body>
<table>
</table>
</body>
</html>
实现:
var worksheet = 'sheet名称'
var uri = 'data:application/vnd.ms-excel;base64,';
// 获取table元素
var strsheet = $("#table_temp").html();
// 下载的表格模板数据
// 将table数据插入模板中
var template = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"";
template += "xmlns:x=\"urn:schemas-microsoft-com:office:excel\"";
template += "xmlns=\"http://www.w3.org/TR/REC-html40\">";
template += "<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>";
template += "<x:Name>" + worksheet + "</x:Name>";
template += "<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>";
template += "</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->";
template += "</head><body><table>" + strsheet + "</table></body></html>";
//下载模板
window.location.href = uri + base64(template);
// base64加密
function base64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
兼容IE
// 导出入口
function ExportExcel(tableId) {
IeAndGoogleExcel(tableId);
}
function getExplorer() {
var explorer = window.navigator.userAgent;
//ie
//if (explorer.indexOf("MSIE") >= 0) { ---只支持IE10以下版本
if (!!window.ActiveXObject || "ActiveXObject" in window) {
//--支持IE6-IE11
return 'ie';
}
//firefox
else if (explorer.indexOf("Firefox") >= 0) {
return 'Firefox';
}
//Chrome
else if (explorer.indexOf("Chrome") >= 0) {
return 'Chrome';
}
//Opera
else if (explorer.indexOf("Opera") >= 0) {
return 'Opera';
}
//Safari
else if (explorer.indexOf("Safari") >= 0) {
return 'Safari';
}
}
function IeAndGoogleExcel(tableid) {
//整个表格拷贝到EXCEL中
if (getExplorer() == 'ie') {
AllAreaExcel(tableid);//只支持ie的导出方式
}
else {
tableToExcel(tableid)//支持非ie浏览器的导出方法
}
}
function AllAreaExcel(tableId) {
try {
var curTbl = document.getElementById(tableId);
var oXL;
oXL = new ActiveXObject("Excel.Application"); //创建AX对象excel
var oWB = oXL.Workbooks.Add(); //获取workbook对象
var oSheet = oWB.ActiveSheet;//激活当前sheet
var sel = document.body.createTextRange();
sel.moveToElementText(curTbl); //把表格中的内容移到TextRange中
try {
sel.select(); //全选TextRange中内容
} catch (e1) {
e1.description
}
sel.execCommand("Copy");//复制TextRange中内容
oSheet.Paste();//粘贴到活动的EXCEL中
oXL.Visible = true; //设置excel可见属性
// var fname = oXL.Application.GetSaveAsFilename("fileName" + ".xls", "Excel Spreadsheets (*.xls), *.xls");
// oWB.SaveAs(fname);
oWB.Close();
oXL.Quit();
} catch (e) {
alert(e.description);
}
}
var tableToExcel = (function () {
var worksheet = 'sheetName'
var uri = 'data:application/vnd.ms-excel;base64,';
var strsheet = $("#group_info").html();
//下载的表格模板数据
var template = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"";
template += "xmlns:x=\"urn:schemas-microsoft-com:office:excel\"";
template += "xmlns=\"http://www.w3.org/TR/REC-html40\">";
template += "<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>";
template += "<x:Name>" + worksheet + "</x:Name>";
template += "<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>";
template += "</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->";
template += "</head><body><table>" + strsheet + "</table></body></html>";
//下载模板
window.location.href = uri + base64(template);
});
后台导出
后台导出指数据在后台写入临时文件,再将文件以流的形式传递到前台。
POI
官网文档:http://poi.apache.org/components/index.html
Apache POI 是用 Java 编写的免费开源的 Java API
Apache POI 提供 API 对 Microsoft Office 格式文档读和写的功能,包括 excel、world、ppt。
思路:
调用服务获取需要导出的数据,使用 POI 提供的API 创建临时文件,并将数据写入文件中。再将文件以流的形式传递到前端。
pom 引入下面依赖:
<!--POI Office 文档的 Java 处理包-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${pioVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${pioVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${pioVersion}</version>
</dependency>
创建excel文件,放入需要的数据
// 新建workbook对象
Workbook wb = new HSSFWorkbook();
// 创建 sheet页对象
Sheet sheetName = wb.createSheet("sheetName");
// 创建行对象; 从第0行开始
Row row = sheetName.createRow(0);
// cell最小单元各
Cell cell = row.createCell(0);
cell.setCellValue("0,0");
row.createCell(1).setCellValue("1,0");
row.createCell(2).setCellValue("2,0");
// 使用循环可将list数据按照自定义格式写入excel文件中
// 更多设置 比如换行、样式、字体等参考文档api
// 将数据写入输出流生成文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
wb.write(fileOut);
}
将后台文件以流的形式反给前台
例子:可作为公共的导出接口,将临时文件写好后调用该服务返回前台
@PostMapping("/Export")
@Override
public ResponseEntity<byte[]> cdrDetailExport(@RequestParam(name = "FILE_NAME") String fileName, HttpServletResponse response) {
// 获取配置的文件路径
String filePath = EnvCfgUtil.getStrValue("exportfile-path");
try{
File cdrFile = new File(filePath+"/"+fileName);
if(cdrFile.exists()){
FileInputStream inputStream = null;
try{
inputStream = new FileInputStream(cdrFile);
byte[] body = StreamUtils.copyToByteArray(inputStream);
response.setContentType("application/vnd.ms-excel;charset=gbk");
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
headers.add("Content-Disposition", "attachment;filename=" +fileName);
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(body.length));
ResponseEntity<byte[]> rsp = new ResponseEntity(body, headers, HttpStatus.OK);
return rsp;
}catch (Exception e) {
e.printStackTrace();
log.error("文件导出失败[{}]", e.getMessage());
throw new BusiException("10111020000040203", "文件导出失败");
} finally {
if (null != inputStream) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
log.error("文件导出失败[{}]", e.getMessage());
throw new BusiException("10111020000040203", "文件导出失败");
}
}
cdrFile.delete();
}
}
}catch(Exception e){
e.printStackTrace();
log.error("文件导出失败[{}]", e.getMessage());
throw new BusiException("10111020000040203", "文件导出失败");
}
return null;
}