導出Excel
項目說明:
1、後臺框架springboot
2、構建工具gradle
3、前端框架layui
4、jdk版本是11
github源碼地址
項目層次結構
相關依賴包
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.apache.commons:commons-lang3:3.8.1'
implementation 'org.springframework.boot:spring-boot-starter-json'
implementation 'org.apache.poi:poi-ooxml:3.14'
implementation 'org.apache.poi:poi:3.14'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
導出excel的工具類
/**
* excel導出工具類
*
*/
public class ExportExcel {
//導出表的標題
private String title;
//導出表的列名
private String[] colName;
private List<Object[]> dataList=new ArrayList<>();
//構造函數。傳入要導入的數據
public ExportExcel(String title, String[] colName, List<Object[]> dataList) {
this.title = title;
this.colName = colName;
this.dataList = dataList;
}
/**
* 導出數據
*/
public void export(OutputStream out){
//工作薄對象
Workbook workbook = new XSSFWorkbook();
var sheet = workbook.createSheet(title);
//產生表格標題行
var rowTitle = sheet.createRow(0);
rowTitle.setHeightInPoints(30);
var cellTitle = rowTitle.createCell(0);
//表格樣式地定義
var getTitleTopStyle = this.getTitleTopStyle(workbook);
var columnTopStyle = this.getColumnTopStyle(workbook);
var style = this.getStyle(workbook);
cellTitle.setCellStyle(getTitleTopStyle);
cellTitle.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(0,
0, 0, colName.length-1));
//定義所需列數
var columnNum = colName.length;
var rowRowNmae = sheet.createRow(1);
//將列頭設置到表格的單元格中
for (var i = 0; i < columnNum; i++) {
var cellRowName = rowRowNmae.createCell(i);
cellRowName.setCellType(Cell.CELL_TYPE_STRING);
RichTextString text = new XSSFRichTextString(colName[i]);
cellRowName.setCellValue(text);
cellRowName.setCellStyle(columnTopStyle);
}
//將查詢的數據設置到sheet對應的單元格中
if (dataList.size()>0){
for (var i = 0; i < dataList.size(); i++) {
var objects = dataList.get(i);//遍歷每個對象
var row = sheet.createRow(i + 2);
for (var a = 0; a < objects.length; a++) {
var cell = row.createCell(a, HSSFCell.CELL_TYPE_STRING);
if (!"".equals(objects[a]) && objects[a] != null) {
cell.setCellValue(objects[a].toString());
} else {
cell.setCellValue("");
}
cell.setCellStyle(style);
}
}
}
//讓列寬隨着導出的列長自動適應
for (var colNum = 0; colNum < columnNum; colNum++) {
var columnWidth = sheet.getColumnWidth(colNum) / 256;
for (var rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++){
Row currentRow;
if (sheet.getRow(rowNum) == null){
currentRow=sheet.createRow(rowNum);
} else {
currentRow = sheet.getRow(rowNum);
}
if (currentRow.getCell(colNum) != null) {
Cell currentCell = currentRow.getCell(colNum);
if (currentCell.getCellType() ==Cell.CELL_TYPE_STRING) {
var length=0;
if (currentCell.getStringCellValue()!=null){
length = currentCell.getStringCellValue().getBytes().length;
}
if (columnWidth < length) {
columnWidth = length;
}
}
}
}
sheet.setColumnWidth(colNum,(columnWidth + 4) * 256);
}
if (workbook != null){
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
*列頭單元格樣式
*/
public CellStyle getColumnTopStyle(Workbook workbook) {
var styles = new HashMap<String, CellStyle>();
// 設置樣式
CellStyle style = workbook.createCellStyle();
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(CellStyle.BORDER_THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
Font dataFont = workbook.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
style.setFont(dataFont);
styles.put("data", style);
// 設置樣式
style = workbook.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
// style.setWrapText(true);
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
// 設置字體
Font headerFont = workbook.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
return style;
}
/*
*標題單元格樣式
*/
public CellStyle getTitleTopStyle(Workbook workbook) {
// 設置字體
Font font = workbook.createFont();
// 設置字體大小
font.setFontHeightInPoints((short) 13);
// 字體加粗
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
// 設置字體名字
font.setFontName("Arial");
// 設置樣式
CellStyle style = workbook.createCellStyle();
//設置單元格的水平對齊類型
style.setAlignment(CellStyle.ALIGN_CENTER);
//設置單元格的垂直對齊類型
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
// 設置低邊框
style.setBorderBottom(CellStyle.BORDER_THIN);
// 設置低邊框顏色
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 設置右邊框
style.setBorderRight(CellStyle.BORDER_THIN);
// 設置頂邊框
//style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 設置頂邊框顏色
//style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 在樣式中應用設置的字體
style.setFont(font);
// 設置自動換行
style.setWrapText(false);
// 設置水平對齊的樣式爲居中對齊;
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
return style;
}
public CellStyle getStyle(Workbook workbook) {
// 設置字體
Font font = workbook.createFont();
// 設置字體大小
font.setFontHeightInPoints((short) 10);
// 字體加粗
//font.setBoldweight(Font.BOLDWEIGHT_BOLD);
// 設置字體名字
font.setFontName("Arial");
// 設置樣式;
CellStyle style = workbook.createCellStyle();
// 設置底邊框;
style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
// 設置底邊框顏色;
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 設置左邊框;
style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
// 設置左邊框顏色;
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 設置右邊框;
style.setBorderRight(XSSFCellStyle.BORDER_THIN);
// 設置右邊框顏色;
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 設置頂邊框;
style.setBorderTop(XSSFCellStyle.BORDER_THIN);
// 設置頂邊框顏色;
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
// 在樣式用應用設置的字體;
style.setFont(font);
// 設置自動換行;
style.setWrapText(false);
// 設置水平對齊的樣式爲居中對齊;
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
// 設置垂直對齊的樣式爲居中對齊;
style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
return style;
}
}
Service層
@Service
public class ExcelService {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelService.class);
//excel標題
private String title = "";
//表格數據
private List<Object[]> dataList;
//excel列頭信息
private String[] colsName;
/**
* 導出excel
*/
public void exportExcel(HttpServletResponse response){
title = "導入標題";
dataList = new ArrayList<Object[]>();
colsName = new String[] { "書籍編號", "借書人", "借書時間", "預計還書時間", "借書狀態" };
for (int i = 0; i < 6; i++) {
var objects = new Object[colsName.length];
objects[0] = "HK200"+i;
objects[1] = "小明"+i;
Timestamp currentTimestamp=Timestamp.valueOf(LocalDateTime.now());
objects[2] = currentTimestamp;
objects[3] = "未定";
if (i%2 == 0) {
objects[4] = "借書中";
}else {
objects[4] = "已還書";
}
dataList.add(objects);
}
try {
response.reset();
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode("導出表名.xlsx", "UTF-8"));
var out = response.getOutputStream();
var exportExcel = new ExportExcel(title, colsName, dataList);
exportExcel.export(out);
out.flush();
out.close();
LOGGER.info("導出Excel成功");
} catch (IOException e) {
e.printStackTrace();
LOGGER.info("導出Excel失敗");
}
}
/**
*導入excel
*/
public JsonNode importExcel(MultipartFile file){
var root= JsonUtil.OBJECT_MAPPER.createObjectNode();
root.put("result","fail");
if (file.isEmpty()){
root.put("cause","必要參數未找到");
return root;
}
ImportExcel excel;
try {
excel=new ImportExcel(file);
}catch (Exception e){
root.put("cause","文件識別失敗");
return root;
}
try {
dataList=excel.getColNames();
} catch (IOException e) {
e.printStackTrace();
root.put("cause","數據解析失敗");
return root;
}
//dataList表示拿到excel的數據列表,這裏不做存儲,只輸出
dataList.forEach(data->{
for (var i=0;i<data.length-1;i++){
System.out.print(data[i]+"\t");
}
System.out.println();
});
root.put("result","success");
return root;
}
}
Controller層
@Controller
public class ExcelController {
private ExcelService excelService;;
@Autowired
public ExcelController(ExcelService excelService) {
this.excelService = excelService;
}
@GetMapping(value = "export",produces = "application/json;charset=UTF-8")
public void export(HttpServletResponse response) {
excelService.exportExcel(response);
}
@PostMapping(value = "import",produces = "application/json;charset=UTF-8")
@ResponseBody
public JsonNode importAsset(@RequestParam("file") MultipartFile multipartFile) {
return excelService.importExcel(multipartFile);
}
@GetMapping("/index")
public String index() {
return "web/index";
}
}
前端頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>excel的導入與導出</title>
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" media="all" />
</head>
<body>
<button onclick="exportExcel();"><h4>導出Excel</h4></button></br>
<fieldset class="layui-elem-field " style="margin-top: 30px;">
<legend>選擇要導入的資產文件</legend>
</fieldset>
<div class="layui-upload">
<button type="button" class="layui-btn " id="test8"><i class="layui-icon"></i>選擇文件</button>
<button type="button" class="layui-btn" id="test9">開始上傳</button>
</div>
</body>
<script type="text/javascript" th:src="@{/layui/layui.js}"></script>
<script>
layui.use('upload', function() {
var $ = layui.jquery,
upload = layui.upload;
upload.render({
elem: '#test8',
url: 'http://localhost/import', //改成您自己的上傳接口
auto:false,
accept: 'file',
bindAction: '#test9',
done: function(res){
if (res['result'] == 'fail'){
layer.msg(res['cause']);
} else{
layer.msg('上傳成功');
}
console.log(res)
}
});
})
//excel導出
function exportExcel() {
window.location.href="http://localhost/export";
}
</script>
</html>
最後實現效果
導入excel的工具類(其它方法在上面類中已經寫好)
/**
* 導入excel內容的工具類
* @author ClowLAY
* create date 2020/3/25
*/
public class ImportExcel {
//文件對象
private MultipartFile file;
/**
* 工作薄對象
*/
private Workbook workbook;
public ImportExcel(MultipartFile file){
this.file = file;
}
/**
* 返回除標題的外的所有數據,第一個對象數組爲列數據
* @return
*/
public List<Object[]> getColNames() throws IOException {
var dataList=new ArrayList<Object[]>();
var rowSize=0;
//根據excel表格式新建表對象
var in = new BufferedInputStream(file.getInputStream());
if (StringUtils.isBlank(file.getOriginalFilename())) {
throw new IOException("Import file is empty!");
} else if (file.getOriginalFilename().toLowerCase().endsWith("xls")) {
this.workbook = new HSSFWorkbook(in);
} else if (file.getOriginalFilename().toLowerCase().endsWith("xlsx")) {
this.workbook = new XSSFWorkbook(in);
} else {
throw new IOException("Invalid import file type!");
}
Cell cell=null;
for (var sheetIndex=0;sheetIndex<workbook.getNumberOfSheets();sheetIndex++){
//獲取指定索引的表對象
var sheetAt = workbook.getSheetAt(sheetIndex);
//第一行作爲標題,不取
for (var rowIndex=1;rowIndex<=sheetAt.getLastRowNum();rowIndex++) {
var row=sheetAt.getRow(rowIndex);
if (row == null){
continue;
}
//獲取一列單元格數量
var tempRowSize = row.getLastCellNum();
if (tempRowSize > rowSize){
rowSize = tempRowSize;
}
var values=new Object[rowSize];
boolean hasValue = false;
for (var columnIndex = 0 ;columnIndex < row.getLastCellNum(); columnIndex++ ){
Object value="";
cell = row.getCell(columnIndex);
if (cell != null){
switch (cell.getCellType()){
case Cell.CELL_TYPE_STRING :
value = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_NUMERIC :
if (HSSFDateUtil.isCellDateFormatted(cell)){
var date=cell.getDateCellValue();
if (date != null){
value = new SimpleDateFormat("yyyy-MM-dd").format(date);
}else
value="";
} else {
value= new DecimalFormat("0").format(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_FORMULA :
value=cell.getCellFormula();
break;
case Cell.CELL_TYPE_BOOLEAN :
value=cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK :
value="";
break;
case Cell.CELL_TYPE_ERROR :
value=cell.getErrorCellValue();
break;
default :
value="";
}
}
//如果當前行的第一列爲空,則跳過
if (columnIndex == 0 && value.toString().trim().equals("")) {
break;
}
values[columnIndex] = value.toString().trim();
hasValue = true;
}
if (hasValue) {
dataList.add(values);
}
}
}
in.close();
return dataList;
}
/**
* 導入測試
*/
/*public static void main(String[] args) throws Throwable {
ImportExcel excel = new ImportExcel(new File("D:/2020-03-23.xlsx"));
var dataList=excel.getColNames();
System.out.println("size="+dataList.size());
dataList.forEach(data->{
for (var i=0;i<data.length-1;i++){
System.out.print(i+","+data[i]+"\t");
}
System.out.println();
});
}*/
}
最後把獲取的表內容輸出到控制檯