ExcelApplication利用で時間がかかる。

解決


kim  2007-08-21 22:36:32  No: 27452

CSVデータをstring2次元配列に読み込み、COMのExcelApplication、ExcelWorksheetを利用してExcelに表示させているのですが、
表示に時間がかかります。
配列の代わりにStringGridを使っても殆ど差はありません。
COMのほうに原因があると思われます。
よい方法はないでしょうか?


HOta  2007-08-21 22:52:54  No: 27453

CSVデータをTab区切りにして、クリップボードを使用して貼り付けたらどうでしょう。


kim  2007-08-21 23:28:46  No: 27454

クリップボードに取り込んだデータをExcelのセルに持ってくるのはどうすればいいのですか?
ExcelApplicationのRange.Valueに代入するのであれば同じだと思うのですが。


Ru  2007-08-22 00:22:35  No: 27455

ここらへんですかね。
https://www.petitmonte.com/bbs/answers?question_id=4942

Mr.XRAYさんの発言の部分でできるかな。

var  ARange : Range;

   // 値をクリップボードにコピー
   ClipBoard.AsText := 'AAA';

   // 指定されたセルに貼付け
   ARange:=WorkSheet.Range['D1','D1'];
   ExcelWorkSheet1.Paste(ARange);


kim  2007-08-22 00:55:42  No: 27456

ありがとうございます。早速やってみます。
結果は後ほど。


kim  2007-08-22 02:07:47  No: 27457

すみません。
var  ARange : Range;
で  Range  が未定義の識別子のエラーになります。


kim  2007-08-22 02:18:23  No: 27458

すみません。タイプミスです。
var  ARange : Range;
で  「Rangeが未宣言の識別子です。」のエラーになります。
              。。。


HOta  2007-08-22 05:28:50  No: 27459

ExcelApplicationのRange.Valueに代入するのではなく、左上のCellを指定してPastします。かなり早く代入できます。

Clipboard.AsText := '2' + #9 + '2' + #9 + '2' + #13#10 + '2' + #9 + '2' + #9 + '2';
WorkSheet.Cells.Item[1, 1].PasteSpecial


kim  2007-08-23 18:15:34  No: 27460

悪戦苦闘していて、報告が遅くなり申し訳ありません。
10桁1500行程度のCSVデータを改行とかもあり行毎に表示しているのですが、
HOta様に教えていただいたWorkSheet.Cells.Item[1, 1].PasteSpecialの
セル指定の[ ]内を[Row,1]と行毎の先頭セルをしていしています。
1,2行目はうまくいくのですが、3行目が4行目に、4行目が7行目に表示され桁位置もくるってきます。該当部分の実際のプログラムは
    ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[IR,1].pasteSpecial;
としています。


HOta  2007-08-23 18:27:04  No: 27461

全ての行をクリップボードにコピーしないと、遅くなります。
改行は、「 + #13#10」を入れます。
行内にデーターが無い場合は、改行だけにします。


kim  2007-08-23 20:01:58  No: 27462

HOta様  ありがとうございます。

各ページ上2行は標題が入りますのでページあたり3行目から21行目まで表示したいのです。それに10文字以上のデータは折り返しを付けたり整形するため、行毎表示したいのです。

        Clipboard.AsText := Clipboard.AsText  + str;
        if iCol < 7 then
          Clipboard.AsText := Clipboard.AsText  + #9
        else
          Clipboard.AsText := Clipboard.AsText  + #13#10;
    end;
    ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[IR,1].pasteSpecial;

としています。データの桁数は7桁です。


HOta  2007-08-24 02:52:05  No: 27463

3行目から21行目までのデーターをクリップボードに用意します。
改行は、「 + #13#10」を入れます。
10文字以上のデータの折り返しは、文字の間に「 + #10」とすれば改行が入ります。
ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[3,1].pasteSpecial;
とすれば、一度でできます。テストはしてみましたか?
いろいろ条件があるのなら、以前のとおり、ゆっくりと動作させれば良いでしょう。整形などは時間がかかります。あらかじめ行や列が決まっているなら、テンプレートを作って、その中にデータを流し込めば良いのではないでしょうか?
Excelは後でいろいろできますが、その分時間はかかります。


フサ  2007-08-24 05:32:34  No: 27464

エクセルクリエーターを購入するのが定番ではないかと思うのですが。


kim  2007-08-25 06:17:31  No: 27465

HOta様  いつも有難うございます。
お教えいただいたことを参考にいろいろやっているのですが後一歩?のところでうまくいきません。帳票はシート一枚で上から連続しており、一ページ22行、その内上の2行は表題と空白行とし、データは3行目から22行迄、次の頁からは25〜44、47〜66、69〜88、91〜110行となり、Items[R,1]のRに3,25,47,69..とうまく代入されているのですが、3頁目が4頁目に表示され,
以降も頁がだんだん大きくずれてしまいます。変数には上手く正当な数字が代入されているのに、なぜ途中から頁がずれるのか(頁にデータは上手く納まっているのですが)不思議でなりません。
もう少し頑張ってみます。

