おはようございます くろねこです
今回は、お仕事系のお話しです
くろねこは、自称SEです
バリバリ開発していた時代は、もうずいぶん昔のこと
性格的に同じことを二度することが嫌いなくろねこは
ちょっとした作業も効率化したいがために
スクリプトやマクロを組むこと、現在でもよくやってます
そんな中、起きてしまった出来事についてお話しします

焦るくろねこ
昨年秋より、関わっている案件がたまたまですが
くろねこが以前に作成したツールとほぼ同一の要件を満たしていることから
そのツール(Excel VBAで構築)を流用することで短い期間で一定の品質を実現することになりました
そのトライアル版のレビューを1月末に実施したのです
このレビューはおもに操作性を重視したもので、実際に動くものを見ながら説明し、その実感を味わってもらうものなのです
レビュー当日
1月某日 10:00AM
会議室に持参するノートPCにプログラム(Excelファイル)を設定し、動作させたところ、
「変数が定義されていません」というエラーが発生しました
レビューは、10:30からです
開発機では全く問題なく動作しています
(もちろん、VBAのオプション「変数の宣言を強制する」はチェック済み)

開発機 でもう一度、動作確認したExcelファイルをノートPCにコピーし直し、再度、動作させましたが、やはり「変数が定義されていません」 のエラーで全く動きません
時刻は、すでに10:15を過ぎています
幸い、説明用資料印刷は済ませておいたので、残された時間はエラー対策にすべて注げます
しかし、時間はあまりにも短すぎます

PCの設定の違いなど思い当たる部分は開発機と同じです
いよいよ時間が無くなり、
仕方なく説明用ノートPCから開発機をリモートデスクトップで接続し、説明することに!
レビューは何とか・・・
今回のレビューは操作性の根幹となる部分をどう実装するかのヒアリングがメインだったのです
くろねこが提案する2つのプランは予想通りのプランを採用することになり、レビューは無事目的を果たすことができたのです

しかし、くろねこは朝のモヤモヤが気になって、気になって仕方ありませんでした

結局、この日はこのトラブルの解決策を見つけることができず、失意のまま帰宅したのです

やっぱり気になる!
疲れていたのですが、ベッドに入っても眠れず、ゴソゴソと起きだし、マシンルームに・・・
問題のExcelファイルはクラウド上にコピーしてあったバックアップをダウンロードし、動作させるための環境を自宅PCでささっと作り動作させます
自宅PCでは、エラーも発生せずに問題なく動作しました
環境別の状態を整理すると以下のようになります


原因がつかめず、夜は深い時間帯に
何度も何度もコードを見直しますが、原因がわかりません(泣)
この日の最後として、類似案件が無いかを調べたところ、
「VBAエディタの自動整形」 というのが悪さをしている可能性に気が付きました
VBAエディタの自動整形とは
この「VBAエディタの自動整形」 とは何ぞや?ということで調べたところ
VBAエディタ(VBE)の自動整形は、コード入力後にカーソルを移動させるだけで、大文字・小文字の自動変換や適切なスペース挿入(ステートメントの整形)、全角半角の適正化を自動で行う機能です
これらは、コードの可読性を高め、入力ミスを防ぐため、インデント(自動インデント)と共に必須の機能として機能するものだそうです
う~ん 怪・し・い
特に「適切なスペース挿入(ステートメントの整形) 」ですよ!
インタプリタで動作するVBAは実行時に構文解析が行われ、その際にこの自動整形が機能してしまう そんな感じだったのでは?
今回、エラーとなったコードは
Set pvWB_Master = Workbooks.Open(pvServer_DestPath, ReadOnly:=True)
で、宣言されていない変数は ReadOnly です(ReadOnlyは変数ではありません)
VBAエディタの自動整形により、上記のコードは以下のように認識された可能性があると判断しました
Set pvWB_Master = Workbooks.Open(pvServer_DestPath, ReadOnly = True)
おそらく、間違いありません
エラー対策
WorkBooks.Openメソッドの引数の書き方が「右辺でもって左辺を定義する」(右辺値参照)書き方になっています
このメソッド、ReadOnly引数は3番目の引数で通常であれば
Open(ファイルのパス,,{ReadOnlyならTrue },・・・)
と書くはずです(引数2は省略値)
このような書き方をくろねこは「位置パラメタ」と呼んでいます(書く位置が引数の意味をもつ)
ところが、引数が多いメソッドとなると省略値が多い場合、カンマだらけになり記述ミスを起こしやすいのです
そこで、「右辺でもって左辺を定義する」 というのがいつの頃からか実装されました
これは、左辺が表す引数に右辺の値を渡すもので
今回のケースで、ReadOnly:=True は、ReadOnlyという引数にTrueを渡すという書き方なんです
このような書き方をくろねこは「キーワードパラメタ」と呼んでいます
「位置パラメタ」と「キーワードパラメタ」というのは
くろねこが若き頃に開発で使用したKEQPARSEでの呼び方です(わかる人いるかな???)
ということで、位置パラメタ方式の書き方に該当部分を改めます
【変更前】キーワードパラメタとして記述
Set pvWB_Master = Workbooks.Open(pvServer_DestPath, ReadOnly:=True)
【変更後】位置パラメタとして記述
Set pvWB_Master = Workbooks.Open(pvServer_DestPath, , True)
もちろん、自宅PCでの動作は万全です!
気が付くと始発が動き出す時刻になってました(やばい!)
翌朝、早い電車で出社、対処済みプログラム(Excelファイル)開発機、ノートPCのそれぞれで動作確認しました!
おわりに
レビュー直前のエラー、さすがに焦りました💦
なんか怖いですね・・・
勝手に解釈されて、コードが成形しなおされてしまうことがあるのですね
「VBAエディタの自動整形」恐るべしです
やっぱり、
省略形の多用や、「右辺でもって左辺を定義する」 (キーワードパラメタ方式)は意図しない動作をしてしまう問題を含んでいるものと感じました
楽しようしてはいけないですね!
ただ、会社のノートPCと開発機の「差」は時間のある時に調査してみようと思います
ほぼ、徹夜になってしまったあの日、よりによって、会議の多い日
波打つように襲い掛かる睡魔に
ホントやばかったです

意識なくなったら
くろねこの身体のことを知る同僚は救急車呼んでしまったかも知れません(笑)
久しぶりにこんなに真剣にコード見ました💦
それでは
