CSVデータをstring2次元配列に読み込み、COMのExcelApplication、ExcelWorksheetを利用してExcelに表示させているのですが、
表示に時間がかかります。
配列の代わりにStringGridを使っても殆ど差はありません。
COMのほうに原因があると思われます。
よい方法はないでしょうか?
CSVデータをTab区切りにして、クリップボードを使用して貼り付けたらどうでしょう。
クリップボードに取り込んだデータをExcelのセルに持ってくるのはどうすればいいのですか?
ExcelApplicationのRange.Valueに代入するのであれば同じだと思うのですが。
ここらへんですかね。
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);
ありがとうございます。早速やってみます。
結果は後ほど。
すみません。
var ARange : Range;
で Range が未定義の識別子のエラーになります。
すみません。タイプミスです。
var ARange : Range;
で 「Rangeが未宣言の識別子です。」のエラーになります。
。。。
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
悪戦苦闘していて、報告が遅くなり申し訳ありません。
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;
としています。
全ての行をクリップボードにコピーしないと、遅くなります。
改行は、「 + #13#10」を入れます。
行内にデーターが無い場合は、改行だけにします。
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桁です。
3行目から21行目までのデーターをクリップボードに用意します。
改行は、「 + #13#10」を入れます。
10文字以上のデータの折り返しは、文字の間に「 + #10」とすれば改行が入ります。
ExcelApplication2.ActiveWindow.ActiveCell.Cells.Item[3,1].pasteSpecial;
とすれば、一度でできます。テストはしてみましたか?
いろいろ条件があるのなら、以前のとおり、ゆっくりと動作させれば良いでしょう。整形などは時間がかかります。あらかじめ行や列が決まっているなら、テンプレートを作って、その中にデータを流し込めば良いのではないでしょうか?
Excelは後でいろいろできますが、その分時間はかかります。
エクセルクリエーターを購入するのが定番ではないかと思うのですが。
HOta様 いつも有難うございます。
お教えいただいたことを参考にいろいろやっているのですが後一歩?のところでうまくいきません。帳票はシート一枚で上から連続しており、一ページ22行、その内上の2行は表題と空白行とし、データは3行目から22行迄、次の頁からは25〜44、47〜66、69〜88、91〜110行となり、Items[R,1]のRに3,25,47,69..とうまく代入されているのですが、3頁目が4頁目に表示され,
以降も頁がだんだん大きくずれてしまいます。変数には上手く正当な数字が代入されているのに、なぜ途中から頁がずれるのか(頁にデータは上手く納まっているのですが)不思議でなりません。
もう少し頑張ってみます。
フサ様
天邪鬼ですが、自分で作ってみたいので、頑張ります。
ありがとうございました。
変数の使い方がおかしくなっているのですね。
一度、その部分のソースをあげてみたらどうでしょう。
多分、頁毎の初期化がうまくいっていないのでしょう。
ところで、1頁毎にpasteSpecialしているのではないようですね。
1頁毎にpasteSpecialしたほうが、早くなりますよ。
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を使うと下のセルに移るようでしたので、リストのままとしています。
頁と行数は別にすればどうでしょう。
> 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; マスク
HOta様
行が少しずれますが、殆んど変わりません。
5-24,29-48,75-94,143-162,233-251...となります。
なぜでしょうね?
もう少しがんばります。
おかしいな?
(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;
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分ぐらいに短縮されました。
長い間本当にありがとうございました。
今後ともよろしくお願いいたします。
ツイート | ![]() |