1. 程式人生 > >java匯出大量的excel

java匯出大量的excel

廢話少說,直入主題

基本思路為  建立一個臨時檔案 寫入資料 匯出資料  刪除臨時檔案

首先需要兩個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類
<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

<?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.st
 $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()
                       }
這樣就大功告成啦,匯出所用的時間大部分是花費在資料庫查詢中,當然這也是你資料庫功底的問題啦