「ネオ写経」のすすめ
「ネオ写経」のすすめ
新型コロナウイルス対応で外出の自粛が求められる中、みなさまいかがお過ごしでしょうか。
ろくにテレワーク環境も整っていないのに、「とにかくテレワークだ!」的に導入されてしまった事業所も、それなりにあると思います。
個人的には、この期間は〈終息後のダメージ回復〉を効果的に行うために個人が力量を高める機会ととらえるのが良いと思います。それができる余裕のある業界に限られますが……。
「ネオ写経」とは
私が勝手に考えました。
もともと、プログラミング界隈で「写経」といえば、サンプル・コードの類を写すこと。(ですよね?)
ただ、私は「写経」というものをしたことがほぼない。写しているうちに、「あら? じゃあ、ここはこうした方がおもろいやんけ。」とか、「ついでにこうしといたれ。」みたいなのが出てくるから、「般若心経」を写していたはずなのに、なぜか「あほだら経」が出来上がっていた、ということが起こる。
そんな私が考えた「ネオ写経」とは!?
既存クラスをラップしたクラスを作る。
これ。
ニセFileSystemObjectを作る
FileSystemObject
は便利だ。
しかも、プロパティ名とかメソッド名は、さすがプロが作っただけあって、実に良くできている。コードが実に読みやすくなる。
ところが、デフォルトでは使えない。
いちいち参照設定をせねばならん。
もちろんCreateObject
を使えば参照設定せずにすむ。
しかし、これだとObject
型変数に突っ込んで使用することになり、コーディング時に入力補完の恩恵が得られずイマイチ。
もちろん、コーディング時に参照設定をしておき、完成したら参照設定を切る、という方法もあるにはあるが、それはそれでメンドクサイ。
だったら、FileSystemObject
クラスをラップしたFileSystemObject
クラスを自作しちまえばいいんでねえの!
コンストラクタ
これは簡単。Class_Initialize
でScripting.FileSystemObject
クラスのインスタンスを得ればよい。
まず、プロジェクトにクラスモジュールを挿入し、オブジェクト名をFileSystemObject
にする。そして、クラスモジュールに次のコードを書く。
クラスモジュール FileSystemObject
'Declarations Section' 'Module Level Variables' Private fsObj As Object 'Constructor' Private Sub Class_Initialize() Set fsObj = CreateObject("Scripting.FileSystemObject") End Sub
これだけ。
これで、プロパティとかメソッドをこの変数fsObj
を経由して呼び出すようにすればいい。
プロパティとメソッドの実装(笑)
大袈裟な見出しだが、プロパティをメソッドを実装(笑)するときの教科書が、おれたちの「オブジェクト ブラウザー」様だ!
「ブラウザー」と延ばしているところがボスキャラ感があっていいよね。
[F2]キーを押すか何かして、「オブジェクト ブラウザー」を開き、FileSystemObject
を指定すると、
こんなふうにメンバを確認することができるし、
こんなふうに各メンバの実装方法を確認することもできる。
あとはコーディングあるのみ!
……である!
プロパティの実装(笑)
……といっても、FileSystemObject
にはプロパティは一つしかない。これは意外だった。なんと、Drives
コレクションを返すDrives
プロパティしかないのだ。
実装方法は、オブブラ(略すなw)によると、
Property Drives As Drives
とのこと。
もちろん、このまま打ち込んでもコンパイルエラーになるので、脳内でコードを補完して
Public Prooerty Get Drives() As Drives
とする。
もちろん、Microsoft Scripting Runtime
を参照設定しないのだから、As Drives
ではまずい。で、
Public Prooerty Get Drives() As Object
と、返り値をObject
型に改めておく。
あとは中身。
Dim ret As Object Set ret = fsObj.Drives '……(1)' Set Drives = ret '……(2)'
これでいい。変数fsObj
はモノホンのFileSystemObject
クラスのインスタンスを指しているから、そのDrives
プロパティの返り値はもちろんモノホンのDrives
コレクション。
だから、まずは(1)の
Set ret = fsObj.Drives
で返り値用の変数ret
にモノホンのDrives
コレクションを突っ込んでおき、(3)の
Set Drives = ret
でニセのDrives
プロパティの返り値としてやる。
プロシージャ全体は
Public Prooerty Get Drives() As Object Dim ret As Object Set ret = fsObj.Drives Set Drives = ret End Property
こう。
メソッドの実装(笑)
メソッドも基本的にはこの方法。
このように、オブブラ(笑)で、
Sub
/Function
の別- 引数リスト
- 引数が
Optional
かどうか - 返り値の型
を確認し、それに応じてコーディングすればいい。
たとえば先の画像のCreateTextFile
メソッドならば、
- 種別は
Function
- 引数は
FileName
、OverWrite
、Unicode
の三つ。 - 引数
OverWrite
・Unicode
はOptional
- 返り値は
TextStream
型
なので、それに応じてコーディングする。
Public Function CreateTextFile( _ ByVal FileName As String, _ Optional ByVal OverWrite As Boolean = True, _ Optional ByVal Unicode As Boolean = False) As TextStream
となる。
しかし、TextStream
クラスもScripting.FileSystemObject
クラスのメンバなので、Object
にする。
Public Function CreateTextFile( _ ByVal FileName As String, _ Optional ByVal OverWrite As Boolean = True, _ Optional ByVal Unicode As Boolean = False) As Object
こうなる。
プロシージャ全体は
Public Function CreateTextFile( _ ByVal FileName As String, _ Optional ByVal OverWrite As Boolean = True, _ Optional ByVal Unicode As Boolean = False) As Object Dim ret As Object Set ret = fsObj.CreateTextFile(FileName, OverWrite, Unicode) Set CreateTextFile = ret End Function
こう。
引数が列挙体型のやつがある
あと、メソッドの中には引数がScripting.FileSystemObject
の中で定義された列挙体であるものがある。
たとえば、
このGetStandardStream
メソッドの場合、
Function GetStandardStream(StandardStreamType As StandardStreamTypes, [Unicode As Boolean = False]) As TextStream
とあるように、第1引数StandardStreamType
がStandardStreamTypes
という見慣れない型である。
こいつは、オブブラ(笑)で見ると
となっているように、Scripting
クラスで定義された列挙体なんである。
当然、Microsoft Scripting Runtime
を参照設定していないと使えない。
そういうときはどうするか。
このニセFileSystemObject
クラスモジュール内でPublic Enum
にしてしまえばいいのである!
'Declarations Section' 'Constants' Public Enum StandardStreamTypes StdIn = 0 StdOut = 1 StdErr = 2 End Enum
列挙体のメンバがそれぞれどの数値を表しているのか、というのもオブブラ(笑)先輩を見ればわかる。
ほれ。こんなふうに。
Scripting.__MIDL___MIDL_itf_scrrun_0001_0001_0003
ちゅうのは何のことやらわからんがw
おわりに
上記のようにして、ひたすらプロパティ・メソッドを実装(笑)し続けることを、「ネオ写経」と呼んでおります。
オブジェクトの仕組みがよくわかって実に勉強になります。
「新型コロナ自粛で勉強ぐらいしかすることがない」という人は、一度やってみてはいかがでしょうか?
ちなみに、FileSystemObject
は、配下にDrives
、Drive
、Folders
、Folder
、Files
、File
、TextStream
というScripting
内のオブジェクトを抱えているので、本気でFileSystemObject
クラスを丸ごとラップしようと思ったら、全部で八つもクラスモジュールを作ることになりますw
こんなふうに。
特に、Folders
-Folder
のような階層構造を持つクラスを表現するのにめちゃくちゃ頭を使いましたw