お世話になっております。
さっそくですが過去ログの
「ExcelのデータをDelphiで読み込むには」にて、
ウォレスさんの以下のサンプルで
保存したファイルからは読み込めましたが
現在表示されている、シートの内容を
読み込むには、どのようにすればよいのでしょうか?
それともシートの内容が更新される度に、
上書き保存してやる必要がありますか?
よろしくお願いします。
---------------------------------------------------
var
ExcelApp: Olevariant;
ExcelBook: Olevariant;
ExcelSheet: Olevariant;
iRow: Integer;
iCol: Integer;
Ctmp: Variant;
begin
ExcelApp := CreateOleObject('Excel.Application');
ExcelBook := ExcelApp.WorkBooks.Open('c:\tmp\test.xls', False);
ExcelSheet := ExcelBook.WorkSheets['テスト用'];
Memo1.Clear;
for iRow := 1 to 5 do
begin
Ctmp := '';
for iCol := 1 to 5 do
begin
Ctmp := ExcelSheet.Cells[iRow, iCol].value;
Memo1.Lines.Add(InttoStr(Ctmp));
end;
end;
end;
---------------------------------------------------
ここにExcelを操作するクラスがありますよ。
これではできないだろうか?
http://www.geocities.jp/lupin_home/
さださん、ありがとうございます。
やってみましたが、やはり保存されたデータ
でないとダメみたいなので、それで
やります。
イマイチ納得はできませんが・・・・
解決済みということですが,ちょっとのぞいたものでから...
「現在表示されている」の意味が不明なのですが.
1. 表示されているブックのあるシートのセル値を取得したが
既に保存済みのデータが表示されてしまう.
2. ブックを表示してからその値をMemo1に表示したい.
もし,2.であれば,
ExcelSheet := ExcelBook.WorkSheets['テスト用'];
のあとに,
ExcelApp.Visible:=True;
を追加すれば表示は可能です.
意味を取り違えていたらごめんなさい.
Mr.XRAY様、ありがとうございます。
実は、私がやりたい事は、
ファイルに保存されていない、Excelのデータを
Delphiで読み込む(操作する)事なんです。
現状はDelphiで出来そうにないので、データを
入力した後に必要に応じてファイルに出力してもらい
それをインターバルタイマーなどで読み込む仕様で
納得してもらおうかと思った次第です。
あれからも調べていたら、VBの掲示板でこの表現で
の質問を見つけまして、うまい表現だなと思いました。
VBでは出来るようなんですけど・・・・
ええと、既に解決済みとなっていますが・・・
私もこの件に関しては知りたいです。
ビギナーなりの想像です。
ハンドルからOLEヴァリアントへのオブジェクト代入(言葉遣いは正しい?)ができればいいのですよね?
CreateOleObject のかわりに GetActiveOleObject を使うにしてもファイル名が必要ですので、1度も保存されてないEXCELには無理そうですし。
ハンドルの取得はEnumWindowsProcで出来そうです(あたりまえ?)
[Servers]タブのTExcelApplicationなら,既に起動中のExcelに
接続できるんだけどな...
このコンポのConnectメソッドです.
同じようなものが,OleObjectというんですか,あるのではないかと
思うのですが.調べる気力なし.ゴメン!!
>Servers]タブ・・・・
それって多分professional版ですよね?
私みたいなサンデープログラマはDelphi6Personalです。トホホ
やはり、起動中のExcelに接続するのは(出来るのでしょうが)面倒そうですね。
できますよ.できるはずですよ.
今最初のコードを見直したら,保存済みのブックを読出していますよね.
目的は,
新規にブックを作成して表示する.
このブックのあるシートのあるセルに値を入力する.
この値を取得する.
でしたよね.
だったら既存のブックを,わざわざ開く必要はありません.
{ブック追加}
WorkBook := Excel.Workbooks.Add;
{WorkSheet1をアクティブにする。}
WorkSheet := WorkBook.WorkSheets[1];
{WorkSheet1をアクティブにする。}
WorkSheet := WorkBook.WorkSheets[1];
として,このシートを対象にすればいいだけのはずです.
かわにーさんの目的は、
>新規にブックを作成して表示する.
の部分が、「Delphiではなく、ユーザの場合」に、ということですよね?
一度も保存されていない場合、ブックをうまくOLEヴァリアントに代入する(用語使いが変かも)ことができません。
Mr.XRAYさんのおっしゃるように、Addメソッドを実行しましたが、接続しないようです・・・
頓珍漢でしたらすいません。
>頓珍漢でしたらすいません。
これは違いますね.多分,頭の中で考えている動作がお互いに異なって
いるためだと思います.以下にテストしてコードをリストします.
多分,ウォレスさんのは2.じゃないかと思います.私が想像したのは
1.の方です.新規だからどちらでも同じだと思ったんです.
それと,D6 Personal版でも,ちょっと面倒ですけど,ActiveXの取込み
をすると,TExcelApplicationが使えるようになります.
では,コード流します(Private以降).
private
{ Private 宣言 }
Excel: Variant;
WorkBook: Variant;
WorkSheet: Variant;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// 感想
// OleObjectはコード補完機能が使えないのが不便
// 逆にExce VABのコードがそのまま利用可能なのは便利
// でもやっぱりTExctApplictionの方が私はいい
// 以下のコードはusesにComobjが必要
//====================================================================
// 1.
// 新規にブックを作成し表示する
// 表示したExelのセルに値をセット
//====================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
{Excelのオブジェクトを作成}
Excel := CreateOleObject('Excel.Application');
{ブックを作成}
WorkBook := Excel.Workbooks.Add;
{シートオブジェクトを定義}
WorkSheet := WorkBook.WorkSheets[1];
{表示}
Excel.Visible:=True;
{セルA1に文字ABCをセット}
WorkSheet.Cells[1,1].Value:='ABC';
end;
//====================================================================
// 2.
// 既に誰かが表示したエクセルを操作する
// でも誰だ.このプログラムを起動する人とは別?
//====================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
{表示中のExcelのオブジェクトを取得}
Excel:=GetActiveOleObject('Excel.Application');
{シートオブジェクトを定義(ここではSheet3)}
WorkSheet := Excel.WorkSheets[3];
{そのシートをアクティブにする}
WorkSheet.Activate;
{表示}
Excel.Visible:=True;
{セルA1に文字ABCをセット}
WorkSheet.Cells[1,1].Value:='ABC';
end;
//====================================================================
// 終了処理
// これでいいのかは不明(取敢えずメモリリークはない)
//====================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
try
WorkBook.close;
WorkBook:=unAssigned;
WorkSheet:=unAssigned;
Excel.Quit;
Excel:=unAssigned;
except
end;
end;
end.
スンマセン.Button2のクリックイベント修正します.
前のだと,エクセルが起動していない場合にOLEエラーが発生します.
procedure TForm1.Button2Click(Sender: TObject);
begin
try
{表示中のExcelのオブジェクトを取得}
Excel:=GetActiveOleObject('Excel.Application');
except
ShowMessage('エクセルが起動していません');
exit;
end;
{シートオブジェクトを定義(ここではSheet3)}
WorkSheet := Excel.WorkSheets[3];
{そのシートをアクティブにする}
WorkSheet.Activate;
{表示}
Excel.Visible:=True;
{セルA1に文字ABCをセット}
WorkSheet.Cells[1,1].Value:='ABC';
end;
再びごめんなさい.WorkBookへの接続を忘れていました.
というわけで,以下にコードをUPしました.変更があれば
ここで修正します.
http://homepage2.nifty.com/Mr_XRAY/Others/OleObject_for_Excel1.htm
HP拝見しました。
同じようにしたつもりですが、やはり、表示中のEXCELには接続できませんでした。
(新規作成はうまく行きました)
Win2K+SP4+Delphi6Personalです。
環境の差でしょうか・・・?
どなたか近い環境の方で試していただける方いませんでしょうか・・?
Win2K+D6 Personal+Excel2000
Win2k+D6 Peraonal+Excel97
で実行しました.表示中のExcelにも接続しました.
ただし,「同じように」ではなく,HPにUPしたコードのままです.
同じようにではなく,同じコードだとどうなるか確認してみて下さい.
つま,Sheet3のA1セルにABCが入力されるかどうかですね.
(そうしないと会話が成り立ちません)
それでダメなら他の方法を考える必要があります.
Win2K+SP4+Delphi6 Enterprise
では、うまくいきましたよ!
Button2Clickの中だけでもコピー∩ペーストしてみるといいかも
しれませんよ。
ウォレスさんのExcelはExcel95っていうことはないですか?
そうするとCells[1,1]という風な使い方はできません。
ここの部分は忘れてしまいましたがCells????のように指定するはずです。
※EXCELのバージョンは2000です。
目を皿のようにして間違いを探しましたが、判りません。
(そもそもHPからコピペしているので、ボタンの番号が入れ替わってない限り、差はないのです。)
ぐお〜なんで私だけ?と思いつつ、ただ何度も実行しつづけていると、(その間コードは触らず)突然、出来るように!
そして、また何度か実行していると、また全く接続しないように・・・
IDEと実行ファイルと両方試してみましたが、両者に特別差があるようにも思えません。
とにかく再現性が極めて低いようです。やはり環境なのかな・・・
今からPC立ち上げなおしてやってみます。
うーん、そうしたら出来ない状態の時にタスクマネージャーを確認してみてください。
表示上はExcelが起動していないのにタスクマネージャーの中でExcelのExeが起動していたりしていませんか?
実際には表示上見えていないExcelに接続しているのかもしれません。
お騒がせしています。
PC立ち上げ直後に試してみましたが接続できません。
EXCELの新規作成は必ず成功します。
しかし、接続の方はうまくいきません(><)
結局、先ほど3度ほど成功しただけで後は全く思うように行きません。
皆さんは成功されているようなので、PCの環境の差じゃないかな、と思います。
LupinⅢさん、ありがとうございます。
タスクマネージャで確認しましたが、プロセスにもEXCELらしきものは見当たりませんでした。
しかし、変なことに気づきました。
タスクマネージャでEXCELがいないことを確認 → Button2をクリック
で、本来ならShowMessageを行うはずですが、ここに飛びません。
・・・というかButton2のイベントが関連付けられていないではないですか・・
あれえ?Button1と4は関連付けられているのに??
そもそも、先ほど成功したのに・・・と言い訳してみます(汗
あまりに初歩的なミスで恥ずかしい限りです。みなさん、おさわがせしました。
ツイート | ![]() |