フサ様
天邪鬼ですが、自分で作ってみたいので、頑張ります。
ありがとうございました。


HOta  2007-08-25 06:42:00  No: 27466

変数の使い方がおかしくなっているのですね。
一度、その部分のソースをあげてみたらどうでしょう。
多分、頁毎の初期化がうまくいっていないのでしょう。
ところで、1頁毎にpasteSpecialしているのではないようですね。
1頁毎にpasteSpecialしたほうが、早くなりますよ。


kim  2007-08-25 21:09:03  No: 27467

HOta様  早速ありがとうございます。
ソースは下記の通りです。よろしくお願いいたします。

procedure TfrmExMain.UtiwakeCopy(Sender: TObject);
var
  exCol : char;
  iRow,iCol, IR,R, n: integer;
  tmp : variant;
  str : string;
begin
  if ExcelApplication2.Visible[GetUserDefaultLCID] then
    ExcelWorksheet2.ConnectTo(ExcelWorkbook2.Worksheets['内訳書'] as _worksheet);
    ExcelWorksheet2.Select;
    ExcelWorksheet2.Range['A3','A3'].Select;
    IR := 1;
    tmp := 0;
    Clipboard.AsText := '';
  for iRow := 1 to exR do
  begin
    for iCol := 1 to exC do
    begin
      exCol := Chr(Ord('A') + (iCol - 1));
      if Data[iRow, iCol] <> '' then
        tmp := Data[iRow, iCol];
      if Data[iRow, iCol] = '' then
        str := ''
      else
        str := string(tmp);
      if (iRow mod 21) = 0 then
        str := '';
      if length(tmp) >10  then
        ExcelApplication2.ActiveWindow.ActiveCell.Range[exCol + IntToStr(iRow),
              exCol + IntToStr(iRow)].WrapText := True;

        Clipboard.AsText := Clipboard.AsText  + str;
        if iCol < 7 then
          Clipboard.AsText := Clipboard.AsText + #9
        else
          Clipboard.AsText := Clipboard.AsText + #13#10;
    end;
    if (iRow mod 21) = 0 then
    begin
      R := IR + Trunc(IR/21) - 21;
      ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[R,1].pasteSpecial;
    Clipboard.AsText := '';
    end;
    IR := IR + 1;
  end;
  finalize(Data);
end;

尚、折り返しは+#10を使うと下のセルに移るようでしたので、リストのままとしています。


HOta  2007-08-26 02:04:32  No: 27468

頁と行数は別にすればどうでしょう。
>    if (iRow mod 21) = 0 then
>    begin
>      //R := IR + Trunc(IR/21) - 21;  マスク
         R := (IR - 1) * 22 + 3;   //頁により行数を決める
> ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[R,1].pasteSpecial;
>      Clipboard.AsText := '';
       Inc(IR);                   //頁増加
>    end;
>    //IR := IR + 1;  マスク


kim  2007-08-26 09:02:42  No: 27469

HOta様
行が少しずれますが、殆んど変わりません。
5-24,29-48,75-94,143-162,233-251...となります。
なぜでしょうね?
もう少しがんばります。


HOta  2007-08-26 15:23:53  No: 27470

おかしいな?
(1 - 1) * 22 + 3 =  3
(2 - 1) * 22 + 3 = 25
(3 - 1) * 22 + 3 = 47
のはずですが??

下記のように頁毎でなく、全てを一度にすればどうでしょう。
>    if (iRow mod 21) = 0 then
>    begin
>      //R := IR + Trunc(IR/21) - 21;  マスク
       Clipboard.AsText := Clipboard.AsText + #13#10 + #13#10 + #13#10 + #13#10 + #13#10;
> //ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[R,1].pasteSpecial; マスクループの外に出す。
>      Clipboard.AsText := '';
       Inc(IR);                   //頁増加
>    end;
>  end;
//追加
ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[3,1].pasteSpecial;


kim  2007-08-27 03:17:32  No: 27471

HOta様

    if (iRow mod 21) = 0 then
    begin
//    R := IR + Trunc(IR/21) - 21;
      Clipboard.AsText := Clipboard.AsText + #13#10; //1個だけ
//     ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[R,1].pasteSpecial;
//      Clipboard.AsText := '';  //消去
//      Inc(IR);  //消去
    end;
  end;
  ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[1,1].pasteSpecial;  //[1,1]に
  finalize(Data);
end;

でうまくいきました。
家と会社でマシン速度が違うのですが、65頁分10分程かかっていたのが
2分ぐらいに短縮されました。
長い間本当にありがとうございました。
今後ともよろしくお願いいたします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加