簡介
官網:http://jxls.sourceforge.net/
Jxls是一個小型Java庫,可以輕鬆生成Excel報告。Jxls在Excel模板中使用特殊標記來定義輸出格式和數據佈局。
許多具有某種報告功能的Java應用程序都需要生成Excel。
Java有很好的開源和商業庫來創建Excel文件(值得一提的是開源軟件,包括Apache POI和Java Excel API)。
從某種意義上說,這些庫是非常低級的,它們要求你編寫大量的Java代碼,甚至創建簡單的Excel文件。
總結:
1,Jxls比poi使用代碼少,有官方使用說明,易於學習和使用。
2,Jxls使用模板批註的表達式,使得導出數據時實體類字段順序無需對應excle模板字段順序。
3,導出Jxls有缺陷,但第一列爲空時,會造成後面的數據無法讀取,下面再具體說。
依賴
<!-- JXLS 核心 -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.6.0</version>
</dependency>
<!-- 基於poi實現 -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.2.0</version>
</dependency>
<!-- 讀取Excle -->
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-reader</artifactId>
<version>2.0.5</version>
</dependency>
工具類
package test.poi;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.Map.Entry;
import org.jxls.common.Context;
import org.jxls.reader.ReaderBuilder;
import org.jxls.reader.XLSReadStatus;
import org.jxls.reader.XLSReader;
import org.jxls.util.JxlsHelper;
/**
* JXLS Excel 工具類
*/
public class JXLSExcelUtil {
/**
* 導出 Excle
* @param templateRelativePathAndName 模板相對路徑和文件名
* @param data Excle模板數據
* @return
* @throws Exception
*/
public static ByteArrayOutputStream export(String templateRelativePathAndName, Map<String, Object> data) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = JXLSExcelUtil.class.getClassLoader().getResourceAsStream(templateRelativePathAndName);
if (in == null) {
throw new Exception("模板文件未找到:" + templateRelativePathAndName);
}
Context context = new Context();
for (Entry<String, Object> d : data.entrySet()) {
if (d.getKey() != null && d.getValue() != null) {
context.putVar(d.getKey(), d.getValue());
}
}
JxlsHelper.getInstance().processTemplate(in, out, context);
return out;
}
/**
* 讀取Excle數據到bean
* @param readConfigXmlRelativePathAndName 讀取配置文件
* @param inputExcelStream 輸入的excle inputSream
* @param beans 要封裝數據的bean
* @return
* @throws Exception
*/
public static boolean readExcelData(String readConfigXmlRelativePathAndName, InputStream inputExcelStream, Map<String, Object> beans) throws Exception {
InputStream in = JXLSExcelUtil.class.getClassLoader().getResourceAsStream(readConfigXmlRelativePathAndName);
if (in == null) {
throw new Exception("配置文件未找到:" + readConfigXmlRelativePathAndName);
}
InputStream inputXML = new BufferedInputStream(in);
XLSReader reader = ReaderBuilder.buildFromXML(inputXML);
XLSReadStatus readStatus = reader.read(inputExcelStream, beans);
return readStatus.isStatusOK();
}
/**
* 讀取Excle數據到bean
* @param readConfigXmlRelativePathAndName 讀取配置文件
* @param file 輸入的excle文件
* @param beans 要封裝數據的bean
* @return
* @throws Exception
*/
public static boolean readExcelData(String readConfigXmlRelativePathAndName, File file, Map<String, Object> beans) throws Exception {
if (file == null) {
throw new Exception("Excel文件爲空");
}
InputStream inputExcelStream = new FileInputStream(file);
return readExcelData(readConfigXmlRelativePathAndName, inputExcelStream, beans);
}
}
模板 這個是重點
批註一:
jx:area(lastCell=”C3”)
定義模板的根區域,可以理解爲需要處理數據的區域
批註二:
Administrator:
jx:each(items=”dataList” var=”data” lastCell=”C3”)
循環表達式
導入配置文件:
上面提到的缺陷就在這裏
“讀取終止條件, 當第一列爲空值會終止讀取數據”
暫時沒有找到理想的解決方案,可以使用poi代替。
readExcelConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<workbook>
<worksheet name="Sheet1">
<!-- section 表示固定的行數,不需要讀取的行 -->
<!-- 下標都是從0開始 -->
<section startRow="0" endRow="1"></section>
<!-- 行列與實體數據對應關係映射 -->
<loop startRow="2" endRow="2" items="dataList" var="data"
varType="test.domain.ExcelDataTest">
<section startRow="2" endRow="2">
<mapping row="2" col="0">data.column1</mapping>
<mapping row="2" col="1">data.column2</mapping>
<mapping row="2" col="2">data.column3</mapping>
</section>
<!-- 讀取終止條件, 當第一列爲空值會終止讀取數據 -->
<loopbreakcondition>
<rowcheck offset="0">
<cellcheck offset="9"></cellcheck>
</rowcheck>
</loopbreakcondition>
</loop>
</worksheet>
</workbook>
控制類
package test.controller;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import test.domain.ExcelDataTest;
import test.poi.JXLSExcelUtil;
import test.util.DownloadUtil;
import test.util.FileUtil;
@RestController
@RequestMapping("/excel")
public class ExcelController {
/**
* 導出Excel數據
* @param response
* @throws Exception
*/
@RequestMapping(value = "/export" , method = RequestMethod.GET, produces = "application/json")
public void export(HttpServletResponse response) throws Exception{
ByteArrayOutputStream baos = null;
OutputStream out = null;
try {
// excel數據 實際運用從數據庫中查詢
List<ExcelDataTest> dataList = new ArrayList<ExcelDataTest>();
ExcelDataTest data = new ExcelDataTest();
data.setColumn1(123456);
data.setColumn2("測試測試");
data.setColumn3("測試測試測試測測試測試測試");
dataList.add(data);
Map<String, Object> datas = new HashMap<>();
datas.put("dataList", dataList); // dataList與批註表達式中的items=”dataList”相同
baos = JXLSExcelUtil.export("templates/jxls測試模板.xlsx", datas);
DownloadUtil.generalDownload(response, baos, "excle導出測試.xlsx");
} catch (Exception e) {
e.printStackTrace();
throw new Exception("導出失敗:" + e.getMessage());
} finally {
if(baos != null){
baos.close();
}
if(out != null){
out.close();
}
}
}
/**
* 導入Excel數據
* @param file
*/
@RequestMapping(value = "/import", method = RequestMethod.POST)
public void importExcel(MultipartFile file) {
File f = null;
try {
// MultipartFile 轉 file
f = FileUtil.multipartFileToFile(file);
List<ExcelDataTest> list = new ArrayList<>();
Map<String, Object> beans = new HashMap<>();
beans.put("dataList", list); // dataList 來自配置文件readExcelConfig.xml的items=”dataList”
JXLSExcelUtil.readExcelData("templates/readExcelConfig.xml", f , beans);
for (ExcelDataTest data : list) {
System.out.println(data.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (f != null) {
f.delete();
}
}
}
}
下載工具類 DownloadUtil
package test.util;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
/**
* 下載工具類
*/
public class DownloadUtil {
/**
* 通用下載設置
* @param response
* @param outData 輸出數據 ByteArrayOutputStream
* @param fileName 文件名
* @throws Exception
*/
public static void generalDownload(HttpServletResponse response, ByteArrayOutputStream outData, String fileName) throws Exception{
response.setContentType( "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
ServletOutputStream out = response.getOutputStream();
outData.writeTo(out);
out.flush();
out.close();
}
/**
* 通用下載設置
* @param response
* @param outData 輸出數據 InputStream
* @param fileName 文件名
* @throws Exception
*/
public static void generalDownload(HttpServletResponse response, InputStream outData, String fileName) throws Exception{
response.setContentType( "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
ServletOutputStream out = response.getOutputStream();
byte[] bffer = new byte[1024];
int r = outData.read(bffer, 0, 1024);
while (r != -1) {
out.write(bffer);
r = outData.read(bffer, 0, 1024);
}
out.flush();
out.close();
}
/**
* 通用下載設置
* @param response
* @param outData 輸出數據 byte[]
* @param fileName 文件名
* @throws Exception
*/
public static void generalDownload(HttpServletResponse response, byte[] outData, String fileName) throws Exception{
response.setContentType( "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
ServletOutputStream out = response.getOutputStream();
out.write(outData);
out.flush();
out.close();
}
}
文件工具類 FileUtil
package test.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件工具類
*/
public class FileUtil {
/**
* MultipartFile 轉 File
* @param file
* 注意:轉換的文件保存在項目的根目錄,因此使用完要及時清理
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile multipartFile) throws Exception {
File toFile = null;
if (multipartFile != null) {
InputStream in = multipartFile.getInputStream();
toFile = new File(multipartFile.getOriginalFilename());
OutputStream os = new FileOutputStream(toFile);
int r = 0;
byte[] buffer = new byte[1024];
while ((r = in.read(buffer, 0, 1024)) != -1) {
os.write(buffer, 0, r);
}
try {
if (os != null) {
os.close();
}
} catch (Exception e) {
}
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
}
}
return toFile;
}
}