java匯出大量的excel
阿新 • • 發佈:2019-02-04
廢話少說,直入主題
基本思路為 建立一個臨時檔案 寫入資料 匯出資料 刪除臨時檔案
首先需要兩個jar包
antlr和stringtemplate
建立資料庫中的類Row
然後需要建立對應的Worksheet類private String name1; private String name2; private String name3; public String getName1() { return name1; } public void setName1(String name1) { this.name1 = name1; } public String getName2() { return name2; } public void setName2(String name2) { this.name2 = name2; } public String getName3() { return name3; } public void setName3(String name3) { this.name3 = name3; }
<span style="font-size:10px;">private int columnNum; private int rowNum; private List<Row> rows; private List<SfOrder> orders; public List<SfOrder> getOrders() { return orders; } public void setOrders(List<SfOrder> orders) { this.orders = orders; } public String getSheet() { return sheet; } public void setSheet(String sheet) { this.sheet = sheet; } public List<Row> getRows() { return rows; } public void setRows(List<Row> rows) { this.rows = rows; } public int getColumnNum() { return columnNum; } public void setColumnNum(int columnNum) { this.columnNum = columnNum; } public int getRowNum() { return rowNum; } public void setRowNum(int rowNum) { this.rowNum = rowNum; }</span>
然後需要寫兩個檔案分別為
head.st
和body.st<?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"> <Created>1996-12-17T01:32:42Z</Created> <LastSaved>2013-08-02T09:21:24Z</LastSaved> <Version>11.9999</Version> </DocumentProperties> <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"> <RemovePersonalInformation/> </OfficeDocumentSettings> <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"> <WindowHeight>4530</WindowHeight> <WindowWidth>8505</WindowWidth> <WindowTopX>480</WindowTopX> <WindowTopY>120</WindowTopY> <AcceptLabelsInFormulas/> <ProtectStructure>False</ProtectStructure> <ProtectWindows>False</ProtectWindows> </ExcelWorkbook> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="宋體" x:CharSet="134" ss:Size="12"/> <Interior/> <NumberFormat/> <Protection/> </Style> </Styles>
$worksheet:{
<Worksheet ss:Name="$it.sheet$">
<Table ss:ExpandedColumnCount="$it.columnNum$" ss:ExpandedRowCount="$it.rowNum$" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">
$it.rows:{
<Row>
<Cell><Data ss:Type="String">$it.name1$</Data></Cell>
</Row>
}$
</Table>
</Worksheet>
}$
下面就是程式程式碼
首先你要從資料中查詢資料,假設你查詢的資料為List資料
//我這裡的list是從map中獲取的你可以直接獲取
List<Row> list=(List<Row>) result.get("list");
list=(List<SfOrder>) result.get("list");
if(list.size()==0){
return null;
}
long startTimne = System.currentTimeMillis();
StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");
stGroup.setFileCharEncoding("UTF-8");//設定編碼,否則有亂碼,匯出excel格式不正確
//寫入excel檔案頭部資訊
StringTemplate head = stGroup.getInstanceOf("/template/head");
String path=request.getSession().getServletContext().getRealPath("/upload/excel/test1.xls");
File file = new File(path);
PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));
writer.print(head.toString());
writer.flush();
int sheets = 10;
//excel單表最大行數是65535
int maxRowNum = 3000;
int maxRowNumLast=0;
//計算要分幾個sheet
sheets=(list.size()%maxRowNum==0) ? list.size()/maxRowNum:list.size()/maxRowNum+1;
//計算最後一個sheet有多少行
maxRowNumLast=list.size()-(sheets-1)*maxRowNum;
上面為預備階段,下面則直接向檔案寫資料
//寫入excel檔案資料資訊
for(int i=0;i<sheets;i++){
Integer nums=0;
StringTemplate body = stGroup.getInstanceOf("/template/body");
Worksheet worksheet = new Worksheet();
worksheet.setSheet(" "+(i+1)+" ");
worksheet.setColumnNum(3);
worksheet.setRowNum(maxRowNum);
List<Row> orders = new ArrayList<Row>();
if(i==(sheets-1)){
for(int j=0;j<maxRowNumLast;j++){
nums=i*maxRowNumLast+j;
SfOrder order=new SfOrder();
order.setOrderId(list.get(nums).getOrderId());
orders.add(order);
}
}else{
for(int j=0;j<maxRowNum;j++){
nums=i*maxRowNum+j;
Row order=new Row();
order.setOrderId(list.get(nums).getOrderId());
orders.add(order);
}
}
worksheet.setOrders(orders);
body.setAttribute("worksheet", worksheet);
writer.print(body.toString());
writer.flush();
orders.clear();
orders = null;
worksheet = null;
body = null;
Runtime.getRuntime().gc();
System.out.println("正在生成excel檔案的 sheet"+(i+1));
}
下面則寫入伺服器磁碟
//寫入excel檔案尾部
writer.print("</Workbook>");
writer.flush();
writer.close();
System.out.println("生成excel檔案完成");
long endTime = System.currentTimeMillis();
System.out.println("用時="+((endTime-startTimne)/1000)+"秒");
下面要讀取檔案,即正式的匯出
//建立file物件
File upload=new File(path);
//設定response的編碼方式
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition","attachment;filename=ceshi.xls");
//讀出檔案到i/o流
FileInputStream fis=new FileInputStream(upload);
BufferedInputStream buff=new BufferedInputStream(fis);
byte [] b=new byte[1024];//相當於我們的快取
long k=0;//該值用於計算當前實際下載了多少位元組
//從response物件中得到輸出流,準備下載
OutputStream myout=response.getOutputStream();
//開始迴圈下載
while(k<upload.length()){
int j=buff.read(b,0,1024);
k+=j;
//將b中的資料寫到客戶端的記憶體
myout.write(b,0,j);
}
//將寫入到客戶端的記憶體的資料,重新整理到磁碟
myout.flush();
myout.close();
如果需要可以,比如這個檔案是動態的我們可以讓這個檔案是動態的,就要將此檔案刪除
File fileDel = new File(path);
// 如果檔案路徑所對應的檔案存在,並且是一個檔案,則直接刪除
if (fileDel.exists() && file.isFile()) {
fileDel.delete()
}
這樣就大功告成啦,匯出所用的時間大部分是花費在資料庫查詢中,當然這也是你資料庫功底的問題啦