廢話少說,直入主題
html
基本思路爲 建立一個臨時文件 寫入數據 導出數據 刪除臨時文件
java
首先須要兩個jar包數據庫
antlr和stringtemplate緩存
建立數據庫中的類Row服務器
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; }
而後須要建立對應的Worksheet類app
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; }
而後須要寫兩個文件分別爲this
head.st編碼
excel
<?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>
和body.stcode
$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() }
這樣就大功告成啦,導出所用的時間大部分是花費在數據庫查詢中,固然這也是你數據庫功底的問題啦