VBレスキュー(花ちゃん)
VB2005用トップページへVBレスキュー(花ちゃん)のトップページVB6.0用のトップページ各掲示板

リンク元へ戻ります。 Excel・Word 関係のメニュー
1.VBからExcel及びWordを操作する時の注意事項
2.VBからエクセルを起動・終了する基本操作例
3.上記、基本操作例を使ってのVBからExcel にデータを送りグラフを表示
4.Excel ワンポイントテクニック集
5.Excel 2007 以降のリボンを操作する及びユーザーからの操作を禁止する
6.指定のセル範囲の列幅・行の高さを含めてコピー・アンド・ペーストする
7.
8.
9.
10.
11.VB6.0 からワードを起動・終了する基本操作例
12.Word の既存ファイルを読み込み検索・置き換え後保存する
13.VB6.0からExcel/Wordを起動しExcelの表をWordに貼付印刷する
14.VBから Word の差し込み印刷機能を使って[宛て名ラベル]を印刷する
15.Word の Tasks プロパティを使ってのタスク(プロセス)の一覧を取得・他
16.Word VBA 簡易リファレンス及び使用例
17.
18.
19.
20.


1.VBからExcel及びWordを操作する時の注意事項
1.VBから Excel を操作する時の注意事項
2.Excel のプロセスが正常に終了しない理由
3.ActiveCell にみる Excel のプロセスが正常に終了しない状況の検証
4. 
5. 
6. 

 下記プログラムコードに関する補足・注意事項 
動作確認:Windows Vista・Windows 7 (32bit) / VB6.0(SP6)
Option :[Option Explicit]
参照設定:追加なし
使用 API:
なし
その他 :
    :
このページのトップへ移動します。 1.VBから Excel を操作する時の注意事項
1.当サンプルをご使用になる前に、プロジェクト→参照設定で Microsoft Excel *.* ObjectLibrary にチェックを入れておいて下さい。
又、バージョンの異なるExcel を複数同じパソコンに導入している場合は、それぞれの共通となるバージョンで設定しておくと、どのパソコンで使用できるようです。
例、開発環境(9.0 で参照設定) 実行環境(Excel2000/Excel2002/Excel2007) でExcel 2007が立上がり問題なく動作します。(但し、ご自分の環境で確認して下さい。プログラム内容にもよる)
※ Excel 2007 での動作は、Excel のシート・ブック類は旧のバージョンで作成したものを使用すれば、互換モードで動作するので、大抵の場合 Excel 2007 上でも動作します。
但し、Excel 2007 で作成したブック等を使用した場合は動作の確認は行っておりません。
2.VB から Excel を操作する場合、事前バインディング(アーリーバインディング)の変数を使う方法と実行時バインディング(レイトバインディング)の変数を使う方法があります。
事前バインディングを使用するメリットとして、事前バインディングされたオブジェクトは遅延バインディングされたオブジェクトよりも処理が高速です。また、使用されているオブジェクトの種類が明確になるため、コードがより読みやすくなり、保守も簡単になります。
特に、自動コード補完やダイナミックヘルプなどの便利な機能が有効になります。これは、Visual Studio の統合開発環境 (IDE) により、コードの編集中に作業しているオブジェクトの種類が正確に判断されるためです。
事前バインディングを使用すると、プログラムのコンパイル時にコンパイラがエラーを報告できるため、ランタイムエラーの数が減少し、エラーの重大性も低下します。
又、コーディング段階で、オブジェクトで使われているプロパティやメソッドの構文がチェックされて、誤りがあるとエラーが表示されます。(自動メンバー表示などのインテリセンス機能も働く)
逆に、実行時バインディングのメリットとしては、参照設定する必要がなくなり、Excel の各バージョン間でバージョンを気にしないで使用できるという事です。
しかし、デメリットとして事前バインディングでのメリットの部分の恩恵が受けられず、定数の宣言を独自にしないといけないし、インテリセンス機能も働かず、プロパティやメソッドの構文がチェックがされない為、間違ったコードを書いても気が付かず、エラーの温床になりかねません。
従って、この書き込み等を参考にされている方や掲示板で質問されるレベルの方は、事前バインディングを使用するようにして下さい。

  Dim xlApp As Object        '実行時バインディングの変数
  Dim xlApp As Excel.Application  '事前バインディングの変数

不慣れな方が、参照設定をしなくてもいいし、各バージョンで共通で使用できると安易に使用されると、エラーが発生したり、Excel のプロセスが終了しない等の原因の元になり、原因が掴めず却って手間がかかる事になり、挙句の果て掲示板にバグ取りの依頼の書き込みをする羽目になります。

