線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6555
推到 Plurk!
推到 Facebook!

關於資料表轉存成excel檔案,當資料量太大時出現的問題

尚未結案
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-04-07 20:29:33 IP:211.74.xxx.xxx 未訂閱
大家好,我想將資料表轉存成excel,當資料表資料不多時,可以順利轉出,但是一旦資料一多,如336筆多的資料,就會出現「OLE error 800A03EC」的錯誤!不曉得是哪個地方錯了!請各位指教!謝謝!^^ 以下是我的程式: tb_read:=TTable.create(self); tb_read.DatabaseName:=Dbname; tb_read.TableName:=a[i]; tb_read.Open; except showmessage('無法與評鑑系統連線'); end; //Result取得excel.appliation的資訊; Result:=GetActiveObject(ProgIDtoClassID('Excel.application'),nil,FIUnknown); if Succeeded(Result) then FExcel:=FIUnknown as IDispatch else begin try FExcel:=CreateOleObject('Excel.Application'); except ShowMessage('無法轉存!!'); Raise end; end; try FWorkbook:=FExcel.workbooks.add//新增一個試算表; except showmessage('無法新增一個excel檔'); end; try FWorksheet:=FWorkbook.worksheets.add; //新增一個sheet; except showmessage('無法新增一個sheet'); end; for col:=1 to tb_read.FieldCount do //將資料表欄位名稱轉存至excel; begin FWorksheet.cells[1,col].value:=tb_read.fields[col-1].fieldname; end; with tb_read do begin first; row:=2; while not eof do begin for col:=1 to tb_read.fieldcount do begin FWorksheet.cells[row,col].value:=tb_read.Fields[col-1].asstring; end; row:=row 1; Next; end; end;
pgdennis
資深會員


