全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1856
推到 Plurk!
推到 Facebook!

请问为什么使用delphi7的servers控件操作word时消耗时间不是与操作量

尚未結案
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-07-29 12:19:26 IP:222.240.xxx.xxx 未訂閱
根据我的统计: 如果进行x个操作需要n分钟的话, 那么进行2x个操作就需要超过4n分钟. 请问各位是否有同样的问题?原因是什么?如果解决?
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-08-01 07:35:15 IP:203.69.xxx.xxx 未訂閱
如果能給個簡單的範例, 出現你所說的狀況, ㄧ定有許多人ㄧ起幫你解決....
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-08-01 12:24:33 IP:218.76.xxx.xxx 未訂閱
任何操作,比如连续获取1000个字的大小。 先记录初始时间d0, 然后在获取到第250个的时候记录一下当前时间d1, 在获取到第500个的时候记录一下当前时间d2, 在获取到第750个的时候记录一下当前时间d3, 在获取到第1000个的时候记录一下当前时间d4, 设消耗时间d1-d0=n, 那么就会发现d2-d0=4n而不是2n d3-d0=8n而不是3n d4-d0=16n而不是4n。 不仅用delphi的控件如此,我用CreateOleObject('word.Application')调用word也是如此,只是速度稍微快一点点。
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-08-01 13:12:29 IP:203.69.xxx.xxx 未訂閱
照你的說法 同樣獲取 1000 個字 先紀錄初始時間 d0 然後在獲取第 200 個的時候 紀錄一下當前時間 d1, 在獲取第 400 個的時候 紀錄一下當前時間 d2, 在獲取第 600 個的時候 紀錄一下當前時間 d3, 在獲取第 800 個的時候 紀錄一下當前時間 d4, 在獲取第 1000 個的時候 紀錄一下當前時間 d5, 設消耗時間d1-d0=n d2-d0=4n d3-d0=8n d4-d0=16n d5-d0=32n 我這樣推論對嗎? 若分為 10 次測量, 設 d1-d0=m 那 d10-d0=2^10m=1024m 哦.... 這是不是表示你獲取每個字時, 程式都要從第1個開始算. 我的意思是 取第k個字時, 是要花移動 k 個字的時間, 所以 取 n 個字要花 n*(n 1)/2次移動, 就算是這樣 上面的 d5-d0 也只有不到 25n 還不至於到 32n. 所以你的推論是對的嗎, 有範例程式可以佐證嗎? 也許我沒說清楚, "給個簡單的範例" 就是給ㄧ段簡單的程式碼會造成你所說的狀況出現, 像我看到你的問題時, 我就要花時間去弄ㄧ個範例出來檢查是不是有你所說的情況, 不然就等我有空才能慢慢試試看; 如果你能給ㄧ個.pas檔案 的內容, 大家ㄧ定很樂意馬上抓下來測, 給別人方便就是方便自己. 您覺得我說的有理嗎?
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-08-01 16:40:22 IP:218.76.xxx.xxx 未訂閱
下面是我写的一个测试程序的pas文件,测试一个4000字的文档结果为(秒): d1-d0=27.21              (前1000个操作的时间) d2-d0=87.92              (前2000个操作的时间) d3-d0=182.27              (前3000个操作的时间) d4-d0=308.49              (前4000个操作的时间) 使用的delphi7+word2003,虽然不是严格象我前面提的那样成倍数增长,也基本显示了这种趋势了。
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Word2000, OleServer, ComCtrls;    type
  TForm1 = class(TForm)
    wa1: TWordApplication;
    wd1: TWordDocument;
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    pb1: TProgressBar;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    function connecttoword:boolean;
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    function Tform1.connecttoword:boolean;
var
fn:OleVariant;
begin
result:=false;
try
wa1.connect;
except
memo1.Lines.Add('Word连接失败,请确定Word2000或Word2003是否已经正确安装!');
exit;
end;
if wa1.Documents.Count=0 then
   begin
   memo1.Lines.Add('没有打开文件!');
   exit;
   end;
