最近因工作需求,需要导出符合运营人员的需求的数据,那我们就需要按照运营的数据模板给其填充相应的数据,此时Jxls就被引入到项目中,具体实现如下:
1、引入jar文件
<dependency>
<groupId>net.sf.jxls</groupId>
<artifactId>jxls-core</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.1.0</version>
</dependency>
2、excel数据模板制定(根据具体业务需求制定,因为我们模板是固定的且要对应相应的插图计算,所以这里不能使用动态追加的方式(foreach),如果对于excel中的插图复杂计算,动态追加会直接影响图形计算内容,当然如果你会VB另说)
a、选定所赋值区域最后一列
b、在所属区域内赋值(没有特殊函数的直接赋值)
c、遍历循环,在需要遍历的区域的第一个单元格处加上批注:
jx:each(items=“v.dto” var=“dto” lastCell=“D21”)
d、固定取集合中的第几个值
3、代码实现将内容写入固定的excel中
此处我用了2种方式实现:
第一种从阿里云直接拉取模板文件
public void excel(AllianceReportDto allianceReportDto,ReportDto reportDto,HttpServletResponse response ){
// 导出的excel临时路径
String filePathname = getTempPath()+"讴歌周报.xlsx";
try {
// 统一资源(从阿里云直接拉取文件)
URL url = new URL("https://xxxxxxxxx.oss-cn-hangzhou.aliyuncs.com/template/acura/ouge_report.xlsx");
// 连接类的父类,抽象类
URLConnection urlConnection = url.openConnection();
// http的连接类
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
//设置超时
httpURLConnection.setConnectTimeout(1000*5);
//设置请求方式,默认是GET(在拉取文件的时候,这个地方需要设置为get请求,否则在写入文件的时候会直接报错)
httpURLConnection.setRequestMethod("GET");
// 设置字符编码
httpURLConnection.setRequestProperty("Charset", "UTF-8");
// 打开到此 URL引用的资源的通信链接(如果尚未建立这样的连接)。
httpURLConnection.connect();
BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
// 导出的excel临时路径
OutputStream os = new FileOutputStream(filePathname);
Context context=new Context();
context.putVar("reportDto",reportDto);
context.putVar("allianceReportDto",allianceReportDto);
// 将数据放入excel中
JxlsHelper jxlsHelper = JxlsHelper.getInstance();
Transformer transformer = jxlsHelper.createTransformer(bin, os);
jxlsHelper.processTemplate(context, transformer);
//下载文件
File file=new File(filePathname);
if(file.exists()){
//export(file);
downloadFile("讴歌周报.xlsx",file,response);
File file1 = new File(filePathname);
if(file1 .exists()) {
file1.delete();
}
}
bin.close();
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
第二种直接从固定服务器位置拉取文件
public void excel1(AllianceReportDto allianceReportDto,ReportDto reportDto,HttpServletResponse response ){
// 导出的excel模板
String outTemplateDir = getTempPath()+ "ouge_report.xlsx";
// 导出的excel临时路径
String filePathname = getTempPath()+"讴歌周报.xlsx";
try {
// 导出的excel模板
InputStream is = new FileInputStream(outTemplateDir);
// 导出的excel临时路径
OutputStream os = new FileOutputStream(filePathname);
Context context=new Context();
context.putVar("reportDto",reportDto);
context.putVar("allianceReportDto",allianceReportDto);
// 将数据放入excel中
JxlsHelper jxlsHelper = JxlsHelper.getInstance();
Transformer transformer = jxlsHelper.createTransformer(is, os);
jxlsHelper.processTemplate(context, transformer);
//下载文件
File file=new File(filePathname);
if(file.exists()){
//export(file);
downloadFile("讴歌周报.xlsx",file,response);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
直到此时,excel文件已经写入你所设置的位置,那我们还需要通过浏览器来下载,以下是下载方式:
public static void downloadFile(String fileName, File file, HttpServletResponse response) throws IOException {
byte[] data = getBytesFromFile(file);
if (fileName == null || "".equals(fileName)) {
fileName = file.getName();
}
download(fileName, data, response);
}
/**
* <p>Description: 文件类型转换为byte</p>
* @param file 文件
* @return byte
*/
public static byte[] getBytesFromFile(File file) {
if (file == null) {
return null;
}
FileInputStream stream = null;
ByteArrayOutputStream out = null;
try {
stream = new FileInputStream(file);
out = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = stream.read(b)) != -1) {
out.write(b, 0, n);
}
return out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stream != null) {
stream.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* <p>Description: 单个文件下载</p>
* @param fileName 下载的文件名称(如:123.txt),若为空,则为"未命名"
* @param data 文件的字节数据
* @param response
* @throws IOException
*/
public static void download(String fileName, byte[] data, HttpServletResponse response) throws IOException {
if (fileName == null) {
fileName = "未命名";
}
if (data != null) {
response.setCharacterEncoding("UTF-8");
response.setContentLength(data.length);
response.addHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
response.setContentType("application/octet-stream");
response.getOutputStream().write(data);
response.getOutputStream().flush();
}
}
获取临时文件夹路径,每个linux服务器都有一个默认文件夹,且开放所有权限,所以小伙伴们如果没有操作公司服务器的权限,那么久请用这个默认文件夹:/tmp、具有一切操作的权限(当然,创建完临时路径问价下载完毕之后记得删除创建的临时路径)
/**
* 临时文件夹路径,模板文件路径
* @return
**/
public static String getTempPath(){
if("".equals(FILE_TEMP)){
String os = System.getProperty("os.name").toLowerCase();
if (!os.startsWith("windows")) { // 非windows系统
FILE_TEMP = "/tmp/fileTemplate/" ;
File file1 = new File(FILE_TEMP);
if(!file1 .exists()) {
file1.mkdirs();//创建目录
}
}else{
String root = ReportDataController.class.getResource("/").toString().replace("file:/", "");
FILE_TEMP = root + "fileTemplate/";
}
}
return FILE_TEMP;
}
至此,按照模板数据到出,并下载到服务器的功能已经实现完毕!