« Firefox 2.0.0.12リリース | トップページ | ルータが壊れた »

2008年2月 9日 (土)

不安定なExcel VBAマクロの作り方

日頃仕事でExcel 2003のVBAのマクロを沢山作って使っているのだけど、どうにも不安定なマクロがいくつかある。そのマクロがあるファイルを開くと頻繁にExcelが落ちるのだけど、どうもオブジェクト型変数を使っているものが怪しい感じ。

今まではオブジェクト型変数を関数内で宣言して使ったあとはそのまま放置して関数を抜けていたのだけど、関数から抜ける時にその変数にNothingを代入するようにしてみたら安定して動作するようになった。

よく考えてみると、たぶんこういう事ではないかと。

Dim xx As Object

として宣言したオブジェクト型変数は、使用時に

Set xx = Workbook.Add

などのようにSetステートメントを使って使用するオブジェクトを割り当てる。ExcelのVBAのヘルプなどを読むと、オブジェクト型変数そのものはオブジェクトを参照するためのアドレスを格納する変数で、Setでオブジェクトを割り当てた時に、オブジェクトの情報を格納するためのメモリ領域を確保して、そのアドレスがオブジェクト型変数に格納されるという事らしい。

問題なのは、何かのオブジェクトを割り当てたままその変数が宣言された関数を抜けてしまうと、オブジェクト情報を格納したメモリ領域が残されたままでオブジェクト型変数だけが削除されてしまうことが起こるらしいことである。VBAが丁寧なメモリ管理をしていてくれたら、こうして参照されなくなったメモリ領域も解放してくれるのだけど、Micro$oftの作るものなのでそんな事を期待してはいけないのだろう。したがって、オブジェクト型変数を宣言した関数を抜ける前に

Set xx = Nothing

として何も参照していない状態にしてオブジェクト情報を格納したメモリを解放するのがVBAを使う人の責任、という事になるようだ。Cなんかだとmallocなんかで確保した領域はきちんと解放してあげるように意識するのだけど、VBAだとついその辺がルーズになってしまう (^^;)

オブジェクト型ではこうした問題があるのだけど、動的配列やVariant型の変数だとどうなんだろう? 今までは何も気にせずそのまま関数を抜けていたけど、ちょっと気になる。

動的配列の場合、最初にDimステートメントで宣言するときはその型の変数を参照するためのポインタが作成されるだけで、後でRedimステートメントでサイズを指定した時に実際にデータを格納するための領域が確保され、その先頭アドレスが変数に格納される。したがって、関数を抜ける前にEraseできちんと記憶域を解放しておく必要があるような気がする。そのくらいVBAの環境が処理してくれないかなあ。一応念のために、

Dim xx() As Double
Dim n As Long
...
Redim xx(n)
...
Erase xx

というように最後にEraseを追加。

Variant型は入れるデータによって使用するメモリサイズが変わるとヘルプにあるので(長い文字列や配列まで入っちゃうし)、こいつもどこかにデータを入れるための領域を確保して、Variant型の変数自身にはそこへのアドレスが格納されるだけという形のように思える。とすると、Variant型も最後にEmptyかNullを放り込んで記憶領域を解放する必要があるんだろうか。そういう記述はあまり見た事が無いので、これこそVBAの実行環境が勝手に処理してくれているんじゃないかと思うけど。そもそもVBAはデフォルトでは変数の宣言を強要しないし、変数の宣言をするにしても型名をつけなくてもOKな仕様で、どちらの場合も変数はVariant型として宣言されていると見なされる。こういう仕様なので、Variant型に対する取り扱いぐらいはちゃんとやっていると思うのだけど、M$製品は油断できないからなあ。

|

« Firefox 2.0.0.12リリース | トップページ | ルータが壊れた »

Windows」カテゴリの記事

Excel」カテゴリの記事

コメント

自分で宣言したんだから
それを解放するのは当たり前かと。。。

MS製品だからというより
プログラムを書いた人の意識の問題ですよ。

vbaを使いたくないなら
gcがあるjavaでpoiなんかを使えばいいわけで。

投稿: (;´Д`) | 2008年3月 3日 (月) 16時22分

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック


この記事へのトラックバック一覧です: 不安定なExcel VBAマクロの作り方:

« Firefox 2.0.0.12リリース | トップページ | ルータが壊れた »