<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數(shù)據(jù)下載的東西,發(fā)現(xiàn)當(dāng)數(shù)據(jù)超過10萬行之后,就會內(nèi)存溢出(用的是本機(jī)TOMCAT測試,內(nèi)存有限,沒能調(diào)過),新做一種方式,來感覺一下,發(fā)現(xiàn)速度有點慢,其他還可以.?

    一、問題描述

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

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

    ???

    二、實現(xiàn)靈感

    ??? Excel 文件打開之后選擇另存為可以保存為 XML 類型文件,因此就考慮構(gòu)造符合 Excel 可以打開的 XML 類型文件,并且對該 XML 文件進(jìn)行最簡單化處理,去除 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>

    ??? <!— 一行數(shù)據(jù) --//>

    <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 文件結(jié)束 --//>

    ?

    ?

    注釋:

    a <Worksheet ss:Name="sheet0">? 引號內(nèi)部的是該 sheet 的名稱。

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

    ?

    ?

    三、實現(xiàn)方式

    ??? 通過第一步的分析可以發(fā)現(xiàn)只要我們構(gòu)建這樣格式的 XML 數(shù)據(jù),就可以通過 Excel 打開,并且可以實現(xiàn)分 sheet 的樣式。但是數(shù)據(jù)下載到用戶本地是 XML 類型的話,那是沒什么意義的,就算打開方式選擇使用 Excel 可以打開,因此如何將用戶下載的文件類型改為 XLS 呢?這里就可以通過在下載的 servlet 中設(shè)置 response.setContentType("application/vnd.ms-excel") 來實現(xiàn)。
    我實現(xiàn)了五個類來封閉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的數(shù)據(jù)對象

    ?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數(shù)據(jù)類型
    ?private String value = ""; //cell數(shù)據(jù)
    ?
    ?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();
    ???????? // 設(shè)置響應(yīng)頭和下載保存的文件名
    ???????? response.setContentType("application/vnd.ms-excel");
    ???????? response.setHeader("Content-Disposition","attachment; filename=\""+Chinese.toPage(fileNametemp)+"\"");
    ????????
    ???????? String rows_temp = request.getParameter("rows");//頁面?zhèn)鬟^來的每個SHEET可以存放的條數(shù)
    ???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的值轉(zhuǎn)換成VECTOR,這個可以看我上一版本,上面有詳細(xì)的寫法
    ?????????
    ???????? 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);//設(shè)置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();//設(shè)置行?
    ???????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);
    ?????}
    ?????//還有剩余的數(shù)據(jù)
    ?????if (sheet_count * count_rows < a){
    ??????WorkSheet sheet = new WorkSheet();//創(chuàng)建一個新的SHEET
    ??????sheet.setName("sheet" + sheet_count);//設(shè)置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();//設(shè)置行
    ???????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");//設(shè)置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();//設(shè)置行?
    ???????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的時候重復(fù)代碼比較多,可以寫一個公用的方法,,我為了把XML描述的詳細(xì)一點,把這些都封裝成了對象,但在拼字符串的時候,對象就會太多,以后如果改版的話,可以把它盡量封裝少一點對象,這樣速度可能會快一點,內(nèi)存可能會少用一點.

    ?

    轉(zhuǎn) : http://www.tkk7.com/wujiaqian/archive/2006/12/11/86970.html

    posted on 2007-01-08 15:38 小石頭 閱讀(1827) 評論(1)  編輯  收藏 所屬分類: 轉(zhuǎn)載區(qū)我的java學(xué)習(xí)

    FeedBack:
    # re: 通過構(gòu)造XML數(shù)據(jù)流下載成Excel文件[轉(zhuǎn)]
    2012-08-02 12:56 | 隨便你叫
    這真心要感謝微軟大大們的努力以及開放出這個東西!  回復(fù)  更多評論
      
    主站蜘蛛池模板: 曰曰鲁夜夜免费播放视频| 5g影院5g天天爽永久免费影院| 四虎永久在线观看免费网站网址| 亚洲av福利无码无一区二区 | 亚洲国产成人精品久久久国产成人一区二区三区综 | 亚洲一级片内射网站在线观看| 特级av毛片免费观看| 亚洲成?Ⅴ人在线观看无码| 人妻免费久久久久久久了| 亚洲综合伊人久久综合| 国内精品免费视频精选在线观看| 久久伊人久久亚洲综合| 亚洲无砖砖区免费| 亚洲色www永久网站| 四虎成人免费大片在线| 美女被爆羞羞网站在免费观看| 亚洲高清无码专区视频| 中文字幕在线视频免费观看| 亚洲VA中文字幕无码一二三区| 全部免费毛片在线播放| 亚洲欧美日韩中文高清www777| 免费观看国产精品| 成人电影在线免费观看| 亚洲国产精品一区二区久| 国产真人无遮挡作爱免费视频| 国产成人无码精品久久久免费 | 国产亚洲色婷婷久久99精品| 一区二区在线免费观看| 亚洲熟妇成人精品一区| 狠狠亚洲狠狠欧洲2019| 日韩在线免费视频| 在线播放国产不卡免费视频| 亚洲视频在线播放| 免费v片在线观看| 亚洲一区二区在线免费观看| 亚洲国产午夜精品理论片在线播放 | 水蜜桃亚洲一二三四在线| 99精品国产免费久久久久久下载| 香港特级三A毛片免费观看| 亚洲第一区香蕉_国产a| 全亚洲最新黄色特级网站 |