POI3.6版本导出Excel遇到的导出乱码问题
最近开发时遇到了使用POI3.6版本时导出Excel乱码的问题,最开始以为是没有设置编码的问题,在经过大量查询之后仍没有解决方法,最后换了一种方案来实现。
首先前端准备一个按钮,实现点击按钮导出Excel的功能,前端代码如下
<button onclick="exportToExcel()">导出Excel</button>
js代码:
/** 导出Excel */
function exportToExcel() {
if (dataList.length == 0) {
return;
}
let url = location.protocol + '//' + location.host + '/mvc/coverage/export'
$.ajax({
url: url, // 后台接口地址
method: 'POST',
data: JSON.stringify(dataList), // 前台传输的数据,需要转换为JSON字符串
contentType: 'application/json;charset=UTF-8',
success: function (result) {
var binary = atob(result);
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var blob = new Blob([view], {type: "application/vnd.ms-excel"}); // 创建Blob对象
var downloadUrl = URL.createObjectURL(blob); // 创建下载链接
var a = document.createElement("a");
a.href = downloadUrl;
a.download = "data.xls";
a.click(); // 模拟点击下载链接
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(downloadUrl);
}, 100);
},
error: function (error) {
console.log(error);
console.log(JSON.parse(error.responseText));
}
});
}
最后附上接口代码:
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.apache.poi.ss.usermodel.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
/**
* Date: 2023/5/29 14:35
* FileName: CoverageController
* Description:
*/
@Controller
@RequestMapping("/coverage")
public class CoverageController {
/**
* 导出Excel数据
*
* @param dataList 需要往Excel写的数据
* @return java.lang.String
* @Date 18:39 2023/5/30
**/
@RequestMapping(value = "/export", method = RequestMethod.POST, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public String export(@RequestBody List<Map<String, Object>> dataList) throws IOException {
if (dataList.size() > 0) {
// 1. 创建Workbook对象
Workbook workbook = new HSSFWorkbook();
// 2. 创建Sheet对象,Sheet用于设置Excel文件中的表格
Sheet sheet = workbook.createSheet("Sheet1");
// 创建表头
Row headerRow = sheet.createRow(0);
// 表头,也就是第一行,可以自行设置
String[] headers = {"省级公司", "加油站数量", "覆盖加油站数量", "覆盖率(%)", "3000吨以上站点数", "3000吨以上覆盖站点数", "3000吨以上覆盖率(%)"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
}
// 3. 遍历数据,将数据写入到Sheet中
int rowIndex = 1; //excel从第二行开始写入数据
for (Map<String, Object> dataMap : dataList) {
Row row = sheet.createRow(rowIndex++);
int cellIndex = 0;
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// 创建单元格,并将数据写入单元格中
Cell cell = row.createCell(cellIndex++);
if (value == null) {
cell.setCellValue("");
} else if (value instanceof String) {
// 将String类型的数据转换成UTF-8编码格式, 且内容不能为null
String s = ((String) value);
if (s != null) {
cell.setCellValue(new String(s.getBytes("UTF-8"), "UTF-8"));
} else {
cell.setCellValue("");
}
} else if (value instanceof Number) {
// 数字类型直接输出
cell.setCellValue(Double.valueOf(value.toString()));
}
// 其他类型可以适当处理
}
}
// 4. 将Workbook转换为Base64编码,返回JSON响应
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
byte[] bytes = bos.toByteArray();
String base64Data = Base64.getEncoder().encodeToString(bytes);
return base64Data;
} else {
return "集合为空";
}
}
}