インターフェース周りのち~んw現象

インターフェース周りのち~んw珍現象

前回

akashi-keirin.hatenablog.com

のやり方は、別プロジェクト間でインターフェースを共有しようとしたのがそもそも間違いだったのかも知れん、と思い直して、やり方を変えてみた。

thom.hateblo.jp

コチラを参考に、インターフェースを含んだブックをアドインにして、参照設定で共有するやり方に改める。

準備1 アドインにする

インターフェースIChokiShowable(インターフェース名らしく、先頭に「I」を付けました。すんません。)を搭載したブックを作り、ChokiShowableAddin.xlamという名前で保存しておく。

f:id:akashi_keirin:20190224120206j:plain

このように、「名前を付けて保存」の「ファイルの種類」欄で「Excelアドイン(*.xlam)」を選んだら、勝手に保存先のフォルダが指定されるので、ファイル名だけ指定したらヨロシ。

次に、テキトーにExcelブックを開いて、「ファイル」→「オプション」→「アドイン」の順にたどっていく。

すると、一番下に、「管理」というやつがあるので、

f:id:akashi_keirin:20190224120210j:plain

ドロップダウンリストを「Excel アドイン」にして[設定]ボタンをクリック。すると、

f:id:akashi_keirin:20190224120213j:plain

こんなやつが出てくるので、「Chokishowableaddin」を選んで[OK]をクリックする。

プロジェクト エクスプローラーは、

f:id:akashi_keirin:20190224120218j:plain

こんな状態。

準備2 参照設定する

次に、参照設定をする。

プロジェクト エクスプローラー上で、「VBAProject(ChokiShowableAddin.xlam)」のところをクリックして、プロパティ ウインドウの「オブジェクト名」のところを「ChokiShowable」にする。(別に何でもいいけど。)すると、プロジェクト エクスプローラーが、

f:id:akashi_keirin:20190224120223j:plain

こんなふうになる。

この状態にしておいて、VBEで「ツール」→「参照設定」へと進む。すると、

f:id:akashi_keirin:20190224120227j:plain

リストに「ChokiShowable」があるので、チェックして[OK]をクリック。

準備3 インターフェース実装ブックの準備

これまで同様、「ち~んw1号.xlsm」を使う。「ち~んw1号.xlsm」のThisWorkbookモジュールに次のコードを書く。

リスト1 ち~んw1号.xlsmのThisWorkbookモジュール
Option Explicit

Implements IChokiShowable

Public Sub IChokiShowable_showChoki()
  Debug.Print "ち~んw1号は チョキを 出した!"
End Sub

これだけ。

準備4 インターフェース型オブジェクトを返すメソッド

次に、IChokiShowable型のオブジェクトを返すメソッドを作る。

アドインファイル「ChokiShowableAddin.xlam」の標準モジュールに次のコードを書く。

スト2 ChokiShowableAddin.xlamの標準モジュール
Option Explicit

Public Function getChokiShowableObject( _
            ByVal targetBook As Workbook) As IChokiShowable
  Dim ret As IChokiShowable
  Set ret = targetBook
  Set getChokiShowableObject = ret
End Function

Workbook型オブジェクトを受け取って、IChokiShowable型にして返す、というメソッド。

これで、準備はおしまい。

あとは、これまで同様「ち~んw2号.xlsm」から呼び出すことを試みる。

ち~んw2号.xlsmから呼び出す

次のコードで呼び出しを試みる。

リスト3 ち~んw2号.xlsmの標準モジュール
Public Sub testThisWorkbookInterface()
  Dim anotherBook As Workbook
  Set anotherBook = _
        Workbooks.Open(ThisWorkbook.Path & "\ち~んw1号.xlsm")
  Dim kaniBase As IChokiShowable
  Set kaniBase = getChokiShowableObject(anotherBook)  '……(1)'
  Call kaniBase.showChoki
  Set kaniBase = Nothing  '……(2)'
  Call anotherBook.Close(SaveChanges:=False)  '……(3)'
  Set anotherBook = Nothing
End Sub

変えたのは(1)のところ。

アドインのgetChokiShowableObjectを用いて、変数kaniBaseWorkbookオブジェクトをIChokiShowable型オブジェクトとしてぶち込んでいる。

実行結果

リスト3を実行すると、

f:id:akashi_keirin:20190224120231j:plain

ぐえっ! エラー!

デバッグ]をクリックすると、

f:id:akashi_keirin:20190224120236j:plain

ぬな?! またお前か!

しかしながら、ここで特に何もせずにコードの実行を継続すると、

f:id:akashi_keirin:20190224120241j:plain

無事に意図どおりの結果が得られた。

よかったなあ、カニベースくん!!!!!!!! ぼくはもう胸がいっぱいだよ。

おわりに

しっかし、なんで一旦エラーが出るのかわからんわい。

ちなみに、リスト3の(2)、

Set kaniBase = Nothing

を実行せずに、(3)の

Call anotherBook.Close(SaveChanges:=False)

を実行すると、Excelが派手にバグりますw

興味のある方はどうぞ。

追記

もしかして、「ち~んw1号.xlsm」を開いてanotherBookにぶち込んだ段階では、ThisWorkbookモジュールの

Implements IChokiShowable

(正確にはThisWorkbookモジュールのコード自体)が読み込まれていないのではないか、と思い、リスト3を次のようにしてみた。

リスト3改 ち~んw2号.xlsmの標準モジュール
Public Sub testThisWorkbookInterface()
  Dim anotherBook As Workbook
  Set anotherBook = _
        Workbooks.Open(ThisWorkbook.Path & "\ち~んw1号.xlsm")
  Call anotherBook.callHelloWorld  '……(*)'
  Dim kaniBase As IChokiShowable
  Set kaniBase = getChokiShowableObject(anotherBook)  '……(4)'
  Call kaniBase.showChoki
  Set kaniBase = Nothing
  Call anotherBook.Close(SaveChanges:=False)
  Set anotherBook = Nothing
End Sub

(*)のところに1行追加。インターフェースとは関係のない「ち~んw1号.xlsm」のThisWorkbookモジュールのメソッドを呼び出してみる。これで、確実に(4)の

Set kaniBase = getChokiShowableObject(anotherBook)

実行前に「ち~んw1号.xlsm」のThisWorkbookモジュールを読み込んでくれるはずだ。

実行してみると、

f:id:akashi_keirin:20190224125353j:plain

今度はエラーが出ずに一発で完走した。

うーーーん……。何だかなーーー。