關於資料表轉存成excel檔案,當資料量太大時出現的問題 |
尚未結案
|
funging
一般會員 發表:13 回覆:41 積分:10 註冊:2002-10-28 發送簡訊給我 |
大家好,我想將資料表轉存成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 發送簡訊給我 |
|
funging
一般會員 發表:13 回覆:41 積分:10 註冊:2002-10-28 發送簡訊給我 |
想再針對我的問題說明白,嗯~~基本上我程式,當資料比較少筆時,可以順利的轉存出來,可是當資料表資料一多時,就轉不出來耶!覺得甚是奇怪,所以想說各位是否有遇過類似問題,基本上我的不太像是資料太多筆(超過65535),而使excel無法存下來,而是才三百多筆就轉不出來了耶!真的很奇怪!不曉得是不是我程式出問題,或是哪沒顧慮到的?請各位高手,幫忙看一下!謝謝!^^ ps.還有我的程式是一個row一個row存的, 不曉得如何一筆一筆轉出來哩!^^||
傷腦筋很久了!請各位幫幫忙!謝謝!^^
|
Justmade
版主 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我也對 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 發送簡訊給我 |
引言: 我也對 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 發送簡訊給我 |
引言: 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 發送簡訊給我 |
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 發送簡訊給我 |
|
funging
一般會員 發表:13 回覆:41 積分:10 註冊:2002-10-28 發送簡訊給我 |
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 發送簡訊給我 |
引言: 請問此段是指將欄位名稱先轉到資料表嗎?對,我用 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 發送簡訊給我 |
很抱歉之前要研究所考試,所以沒來回應文章!真的很對不住!不好意思!我還是有少些問題說!^^||
引言: 你可用 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 發送簡訊給我 |
引言: 基本上都是字串型態為主,我之前說的會變成科學符號的欄位,其實本來就是定義成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 發送簡訊給我 |
|
funging
一般會員 發表:13 回覆:41 積分:10 註冊:2002-10-28 發送簡訊給我 |
嗯~~基本上我用了很笨的方法,就是把所有欄位都加個字元'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的關係吧!^^|| 呵~~小妹能力不夠!請解答一下!謝謝您。還有對文字檔轉回資料檔更是沒概念說!^^|| |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |