October 05, 2003

VBAで泣かないために

バイトで現在、VBA(Visual Basic for Applications)っていうのを書いてます。いわゆる、あれですよ、ExcelのMacroとか。で、やっていることはデータをグラフィカルに表におこしたりすることなわけで、一見猫作業=繰り返しやりつづける(どっちかっていうとハムスター作業かも)にみえるわけですが、いかんせんVBAっていうのが非常に詐欺的な言語(言語としても認めたくないぐらい)であるため、死にそうになっています。ってことで今回の御題はすばり『VBAで泣かないために(もう結構泣いたよぅ…)』。

VBAっていうと一般的な使い方はどうもExcelの『マクロでポン機能(マウス操作とかキー操作とかをマクロとして記録してくれるやつ)』をプラモデル的に組み合わせて使っている人が多いようです(もちろん、普段自分もこういう使い方してマクロ作っています)が、今回の作業がデータの構造をきちっととらないとあとあと破滅的になる(データベースからデータをひっぱってきているのです)ものだったので、今回はオブジェクト指向的にクラスモジュールなるものを使ってみました。クラスモジュールの使い方とかは他の人が細かく解説してくれていると思う(なんて無責任な…)ので、今回はずばり、プログラマーなあなたにおくる、VBAでは『クラスモジュール使ってオブジェクト指向やろうとしたのに、そんなことできないの、なんでやねん!!(ぶちっ)』特集といきたいと思います。実際あれができて当然と思い込んで泣かされたことが多数あるので、これは『VBAで泣かないために』っていう御題にぴったりかと思います。

まず当然のごとく、ポリモーフィズムがありません。ポリモーフィズムっていうのは、簡単にいえば、例えば同じ名前で引数の数や種類が違っていると違うものとして識別してくれる機能です。これよって、同じ名前でいくつも関数をつくって場面に応じて使い分けるといったことが普通のオブジェクト指向言語ならできるのですが、できません。もしどうしてもやりたいならVaraint型とかで引数をとって中でひたすら分岐しまくる、という手口を使うしかないんじゃないでしょうか?

次にコンストラクタがいけてません。コンストラクタであるClass_Initialize()は予約されていて、できるということとといえば、内部のオブジェクト変数を初期化するくらいです。しかもそのときはSet hoge = New Collectionみたいな感じでやるんですが、Setってなんなんですか?それゃ、Javaみたいにプリミティブ型とオブジェクト型ではっきりわかれてて、値を代入しているのか、参照を代入しているのか常に意識しなければならない言語ならちょっぴり仕方ないと思うけど、VBAなんて所詮、実行時にアバアバな型チェックしているだけだろっ、っうに。もうSet地獄から逃れたいです…

で、なぜかMethodは5つもありますがな。Sub、Function、Property Get、Property Set、Property Let…。SubとFunctionはまぁ、許そう。Propetryっていうのがねぇ、気持ちが悪い。Propertyっていうのがあるためにクラスとして完全なクロージャーが実現していねえんじゃねぇ??と思ってみる…

あと、当然のごとく(そろそろしつこいかも…、すんません)、クラスでプロパティを保持するクラス変数はありません。

以上のようなことに当分の間はまっていました。VBAに期待??しすぎなのだろぅか。次は演算子編の予定。
変なテンションですが、ようはストレスをぶちまけているだけなのです、すいませんm(_ _)m

※猫作業とハムスター作業の違いについて
猫作業=あきもせず猫じゃらしを追いつづけたり、蝉にとどめをささずにぴょんぴょんしてみたり、とそんな猫がするような連続的行為。猫パンチといい、よくもまぁ、あんだけ同じ動作の繰り返しができるもんだ。
ハムスター作業=夜にひたすら、ひたすら、ひたすら車輪を回しつづける…、まるでインストールやパソコンの組み立てではまった時に人間がとる行動に近い(何度もインストール、何度もメモリチェック…)
どこがちがうんでしょうか…。たぶんハムスター作業のほうが体に悪そうかと…。

19:19 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | この記事をdel.icio.usでブックマーク | トラックバック
このエントリーのトラックバックURL: http://fenrir.naruoka.org/mt/mt-tb.cgi/19
コメント

かなり前の記事にコメントして申し訳ないけど
一応インターフェイス使えばポリモーフィズム使えますよ
hoge as IHoge はインターフェイスとして
Select Case TypeName(hoge)
Case "CHoge"
Case "CHoge2"
End Select
ちょっとルビーっぽい?
いちいちタイプ名の文字列でわかれてるのがウザいですが

Posted by: hige : October 5, 2009 08:14 AM

>higeさん
なるほどこんな技があるのですね。TypeNameってC++のキーワードにもありますが、使い方が全然違うので混乱しそうです。

Posted by: fenrir : October 8, 2009 10:34 AM

今の職場だとExcel2000のVBAぐらいしか使えないので・・・
色んな言語を渡り歩くと、protected,private,publicとかのスコープの違いなんか気になりますよね

VBAで私が泣いたのは
・イテレータがcollectionと配列ぐらいにしか使えない
・関数がオーバーロードできない
・コンストラクタの引数が固定←書かれてますね
・Excelのバグや、変な仕様を気にするあまり大量のエラートラップが・・・
・フォームのイベントがいまいち使えない
・そもそもExcel2000ではオートシェイプがズレル→ブックを開く人によって、内容がかわる・・・汗 それに伴って、ズレ量をごまかしたり、オートシェイプのバウンドボックスが回転が入るとまったく使えないだとか、グループ化されたオブジェクトの座標が良くわからないとか←デバッガで見ると、整数型・・・Singleじゃなかったのか・・・だとか


良いところは
・会社で使える(笑 前はborlandのコンパイラ入れてましたが・・・IDEまで何も準備せずに使えるVBAが結局・・・)
・Excelの関数等はヘルプを見るだけで使える(インターネットも使えない環境)
・Win32APIならそれなりに使える

まぁ、妥協の塊のようなメリットですが・・・

オブジェクト志向で困ったといえば、SingleTonなクラスが実現できないとか モジュールもクラスみたいなものなんだから、オブジェクトとして扱わせてくれよ・・・と思ったり・・・
オブジェクト指向使わないでVBAプログラムしてる人って、ポインタも何も無い状況で、データ構造どう扱ってるんでしょうね・・・笑
クラスを使えばデータ構造作れるので、Cの構造体使ってクラスを実現するのを逆にしたと思えば・・・

気持ち悪いコードがたくさん出てきますよ

実行速度でも
Win32のDIBitmapを使った
メモリマップドビットマップなんて、死ぬほど重くて使えた物では無かったですが、GDIに限定すれば使えます

ここまで書いておいて何ですが
C++のコンパイラが使える環境なら、dll作ってExcelで呼んで使用しますね・・・
Excel上で動く というニーズがあるんですよね・・・

VBAで泣かないためには、WindowsAPIを学んだ時のような・・・哀しい覚悟が必要ですね・・・

Posted by: hige : October 10, 2009 02:48 PM

>higeさん
長文のコメントからご苦労が伺えます。
Excelで動くメリットが社会的にはかなり重要だ、というのは同感です。現場によってはExcelがWordとして使われているようですから。改行するかわりにセルで文章を組む、とか本当に見ていて痛々しい限りです。ITがまさに雇用を創生しているのが頷けます(笑)。

Posted by: fenrir : October 17, 2009 07:16 PM

Setについてですが確かに面倒ですね。
VBAの各種オブジェクトのデフォルト・プロパティが単なる代入式(Let)で代入可能なのでSetが欠かせないという羽目になったと私は思っています。個人的にはデフォルト・プロパティなんかいらんのにと思う次第。

DIM foo as Range
set foo = Range("A1")
foo = Range("B2") '' (1)

こう書かれていて、これをどう解釈するかが、Setなしには立ち行かなくなるのが痛い。デフォルト・プロパティがなければ、(1) では foo に Range("B2") の参照が代入されるとVBA側が解釈すればよいのですが、実際にはデフォルト・プロパティであるvalueがあるために、 foo.value = Range("B2").value という結果と同じになってしまいますよね。Set の有無で解釈が変わってしまう(動作が変わってしまう)のもいただけません。デフォルトがあると便利だろうと考えてそのようにしたのかもしれませんが、おかげで Set を余儀なくされてしまいました。 仕様と言えばそれまでですが、個人的には使用するプロパティは明示されるべきだと思います。

foo.value = Range("B2").value

これでいいじゃないかと。デフォルト・プロパティを考えた人は、「ナイス!」って思ったんでしょうね。。。トホホです。

Posted by: ironya : February 18, 2011 11:33 AM

>ironyaさん
コメントありがとうございます。随分と過去のことなので記憶とともにVBAは葬り去りましたが、なるほど『ナイス』って思っちゃったことによる弊害なんでしょうね… 確かにSetなしでは立ち行きませんね。

Posted by: fenrir : February 20, 2011 10:56 PM
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。