wd1.ConnectTo(wa1.ActiveDocument);
memo1.Lines.Add('已连接到文档:' wd1.Name);
result:=true;
end;    procedure TForm1.Button1Click(Sender: TObject);
begin
connecttoword;
if wd1.Characters.Count<4000 then memo1.Lines.Add('文章长度不够,请选择更长的文件测试');
end;    procedure TForm1.Button3Click(Sender: TObject);
begin
wd1.Disconnect;
wa1.Disconnect;
end;    procedure TForm1.Button2Click(Sender: TObject);
var
i,i1,i2,i3,i4:integer;
size:single;
d0,d1,d2,d3,d4:Tdatetime;
begin
d0:=now;
pb1.Min:=0;
pb1.Position:=0;
pb1.Max:=4000;    for i:=1 to 4000 do
   begin
   case i of
      1000:d1:=now;
      2000:d2:=now;
      3000:d3:=now;
      4000:d4:=now;
   else
   end;
   size:=wd1.Characters.item(i).Font.Size;
   pb1.Position:=i;
   end;    memo1.Lines.Add(format('d1-d0=%f',[(d1-d0)*24*3600]));
memo1.Lines.Add(format('d2-d0=%f',[(d2-d0)*24*3600]));
memo1.Lines.Add(format('d3-d0=%f',[(d3-d0)*24*3600]));
memo1.Lines.Add(format('d4-d0=%f',[(d4-d0)*24*3600]));    end;    end.
發表人 - logv 於 2005/08/01 21:39:08
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-08-01 17:47:11 IP:203.69.xxx.xxx 未訂閱
看來好像真被我說中了, wd1.Characters.item(i) 這行, 恐怕每次都會從頭開始算.....
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-08-01 17:57:41 IP:220.168.xxx.xxx 未訂閱
是吗?那如果我想直接访问某个字的属性,应该如何操作才能避免它从头开始计算?
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-08-01 19:06:10 IP:203.69.xxx.xxx 未訂閱
參考這ㄧ篇 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtoretrievestartendcharactersinranges.asp
procedure TForm1.Button1Click(Sender: TObject);
var
  rgn: Range;
  i,iStart,iEnd,iCount: Integer;