發表:41
回覆:526
積分:443
註冊:2002-05-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-04-07 22:06:37 IP:211.74.xxx.xxx 未訂閱
看不出有何問題,你要不要先試試這個>
------
星期一,二...無窮迴圈@@
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-04-08 00:38:15 IP:211.74.xxx.xxx 未訂閱
想再針對我的問題說明白,嗯~~基本上我程式,當資料比較少筆時,可以順利的轉存出來,可是當資料表資料一多時,就轉不出來耶!覺得甚是奇怪,所以想說各位是否有遇過類似問題,基本上我的不太像是資料太多筆(超過65535),而使excel無法存下來,而是才三百多筆就轉不出來了耶!真的很奇怪!不曉得是不是我程式出問題,或是哪沒顧慮到的?請各位高手,幫忙看一下!謝謝!^^ ps.還有我的程式是一個row一個row存的, 不曉得如何一筆一筆轉出來哩!^^|| 傷腦筋很久了!請各位幫幫忙!謝謝!^^
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-04-08 09:03:14 IP:218.16.xxx.xxx 未訂閱
我也對 OLE 不熟悉,也看不出你的程式有甚麼問題。 不過,你有甚麼原因一定要用 OLE 來傳資料嗎? 我看你的程式好像只簡單地將資料轉過 excel, 並沒作甚麼格式特殊處理等。 如果這樣的話,直接將 數據存成 Excel 檔案不是更容易嗎 ? 你可參考拙作 《DataSet 儲存成 txt/csv/xls 簡單程序》 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=27241 你可將該函數(僅24行)複制到你的程式便可使用了。 你的情況可這樣使用 : use ShellAPI // 若你不需 ShellExecute 可不用這行 tb_read:=TTable.create(self); tb_read.DatabaseName:=Dbname; tb_read.TableName:=a[i]; tb_read.Open; SaveDataSet(tb_read,'test.xls',#9); shellExecute(handle,'open','test.xls',nil,nil,SW_NORMAL); // 用 excel 開剛做的檔案 至於為甚麼會出現「OLE error 800A03EC」,要等 OLE 的高手來幫忙了。
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-04-08 11:36:30 IP:211.74.xxx.xxx 未訂閱
引言: 我也對 OLE 不熟悉,也看不出你的程式有甚麼問題。 不過,你有甚麼原因一定要用 OLE 來傳資料嗎? 我看你的程式好像只簡單地將資料轉過 excel, 並沒作甚麼格式特殊處理等。 如果這樣的話,直接將 數據存成 Excel 檔案不是更容易嗎 ? 你可參考拙作 《DataSet 儲存成 txt/csv/xls 簡單程序》 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=27241 你可將該函數(僅24行)複制到你的程式便可使用了。 你的情況可這樣使用 : use ShellAPI // 若你不需 ShellExecute 可不用這行 tb_read:=TTable.create(self); tb_read.DatabaseName:=Dbname; tb_read.TableName:=a[i]; tb_read.Open; SaveDataSet(tb_read,'test.xls',#9); shellExecute(handle,'open','test.xls',nil,nil,SW_NORMAL); // 用 excel 開剛做的檔案 至於為甚麼會出現「OLE error 800A03EC」,要等 OLE 的高手來幫忙了。
嗯~~其實我也對ole很不熟悉,了解的程度也比您更少說! 因為這是參考學長姊的程式參考而來的,只是不甚了解!所以一出現問題,我也很難知道為何會出現那種錯誤!^^|| 目前還在研究您提供的方法,不曉得為何?出現以下錯誤 程式中的 >
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-04-08 12:36:26 IP:218.16.xxx.xxx 未訂閱
引言: 1.SaveDataSet(tb_read,'test.xls',#9);出現[Error] Dbset_Backup.pas(1572): Undeclared identifier: 'SaveDataSet' 不曉得是不是我少了什麼元件,或是少use東西,我原本是用ttable的元件!
SaveDataSet 是自定程序,不需要安裝其麼元件,但你總要將我在那篇文中的程式加入你的程式裡才可使用啊。 放的地方可以是 imprementation 之後,其他程序之前如 : implementation {$R *.DFM} procedure SaveDataSet(TT : TDataSet; FileName, Delimiter : String); var ... ... end; procedure xxxx.yyyy(zzzz); ... ...
引言: 2. M.Add(Line);出現 [Error] Dbset_Backup.pas(2282): Missing operator or semicolon
這應是你 M.Add(Line); 之前一行 漏了 ; 罷
引言: 3.[Fatal Error] main_pro.dpr(71): Could not compile used unit 'backup\Dbset_Backup.pas'
有任何其他 Error 就會出現這個,解決其他問題就不會出現了。
引言: 還有一個問題,我要是想針對轉出的資料做處理,想將其中一個行加個字元「a」,這樣的話,我該怎麼辦呢??
若使用 OLE 你的方法應改成
with tb_read do
begin
  first;
  row:=2;
  while not eof do
  begin
    FWorksheet.cells[row,1].value:='a'   tb_read.Fields[0].asstring; 
    for col:=2 to tb_read.fieldcount do
      FWorksheet.cells[row,col].value:=tb_read.Fields[col-1].asstring; 
    row:=row 1;
    Next;
  end;
end;
若你使用我說的程序,也可改成
procedure Save_tb_read(TT : TDataSet; FileName, Delimiter : String);
var
i : integer;
line : string;
M : TStringList;
begin
  TT.Active := true;
  TT.First;
  M := TStringList.Create;
  Line := TT.Fields[0].DisplayName; // 可改成FieldName
  For i := 1 to TT.FieldCount -1 do
    Line := Line   Delimiter   TT.Fields[i].DisplayName; // 可改成FieldName
  M.Add(Line);
  while not TT.Eof do
  begin
    Line := 'a'   TT.Fields[0].AsString;
    For i := 1 to TT.FieldCount -1 do
        Line := Line   Delimiter   StringReplace(StringReplace(TT.Fields[i].AsString,
          #13#10,' ',[rfReplaceAll]),#9,' ',[rfReplaceAll])
    M.Add(Line);
    TT.Next;
  end;
  M.SaveToFile(FileName);
end;
這樣你便可以 Save_tb_read(tb_read,'test.xls',#9); 來儲存並在第一欄作點更動了。
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-04-08 23:22:42 IP:211.74.xxx.xxx 未訂閱
Justmade先生,謝謝您!還有點問題想請教您!^^    我用下面的方式去呼叫您說提供的程式,如下:     
    for  i := 1 to 2 do
      begin        
        try            tb_read:=TTable.create(self);
        tb_read.DatabaseName:=Dbname;
        tb_read.TableName:=a[i];
        tb_read.Open;
  
         //處理檔案名稱
         filename:='#' date1 'v01_' a[i];
           filename1:=mainDir '#' date1 'v01_' a[i] '.xls';               while  FileExists(filename1) do begin
              n:='0' inttostr(strtoint(copy(filename,11,2)) 1);
              filename:='#' date1 'v' n '_' a[i];
              filename1:=mainDir '#' date1 'v' n '_' a[i] '.xls';
           end;
          Save_tb_read(tb_read,filename1,#9);
          j:=j 1;            except
        showmessage(a[i]/ '資料表無法備份');
        end;
        tb_read.free;
        
        
      ExcelApplication1.Quit;         end;
因為我不是很了解你的程式,也由於不同的資料表,需要在不同行加個字元,想將資料表第二行跟第七行加個字元'a',可是想了好久就是做不出來說!^^|| 不曉得該怎麼辦?麻煩您解說一下您的程式!不好意思,對程式不是那麼熟!又得麻煩您囉! 是否請您說明一下程式??
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-04-09 00:21:06 IP:218.16.xxx.xxx 未訂閱
那個程序是和你原本用OLE的程序很接近的,一筆一筆迴圈,每筆一欄一欄迴圈,你要修改某些欄可在欄的迴圈裡做手腳。 你兩個 Table 要特別處理的 Field 都不一樣嗎? 若你每個 Table 要作不同的處理,設計時加入 TTable 元件先設定好比動態生成要容易 要睡了明天再續,站長及其他大大歡迎提供意見/解答。
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-04-09 01:16:33 IP:211.74.xxx.xxx 未訂閱
 Line := TT.Fields[0].DisplayName; // 可改成FieldName  
    For i := 1 to TT.FieldCount -1 do    
   Line := Line   Delimiter   TT.Fields[i].DisplayName; // 可改成FieldName  ==>請問此段是指將欄位名稱先轉到資料表嗎?        M.Add(Line);  
   while not TT.Eof do  begin    
   Line := 'a'   TT.Fields[0].AsString;    
   For i := 1 to TT.FieldCount -1 do  ==>迴圈從1開始是因為line已經記錄第一行的資料了嗎??所以才這樣做的嗎?我想由第二行加a,但是一直達不到自己想要的資料!^^||
   下面這一行不是很清楚是在做什麼耶?? 
   Line := Line   Delimiter   StringReplace(StringReplace(TT.Fields[i].AsString,          #13#10,' ',[rfReplaceAll]),#9,' ',[rfReplaceAll])    
   M.Add(Line);    
   TT.Next;  
   end;  
嗯~~我每個table(有47個) ,有部分資料表內容需要另外加入字元,其實是因為我原先資料如20020020304001像這樣的資料轉到excel會被變成科學符號,想說加個字元就不會有這個問題,還有像「0204」,把他轉到excel也是會把認為數字,所以也是同樣加個字元給他,其實知道這不是個好方法!不過,目前只想到這種解決方式!所以才會想加個字元,造成自己寫程式的困擾!^^||否則,只要單純的轉出,其實就不會有那麼多問題了說!^^||對了!謝謝您提供的方法,比我原先寫的程式,速度快好多,嚇了一跳呢!呵~~^^||
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-04-09 10:36:31 IP:218.16.xxx.xxx 未訂閱
引言: 請問此段是指將欄位名稱先轉到資料表嗎?
對,我用 DisplayName 而不用 FieldName 是因為使用者可以在該 Dataset 輸入跟 FieldName 不同的名稱(如中文名稱),若使用者沒輸入,DisplayName 自動等於 FieldName,這給使用者較多的自由度。
引言: 迴圈從1開始是因為line已經記錄第一行的資料了嗎??所以才這樣做的嗎?我想由第二行加a,但是一直達不到自己想要的資料!^^||
對,也可改成 Line = ''; For i := 0 to TT.FieldCount -1 do 你可用 if / case 來判別現在處理第幾欄才決定要否特別處理
引言: 下面這一行不是很清楚是在做什麼耶?? Line := Line Delimiter StringReplace(StringReplace(TT.Fields[i].AsString,#13#10,' ',[rfReplaceAll]),#9,' ',[rfReplaceAll])
就是一欄一欄的加進Line,並用 Delimiter 分隔囉。 2 個 StringReplace 其中一個將 Tab(#9) 變 空白 另一個將 轉行 (#13#10) 變空白,否則讀入時會有錯誤
引言: 嗯~~我每個table(有47個) ,有部分資料表內容需要另外加入字元,其實是因為我原先資料如20020020304001像這樣的資料轉到excel會被變成科學符號,想說加個字元就不會有這個問題,還有像「0204」,把他轉到excel也是會把認為數字,所以也是同樣加個字元給他,其實知道這不是個好方法!不過,目前只想到這種解決方式!所以才會想加個字元,造成自己寫程式的困擾!^^||否則,只要單純的轉出,其實就不會有那麼多問題了說!^^||對了!謝謝您提供的方法,比我原先寫的程式,速度快好多,嚇了一跳呢!呵~~^^||
你可用 TT.Field[i].DataType 來判別在源資料庫這是甚麼形態來作特別處理 例如
if TT.Field[i].DataType = ftString then
  Line := Line   Delimiter   'A'   TT.Fields[i].AsString 
else
  Line := Line   Delimiter   'B'   TT.Fields[i].AsString;
不過,這樣輸出與直接在 Excel 手動輸入不同,例如你在某欄前面加 ' ,EXCEL 讀入後真的顯示該 ' 而非像手動視之為文字的提示。 發表人 - Justmade 於 2003/04/09 10:45:45
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-04-15 23:02:27 IP:211.74.xxx.xxx 未訂閱
很抱歉之前要研究所考試,所以沒來回應文章!真的很對不住!不好意思!我還是有少些問題說!^^||     
引言: 你可用 TT.Field[i].DataType 來判別在源資料庫這是甚麼形態來作特別處理 例如 if TT.Field[i].DataType = ftString then Line := Line Delimiter 'A' TT.Fields[i].AsString else Line := Line Delimiter 'B' TT.Fields[i].AsString; 不過,這樣輸出與直接在 Excel 手動輸入不同,例如你在某欄前面加 ' ,EXCEL 讀入後真的顯示該 ' 而非像手動視之為文字的提示。
基本上都是字串型態為主,我之前說的會變成科學符號的欄位,其實本來就是定義成char的型態,所以會想加字元給它!^^|| 所以想說是不是不用再去判斷是否為字串型態!?
timhuang
尊榮會員


發表:78
回覆:1815
積分:1608
註冊:2002-07-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-04-16 00:20:41 IP:61.221.xxx.xxx 未訂閱
引言: 基本上都是字串型態為主,我之前說的會變成科學符號的欄位,其實本來就是定義成char的型態,所以會想加字元給它!^^|| 所以想說是不是不用再去判斷是否為字串型態!?
若是將數字以字串格式的顯示, 可以將儲存格的格式設定一下即可. NumberFormatLocal 的設定, 若是某一格的設定方法為: FWorksheet.cells[x,y].NumberFormatLocal := '@'; 若是整個 column 的設定為: FWorkSheet.columns['P'].NumberFormatLocal:='@'; 請參考: http://delphi.ktop.com.tw/topic.php?topic_id=23622
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-04-16 08:50:01 IP:218.16.xxx.xxx 未訂閱
使用該函數來輸出 excel 檔,其實輸出的只是純文字檔,只是格式能被 excel 直接開啟。所以它沒有供設定cell格式的能力。若你不介意資料前有一空白字元,倒可以加一個空白字元在前面,否則,還是要直接控制excel來處理。 你可以先以該函數輸出檔案,再以ole開啟檔案設定 column 格式。
funging
一般會員


發表:13
回覆:41
積分:10
註冊:2002-10-28

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-04-16 21:00:43 IP:211.74.xxx.xxx 未訂閱
嗯~~基本上我用了很笨的方法,就是把所有欄位都加個字元'a',想在還原時,再從第二個字元開始抓資料回資料庫!以之前我所提到的問題(指原字串copy到excel會變成科學符號等問題)。 但是因為justmade先生有提到,這個程式:「其實輸出的只是純文字檔,只是格式能被 excel 直接開啟。」,所以用adotable的方法要還原,就會出現「外部資料表非預期的格式」導致我無法還原!^^|| 想說是不是我用excel來做備份、還原,是不太好的方法呢??假如說我想改成文字檔格式來做備份、還原是否比較容易實作呢??請高手們解答一下!謝謝你們!^^  而我有試著將justmade先生的程式改成以下方式:    
 
filename:='#' date1 'v01_' a[i];
           filename1:=mainDir '#' date1 'v01_' a[i] '.txt';               while  FileExists(filename1) do begin
              n:='0' inttostr(strtoint(copy(filename,11,2)) 1);
              filename:='#' date1 'v' n '_' a[i];
              filename1:=mainDir '#' date1 'v' n '_' a[i] '.txt';
           end;              Save_tb_read(tb_read,filename1,#9);
結果只出現欄位名稱,資料都沒出現!呵~~應該是因為那個程式是符合excel的關係吧!^^|| 呵~~小妹能力不夠!請解答一下!謝謝您。還有對文字檔轉回資料檔更是沒概念說!^^||
系統時間:2024-07-01 21:45:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!