<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小石頭
    Excellence in any department can be attained only by the labor of a lifetime; it is not to be purchased at a lesser price.
    posts - 91,comments - 22,trackbacks - 0

    ??? 前些天做了一個EXCEL數據下載的東西,發(fā)現當數據超過10萬行之后,就會內存溢出(用的是本機TOMCAT測試,內存有限,沒能調過),新做一種方式,來感覺一下,發(fā)現速度有點慢,其他還可以.?

    一、問題描述

    ??? 該問題出現是因為在導出文件之后 用戶下載的是 .csv 文件,如果用文本編輯器打開可以查看所有記錄,但是如果用 excel 打開就出現一個 sheet 最多 6 萬條的記錄。因此就不可以使用保存為 csv 文件來實現 excel 文件的下載,需要使用新的方式去實現。

    ??? 如果使用 jxl 開發(fā)包在 web 后臺去創(chuàng)建 Excel 文件,如果數據量比較大,則用戶需要等待很長很長的時間才可以下載到,因為 jxl 的對于 excel 文件的操作都是對象級的 , 文件中每一個格子都是一個 cell 對象,需要后臺去 new 。所以還需要考慮別的方式。

    ???

    二、實現靈感

    ??? Excel 文件打開之后選擇另存為可以保存為 XML 類型文件,因此就考慮構造符合 Excel 可以打開的 XML 類型文件,并且對該 XML 文件進行最簡單化處理,去除 Excel 文件中的每個 cell style 定義、 XML 文件頭部的多余信息,最后整理出一個符合資訊平臺所下載的 Excel 文件的格式 , 請看下面:

    ?

    ?

    <!—XML 文件頭部 --//>

    <?xml version="1.0"?>

    <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">

    ?

    <!—Excel 文件第一個 SHEET --//>

    <Worksheet ss:Name="sheet0">

    <Table>

    <Row>

    <Cell><Data ss:Type="String">aa0</Data></Cell>

    <Cell><Data ss:Type="String">aa1</Data></Cell>

    <Cell><Data ss:Type="String">aa2</Data></Cell>

    </Row>

    <Row>

    <Cell><Data ss:Type="String">aa0</Data></Cell>

    <Cell><Data ss:Type="String">aa1</Data></Cell>

    <Cell><Data ss:Type="String">aa2</Data></Cell>

    </Row>

    </Table>

    </Worksheet>

    ?

    <!—Excel 文件第二個 SHEET --//>

    <Worksheet ss:Name="sheet1">

    <Table>

    ??? <!— 一行數據 --//>

    <Row>

    <Cell><Data ss:Type="String">aa0</Data></Cell>

    <Cell><Data ss:Type="String">aa1</Data></Cell>

    <Cell><Data ss:Type="String">aa2</Data></Cell>

    </Row>

    <Row>

    <Cell><Data ss:Type="String">aa0</Data></Cell>

    <Cell><Data ss:Type="String">aa1</Data></Cell>

    <Cell><Data ss:Type="String">aa2</Data></Cell>

    </Row>

    </Table>

    </Worksheet>

    ?

    </Workbook>

    ?

    <!-- XML 文件結束 --//>

    ?

    ?

    注釋:

    a 、 <Worksheet ss:Name="sheet0">? 引號內部的是該 sheet 的名稱。

    b <Data ss:Type="String">aa1</Data> ?ss:Type 的值是用來定義該 cell 格數據的類型,例如可以為 Number, 表是該 cell 格數據是數字。

    ?

    ?

    三、實現方式

    ??? 通過第一步的分析可以發(fā)現只要我們構建這樣格式的 XML 數據,就可以通過 Excel 打開,并且可以實現分 sheet 的樣式。但是數據下載到用戶本地是 XML 類型的話,那是沒什么意義的,就算打開方式選擇使用 Excel 可以打開,因此如何將用戶下載的文件類型改為 XLS 呢?這里就可以通過在下載的 servlet 中設置 response.setContentType("application/vnd.ms-excel") 來實現。
    我實現了五個類來封閉XML字符串(CellData,TableCell,TableRow,WorkBook,WorkSheet),寫了一個測試類

    package com.hoten.util.xmlxls;

    import java.util.List;
    import java.util.ArrayList;

    public class WorkBook {
    ?private final static String XML_HEARDER = "<?xml version=\"1.0\"?>";
    ?
    ?private List sheetList = new ArrayList(); //存放每行多個sheet的list
    ?
    ?/**
    ? * 取得workbook的xml文件的頭部字符串
    ? * @return
    ? */
    ?private String getHeader(){??
    ??return XML_HEARDER +
    ??? "<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"" + Contants.SEP_N +
    ??? " xmlns:o=\"urn:schemas-microsoft-com:office:office\"" + Contants.SEP_N +
    ??? " xmlns:x=\"urn:schemas-microsoft-com:office:excel\"" +? Contants.SEP_N +
    ??? " xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"" + Contants.SEP_N +
    ??? " xmlns:html=\"http://www.w3.org/TR/REC-html40\">" + Contants.SEP_N ;
    ?}?
    ?
    ?private String getFoot(){
    ??return "</Workbook>";
    ?}
    ?
    ?public String toString(){
    ??StringBuffer strBuff = new StringBuffer();
    ??
    ??strBuff.append(getHeader());
    ??
    ??int len = sheetList.size();
    ??for(int i=0;i<len;i++){
    ???WorkSheet sheet = (WorkSheet)sheetList.remove(0);
    ???strBuff.append(sheet.toString());
    ???sheet = null;
    ??}??
    ??sheetList.clear();
    ??
    ??strBuff.append(getFoot());
    ??
    ??return strBuff.toString();
    ?}
    ?
    ?public void addSheet(WorkSheet sheet){
    ??sheetList.add(sheet);
    ?}
    ?
    ?public void removeSheet(int i){
    ??sheetList.remove(i);
    ?}??
    }


    package com.hoten.util.xmlxls;

    import java.util.List;
    import java.util.ArrayList;

    public class WorkSheet {
    ?
    ?private String name = ""; //該sheet的name
    ?
    ?private List rowList = new ArrayList(); //存放每行多個row的list
    ?
    ?public String toString(){
    ??StringBuffer strBuff = new StringBuffer();
    ??
    ??strBuff.append("<Worksheet ss:Name=\"" + name + "\">").append(Contants.SEP_N);
    ??strBuff.append("<Table>").append(Contants.SEP_N);
    ??
    ??int len = rowList.size();
    ??for(int i=0;i<len;i++){
    ???TableRow row = (TableRow)rowList.remove(0);
    ???strBuff.append(row.toString());
    ???row = null;
    ??}??
    ??rowList.clear();
    ??
    ??strBuff.append("</Table>").append(Contants.SEP_N);
    ??strBuff.append("</Worksheet>").append(Contants.SEP_N);
    ??
    ??return strBuff.toString();
    ?}
    ?
    ?public void addRow(TableRow row){
    ??rowList.add(row);
    ?}
    ?
    ?public void removeRow(int i){
    ??rowList.remove(i);
    ?}

    ?public String getName() {
    ??return name;
    ?}

    ?public void setName(String name) {
    ??this.name = name;
    ?}?
    }


    package com.hoten.util.xmlxls;

    import java.util.List;
    import java.util.ArrayList;

    public class TableRow {

    ?private List cellList = new ArrayList(); //存放每行多個cell的list
    ?
    ?
    ?public String toString(){
    ??StringBuffer strBuff = new StringBuffer();
    ??
    ??strBuff.append("<Row>").append(Contants.SEP_N);

    ??//循環(huán)顯示每行的cell
    ??int len = cellList.size();
    ??for(int i=0;i<len;i++){
    ???TableCell cell = (TableCell)cellList.remove(0);
    ???strBuff.append(cell.toString()).append(Contants.SEP_N);
    ???cell = null;???
    ??}
    ??cellList.clear();
    ??
    ??strBuff.append("</Row>").append(Contants.SEP_N);
    ??
    ??return strBuff.toString();
    ?}?
    ?
    ?public void addCell(TableCell cell){
    ??cellList.add(cell);
    ?}
    ?
    ?public void removeCell(int i){
    ??cellList.remove(i);
    ?}
    ?
    }


    package com.hoten.util.xmlxls;

    public class TableCell {
    ?private String index = ""; //cell在每行顯示的索引位置,可以不填
    ?
    ?private CellData data = new CellData(); //cell的數據對象

    ?public CellData getData() {
    ??return data;
    ?}

    ?public void setData(CellData data) {
    ??this.data = data;
    ?}

    ?public String getIndex() {
    ??return index;
    ?}

    ?public void setIndex(String index) {
    ??this.index = index;
    ?}
    ?
    ?
    ?public String toString(){
    ??return "<Cell>" + data.toString() + "</Cell>";
    ?}
    ?
    }


    package com.hoten.util.xmlxls;

    public class CellData {
    ?private String type = "String"; //cell數據類型
    ?private String value = ""; //cell數據
    ?
    ?public String getType() {
    ??return type;
    ?}
    ?public void setType(String type) {
    ??this.type = type;
    ?}
    ?public String getValue() {
    ??return value;
    ?}
    ?public void setValue(String value) {
    ??this.value = value;
    ?}
    ?
    ?
    ?public String toString(){
    ??return "<Data ss:Type=\"" + type + "\">" + value + "</Data>";
    ?}
    }



    package com.hoten.util.xmlxls;

    public class Contants {
    ?public final static String SEP_N = "\n";
    ?/**
    ? * XML中常量定義
    ? */
    ?public final static String SS_NAME = "ss:Name";
    ?public final static String SS_INDEX = "ss:Index";
    ?public final static String SS_TYPE = "ss:Type";

    }



    測試的方法:
    PrintWriter out = response.getWriter();
    ???????? // 設置響應頭和下載保存的文件名
    ???????? response.setContentType("application/vnd.ms-excel");
    ???????? response.setHeader("Content-Disposition","attachment; filename=\""+Chinese.toPage(fileNametemp)+"\"");
    ????????
    ???????? String rows_temp = request.getParameter("rows");//頁面?zhèn)鬟^來的每個SHEET可以存放的條數
    ???if (rows_temp == null){
    ????rows_temp = "20000";
    ???}
    ???int count_rows = Integer.parseInt(rows_temp);//一個SHEET有多行
    ????????
    ???????? WorkBook book = new WorkBook();
    ???????? Vector v_Rs = RsToVector.ResultSetToVector(rs);// 把RS的值轉換成VECTOR,這個可以看我上一版本,上面有詳細的寫法
    ?????????
    ???????? if (v_Rs != null) {
    ????int a = v_Rs.size();????
    ????int sheet_count = a / count_rows;// 30000行一個sheet。
    ????
    ????if (sheet_count >0){//大于0,則需要多個SHEET
    ?????for (int i = 0;i<sheet_count;i++){
    ??????WorkSheet sheet = new WorkSheet();//創(chuàng)建一個新的SHEET
    ??????sheet.setName("sheet" + i);//設置SHEET的名稱
    ???????????
    ??????for (int b = i* count_rows ;b<(i+1) * count_rows ;b++){???????
    ???????//temp_v.add(v_Rs.get(b));
    ???????Vector temp_v = new Vector();
    ???????temp_v =(Vector) v_Rs.get(b);???????
    ???????//取出一個對象,把對象的值放到EXCEL里
    ???????TableRow row = new TableRow();//設置行?
    ???????for(int m=0;m<numColumns;m++){
    ?????????? ???TableCell cell = new TableCell();
    ?????????? ???CellData data = new CellData();
    ?????????? ???data.setValue((String)temp_v.get(m));
    ?????????? ???cell.setData(data);?????????? ???
    ?????????? ???row.addCell(cell);
    ?????????? ??}?????????? ??
    ?????????? ??sheet.addRow(row);
    ??????}?
    ??????book.addSheet(sheet);
    ?????}
    ?????//還有剩余的數據
    ?????if (sheet_count * count_rows < a){
    ??????WorkSheet sheet = new WorkSheet();//創(chuàng)建一個新的SHEET
    ??????sheet.setName("sheet" + sheet_count);//設置SHEET的名稱
    ???????
    ??????for (int c = sheet_count* count_rows ;c<a ;c++){???????
    ???????Vector temp_vv = new Vector();
    ???????temp_vv =(Vector) v_Rs.get(c);
    ???????//取出一個對象,把對象的值放到EXCEL里
    ???????TableRow row = new TableRow();//設置行
    ???????for(int m=0;m<numColumns;m++){
    ?????????? ???TableCell cell = new TableCell();
    ?????????? ???CellData data = new CellData();
    ?????????? ???data.setValue((String)temp_vv.get(m));
    ?????????? ???cell.setData(data);?????????? ???
    ?????????? ???row.addCell(cell);
    ?????????? ??}?????????? ??
    ?????????? ??sheet.addRow(row);???????
    ??????}
    ??????book.addSheet(sheet);???????
    ?????}
    ????}else{
    ?????
    ?????
    ??????WorkSheet sheet = new WorkSheet();//創(chuàng)建一個新的SHEET
    ??????sheet.setName("sheet1");//設置SHEET的名稱
    ???????????
    ??????for (int bb=0? ;bb<a ;bb++){???????
    ???????//temp_v.add(v_Rs.get(b));
    ???????Vector temp_v = new Vector();
    ???????temp_v =(Vector) v_Rs.get(bb);???????
    ???????//取出一個對象,把對象的值放到EXCEL里
    ???????TableRow row = new TableRow();//設置行?
    ???????for(int m=0;m<numColumns;m++){
    ?????????? ???TableCell cell = new TableCell();
    ?????????? ???CellData data = new CellData();
    ?????????? ???data.setValue((String)temp_v.get(m));
    ?????????? ???cell.setData(data);?????????? ???
    ?????????? ???row.addCell(cell);
    ?????????? ??}?????????? ??
    ?????????? ??sheet.addRow(row);
    ??????}?
    ??????book.addSheet(sheet);
    ????}
    ????????
    ????out.print(book.toString());
    ???}
    ??? 以上拼XML的時候重復代碼比較多,可以寫一個公用的方法,,我為了把XML描述的詳細一點,把這些都封裝成了對象,但在拼字符串的時候,對象就會太多,以后如果改版的話,可以把它盡量封裝少一點對象,這樣速度可能會快一點,內存可能會少用一點.

    ?

    轉 : http://www.tkk7.com/wujiaqian/archive/2006/12/11/86970.html

    posted on 2007-01-08 15:38 小石頭 閱讀(1828) 評論(1)  編輯  收藏 所屬分類: 轉載區(qū) 、我的java學習

    FeedBack:
    # re: 通過構造XML數據流下載成Excel文件[轉]
    2012-08-02 12:56 | 隨便你叫
    這真心要感謝微軟大大們的努力以及開放出這個東西!  回復  更多評論
      
    主站蜘蛛池模板: 国产精品国产午夜免费福利看 | 一区二区三区在线免费看 | 一级特级aaaa毛片免费观看| 精品亚洲一区二区三区在线播放| 久久综合九色综合97免费下载 | 亚欧国产一级在线免费| 久久久亚洲精品视频| 日韩一级免费视频| 人人玩人人添人人澡免费| 亚洲中文无码亚洲人成影院| 久久久久国产亚洲AV麻豆 | 伊伊人成亚洲综合人网7777| 在线免费观看国产| 四虎影视久久久免费| 亚洲国产成人手机在线电影bd| 亚洲成av人片在线观看天堂无码| 91精品国产免费入口| 天堂亚洲免费视频| 亚洲日韩精品无码AV海量| 亚洲成年人在线观看| 亚洲国产成人久久笫一页| 2020久久精品国产免费| 大地资源在线资源免费观看 | 国内精品一级毛片免费看| 性色av极品无码专区亚洲| 亚洲成aⅴ人片在线观| 中文字幕精品亚洲无线码一区| 日韩在线a视频免费播放| 麻豆高清免费国产一区| 成人免费一区二区三区| 国产在亚洲线视频观看| 天堂亚洲国产中文在线| 久久亚洲精品国产精品| 亚洲一区二区三区无码中文字幕| 国产又粗又猛又爽又黄的免费视频| xxxxwww免费| 一级特黄aa毛片免费观看| 手机看片国产免费永久| 高清免费久久午夜精品| 亚洲丶国产丶欧美一区二区三区 | a在线观看免费网址大全|