3.New キーワードを使ったオブジェクト参照の代入 とCreateObject 関数を使ったオブジェクト参照の代入について
New キーワードを使ったオブジェクト参照の代入は、ActiveX コンポーネントがタイプライブラリを提供している場合は、変数宣言またはSet ステートメントで New キーワードを使って新しくオブジェクトを作成し、オブジェクト変数にオブジェクトの参照を代入することができます。

CreateObject 関数を使ったオブジェクト参照の代入は、ActiveX コンポーネントがタイプライブラリを提供しているかどうかに関係なく、Set ステートメントで CreateObject 関数を使うと、新規オブジェクトを作成し、そのオブジェクトへの参照をオブジェクト変数に代入できます。
VB5.0 やVB6.0がでた当時は、CreateObject 関数を使ったオブジェクト参照の方が一般的でしたし、下記サイトにも[Microsoft Office アプリケーションのインスタンスを作成する場合は、New ではなく CreateObject を使用します。]のように書かれております。
http://support.microsoft.com/kb/244264/ja
従って、私も CreateObject を使っておりましたが、VB6.0 の上位バージョン(.NET系)では、New キーワードを使った方法が一般的なので、今回見直しにあたり、New キーワードを使った方法に変更します。

4.VBから Excel を操作すると Excel のプロセスがタスクマネージャーに残ったままになる
下記のExcel VBA オブジェクト一覧表中のオブジェクトと等オブジェクトを返すプロパティ類を間違った操作をするとメモリが解放されず、プログラムを終了してもタスクマネージャーにExcel.exe が残ったままになる事があります。
Excel VBA オブジェクト一覧表
この事は、誰もが一度は経験している事かと思いますし、掲示板への書き込みも多く見られます。
尚、この事は、.NET系の上位バージョンでは、余計厳密になり、VB6.0の場合よりメモリが解放されにくくなっております。
この件は、色々原因がありますますので、別の項で詳しく説明します。
5.
6.
7.
8.
このページのトップへ移動します。 2.Excel のプロセスが正常に終了しない理由
1.一番の原因は、使用した Excel のオブジェクトのメモリの解放もれによるものです。
従って、戻り値にオブジェクト型を返すようなオブジェクトを使用する場合は、変数等に受けて使用後は、解放処理をしてやる必要があります。
本来は、上位バージョンの .NET 系から Excel を操作する場合の時のように使用する必要があるのですが、VB6.0 から Excel を操作する場合は、ある程度 VB6.0 が処理してくれるようで、.NET 系 のようにすべてが解放もれになるような事はありませんが、.NET系に移行された場合にとまどうような事がないようにできる限り、変数に受けて使用し、使用後は、速やかに解放しやるようにして下さい。
2.VBA は、Excel の中で使用していますが、VB6.0 の場合は、VB6.0 から EXcel を介して、Excel のオブジェクトを操作する事になるので、明示的に指定してやる必要があります。
例えば下記のような場合
ActiveSheet ActiveCell Key1:=Range("C2") xlSheet.Range(Cells(1, ・・・略  Selection.ClearContents ,etc.
このような指定の仕方を VB6.0 からするとどのシートを指しているのか、どのセルを指しているのかが曖昧になり、メモリが解放されなくなります。
VBAの場合は、使用しているところが自動的に含まれるので、上記のようなコードを使っても問題ないのですが、VB6.0 の場合は、EXcel を介しているので、その分どのブックを指しているかのように明示的に指定する必要があります。
従って、VBAのコードをそのまま使ったり、マクロの記録で取ったコードをそのまま使ったりすると、メモリがうまく解放されず、Excel のプロセスが残る原因になります。
VB6.0 の場合の、解放されない原因は、こちらの場合がほとんどです。

詳しくは、マクロをVBのコードに変換する場合の注意事項(VB6.0 基本編) ( No.14 ) を参照して下さい。

3.このようにプロセスが残る原因がはっきりしているので問題点を探す事はそう難しい事ではありません。
一番簡単な方法は、最初に、起動と終了のみのコードを書いて、きちんとメモリが解放されタスクマネージャーに、EXcel.EXE が残っていないか確認しておいてから、コードを追加する都度、解放されているか確認しながら、開発を進めていけば、どのコードを使用した場合にメモリが解放されなくなったかが分かるはずです。
その中で、あやしそうなオブジェクトを使用している部分をコメントにして試してみるとかすれば、どのオブジェクトが解放もれになっているのかが特定できるはずです。
その上で対処方法が分からない場合は、掲示板の方に質問されるのは歓迎しますが、コードを丸投げして解放されません、どこが悪いのでしょうかのような質問は、お断りします。
4.ここでいうメモリが解放されないとか、タスクマネージャーにプロセスが残ったままになるという場合は、プログラム上で使用した Excel を終了(解放)した時点での事で、プログラム自体は、起動したままでの状態を指しております。
プログラムそのものを終了したら解放されたという場合は、本来解放もれになっている場合が殆どです。
正しく使っていれば、プログラム起動中でも、Excel を解放した時点で、タスクマネージャーからExcel.exe が消えなければなりません。

このページのトップへ移動します。 3.ActiveCell にみる Excel のプロセスが正常に終了しない状況の検証
まず、2.VBからエクセルを起動・終了する基本操作例 のコードが使用できるようにしておいて下さい。
Command3 と Label1 を Form に貼り付けておいて Command3 のクリックイベントに次のコードを記入して下さい。

Private Sub Command3_Click()
  xlSheet.Activate
  Label1.Caption = ActiveCell.Address
End Sub

準備ができたら、Excel を起動して、Excel が表示されたら、Command3 をクリックして、Label に、$A$1 と表示されているのを確認して下さい。
確認ができたら、Excel の終了ボタン(Command2)をクリックして、Excel を終了してタスクマネージャーに、EXCEL.EXE の表示があるか確認してみて下さい。
タスクマネージャーのプロセスタブのところで、EXCEL.EXE の表示があるかと思います。
この状況が、プロセスが残っているとか、EXCEL.EXE のプロセスが消えないと言われている状況です。
一見上記のコードは正しいように見えます、現にVBAのヘルプの使用例と同等の使用例でもありますが、VB6.0から使用する場合は正しいとはいえないからです。
Excel の VBA のヘルプを詳しく見ると、下記のように書かれています。
------------------------------------------------------------------------------------------
オブジェクトを返すプロパティです。最前面に表示されている、アクティブウィンドウまたは指定されたウィンドウでのアクティブセル (Range オブジェクト) を返します。ウィンドウに表示されているシートがワークシートでないときは、このプロパティは失敗します。値の取得のみ可能です。

構文

.ActiveCell

Application オブジェクトを表す変数。


使用例

次の使用例は、メッセージボックスにアクティブセルの値を表示します。アクティブシートでない場合、ActiveCell プロパティは失敗するので、ActiveCell プロパティを使用する前に、Sheet1 をアクティブにしておきます。

Worksheets("Sheet1").Activate MsgBox ActiveCell.Value
------------------------------------------------------------------------------------------
ここで、注意しなけばならないのが、 Application オブジェクトを表す変数。です。Excel 上で使用する VBA は、そのApplication 上で動作しているので省略が可能で、ActiveCell.Value と書いても問題がないのですが、VB6.0 から使用する場合は、Application オブジェクトを表す変数を使って使用しないと間違った使い方となります。
(エラーとはならないが、上記実験の結果でも分かるようにメモリがうまく解放されません。)

それでは、次に、Application オブジェクトを指定して試して見て下さい。
何度か、Excel 上の違うセルをクリックして、その都度次のコードを実行して見て下さい。

Private Sub Command3_Click()
  xlSheet.Activate
  Label1.Caption = xlApp.ActiveCell.Address
End Sub

何度か、Command3 ボタンをクリックして、動作を確認してから、Excel の終了ボタン(Command2)をクリックして、Excel を終了してタスクマネージャーに、EXCEL.EXE の表示があるか確認してみて下さい。(このプログラム自体は起動したままで)
今度は、EXCEL.EXE の表示がありませんよね。
今回のような場合は、プログラムを終了すれば、タスクマネージャーから、EXCEL.EXE は消えてしまいますので、問題がないと誤解されたり、エラーがでないし、動作(取得できている)はしているので気がつかない人もおられるようですが、何度か同じことを繰り返したり、他の同様な間違った使い方と併用したりすると、プログラム終了後でもタスクマネージャー上に残ったままになったり、メモリリークを起こしたりします。その時点では、どの部分が問題なのか特定する事が難しくなり、挙句の果てに掲示板のお世話になる事になります。
従って、そう言う事ににならないように、[Excelの起動][プログラムのテスト][Excelの終了]と今回のようにプログラムを分けて書いて、コードを追加する度にテストをしてプロセスが残っていない事を確認しながら開発を進めて下さい。

このページのトップへ移動します。 4.


このページのトップへ移動します。 5.


このページのトップへ移動します。 6.


このページのトップへ移動します。 検索キーワード及びサンプルコードの別名(機能名)




このページのトップへ移動します。