begin
  iCount := WordDocument1.Characters.Count;
  iStart:=1;
  iEnd := Min(iStart 100,iCount);
  rgn := WordDocument1.Range(iStart,iEnd);
  while (iStart    用這段試試 我的觀點是 在一個區塊中移動 比在整篇文章中移動快...    順便提一下, 如果將你的程式碼用 
 
夾起來 縮排就不會跑掉了. 編輯框上面有 # 的按鈕也是同樣作用. 內容送出去還是可以改, 要不要改一下啊, 在你提問的頁面 "發表於 - 2005/08/01 : 11:13:21..." 後面應該有4個 "icon" 其中一個可以讓你再修正內容...要不要試一下...
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-08-01 19:08:25 IP:203.69.xxx.xxx 未訂閱
引言: 參考這ㄧ篇 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtoretrievestartendcharactersinranges.asp
procedure TForm1.Button1Click(Sender: TObject);
var
  rgn: Range;
  i,iStart,iEnd,iCount: Integer;
begin
  iCount := WordDocument1.Characters.Count;
  iStart:=1;
  iEnd := Min(iStart 100,iCount);
  rgn := WordDocument1.Range(iStart,iEnd);
  while (iStart    用這段試試 我的觀點是 在一個區塊中移動 比在整篇文章中移動快...    順便提一下, 如果將你的程式碼用 [code] [/code] 夾起來 縮排就不會跑掉了.
編輯框上面有 # 的按鈕也是同樣作用.    內容送出去還是可以改, 要不要改一下啊, 在你提問的頁面
"發表於 - 2005/08/01 : 11:13:21..." 後面應該有4個 "icon" 其中一個可以讓你再修正內容...要不要試一下...         
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-08-01 21:48:00 IP:218.76.xxx.xxx 未訂閱
rgn.Next(wdCharacter,iEnd-iStart 1);这句编译不通过 提示"Types of actual and formal var parameters must be identical"
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-08-01 22:08:38 IP:218.76.xxx.xxx 未訂閱
引言:
引言: 參考這ㄧ篇 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrtskhowtoretrievestartendcharactersinranges.asp
procedure TForm1.Button1Click(Sender: TObject);
var
  rgn: Range;
  i,iStart,iEnd,iCount: Integer;
begin
  iCount := WordDocument1.Characters.Count;
  iStart:=1;
  iEnd := Min(iStart 100,iCount);
  rgn := WordDocument1.Range(iStart,iEnd);
  while (iStart    用這段試試 我的觀點是 在一個區塊中移動 比在整篇文章中移動快...    順便提一下, 如果將你的程式碼用 [code] [/code] 夾起來 縮排就不會跑掉了.
編輯框上面有 # 的按鈕也是同樣作用.    內容送出去還是可以改, 要不要改一下啊, 在你提問的頁面
"發表於 - 2005/08/01 : 11:13:21..." 後面應該有4個 "icon" 其中一個可以讓你再修正內容...要不要試一下...         
我将你的代码修改如下后通过,而且速度均衡。
var
  rgn: Range;
  iStart,iEnd,iCount: olevariant;
  size:single;
  i:integer;
  d0,d1:Tdatetime;
  s:string;
begin
  iCount := Wd1.Characters.Count;
  iStart:=0;
  iEnd := Min(iStart 100,iCount);
  rgn := Wd1.Range(iStart,iEnd);
  while (iStart
谢谢,你还能告诉我为什么你的代码里rgn.Next(wdCharacter,iEnd-iStart 1);我这里为什么会编译不通过吗?这句语法上没有问题啊。     
        
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-08-01 23:04:49 IP:61.219.xxx.xxx 未訂閱
Sorry, 只有看你的程式, 並未實際去 Compile, 因為在趕 Project 抽空回答問題, 所以才會出現這段錯誤碼, 基本上 傳給 OleServer 多數是要求傳址(也就是 func(var a:OleVariant; var b:OleVariant; var ....); 的格式, 所以 Wd1.Range(iStart,iEnd) 過關了, 因為 Delphi 會自動轉為 OleVariant 再傳. 而 rgn.Next(wdCharacter,iEnd-iStart 1); ㄧ個是常數, ㄧ個是計算式都不會過關....而且就如錯誤訊息所言 Types of actual and formal var parameters must be identical 讓程式表達更清晰的小撇步.... 加 [red]..........[/red]在字句的前後, 字句就會變紅色 加 [green]..[/green]在字句的前後, 字句就會變綠色... rgn.Next(wdCharacter,iEnd-iStart 1); //這裡編譯錯誤 這樣表達更醒目
logv
一般會員


發表:5
回覆:22
積分:10
註冊:2004-03-16

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-08-02 09:33:20 IP:222.240.xxx.xxx 未訂閱
经过调试,以下代码通过测试,谢谢! 现将修改后的代码帖在下面,修改的地方用红色标明
var
  rgn: Range;
  iStart,iEnd,iCount,iv,iw: olevariant;
  size:single;
  i:integer;
  d0,d1:Tdatetime;
begin
  iCount := Wd1.Characters.Count;
  iStart:=0;
  iEnd := Min(iStart 100,iCount);
  rgn := Wd1.Range(iStart,iEnd);
  while (iStartrgn:=rgn.Next(iw,iv);//不然rgn不会改变
  rgn.End_:=iend;//使用上句后,iv不论取何值,改变的是rgn的start的值,而rgn的end默认为start 1,所以需要设定
  memo1.Lines.Add(format('d1-d0=%f',[(now-d0)*24*3600]));
end;
系統時間:2024-11-23 8:25:34
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!