炎上wしたコメント欄への対応

炎上wしたコメント欄への対応

f:id:akashi_keirin:20190511075833p:plain
※この画像はフランスジョークですw

大量のExcelブックと戦う業務があって、そのときに必要なシートの名前を勝手に変える人がちょこちょこいたせいで難儀したので、間に合わせでシート名が改変されたブックを検知するメソッドを作った。

そのことを、ほんの軽~い気持ちで

akashi-keirin.hatenablog.com

コチラに書いたところ、なんとコメント欄が炎上wしてしまった。

軽はずみに物議を醸すような記事を書いてしまって申しわけないw

軽く言いわけ

まず、前回記事は、出勤前に慌てて書いたこともあって、状況の説明が不足していた。あと、誤字もあった。

補足しておく。

置かれていた状況

そもそも、次のような状況だった。

  • 様式ブックは当方で作成したものを配布。
  • いちおう、シートの保護はかけていた。
  • 集めたブックの特定のシートについて、印刷範囲と改ページ位置を調整した上でプリントアウトしたい。
  • プリントアウト対象のシート名は結構ややこしい名前にしているので、「わざわざここを変えるやつはおらんやろ」と思い、ブックの保護まではしていなかった。

およそ、このような状況だった。

必要な処理は、

  • フォルダ内の処理対象ブックを開く。
  • 印刷対象のシートを確定する(シートへの記入状況により、印刷すべきシートの数が変わる)。
  • 印刷対象シートについて、印刷範囲と改ページ位置を調整する(記入内容によっては行が追加されることがあるので、改ページ位置を調整することによって倍率を変更する)
  • 印刷対象シートを順にプリントアウトする
  • ブックを閉じてフォルダ移動する

こんな感じ。

炎上wしたコメント欄への回答

コメント欄に長文は書きにくいので、こちらで回答します。

空腹おやじ (id:Z1000S)さん

難しく考えすぎているような気がするんですが?

いや、むしろ、すごーく安易に考えた結果です。

プリントアウト用マクロ自体、間に合わせでちゃちゃっと書いたようなシロモノで、エラー対応なんて全然していなかったため、シート名が変えられていたときに「インデックスが~」エラーが出るわけです。

そこでまあ、これでいこか、とw

単純にマッチングを見るだけなら、targetBook.WorksheetsとshNamesArrayの2重ループで比較すれば良い

「2重ループ」で総当たりするほどのものでもないと思ったんですよね……。

単一ループで
If targetBook.Worksheets(i).Name <> shNamesArray(i - 1) Then
でチェックすれば、シートの並びの変更もハジケます。

シート名で対象シートを指定する方式にしていたので、この方法は全く考慮に入れませんでした。

リスト1のコードは、ワークシートが追加されていた場合をハジケません

やりたい処理が、上記のとおり〈指定したシートを印刷する〉というものだったので、変なシートが追加されていたとしても問題なし(対象シートの名前が変えられて、新規追加シートに対象シートの名前を付けられたら「ち~んw」でしょうけどw)だと思いました。

jinoji さん

dictionary型に入れておいて、Existsで確認する

すでにFileSystemObjectを使うために参照設定しているので、それもありかも、ですね。Dictionaryをセットするのがちょいめんどくさい? 一緒かw

シート名でなくてシートのクラス名?codename?を分かりやすく変更しておいて、それを使う

CodeNameというものを全く知りませんでした。今度試してみます。ありがとうございました。

id:imihito さん

「シートの存在判定」という観点では、現在の方法、「実際に試してエラーの有無で判定」がベスト

上記のとおり、単純に〈その名前のシートが存在するか〉を判定したかっただけなので、id:imihito さんにそのように言ってもらえると、非常に心強く思います。

Excel側のシート名同一判定と、VBAの文字列比較が同じ結果となる保証が無い

この発想はまるでありませんでした。

ただし、これについては、jinoji さんのコメントに

特に困らない気がするし、そんなことをする利用者は滅多にいない気もする。

とあるように、それほど気にすることでもなかったのかも知れませんね。

それにしても、空腹おやじ (id:Z1000S) さんの実験結果、

aというワークシートがある時に、

? ThisWorkbook.Worksheets("A").Name="A"
False
? ThisWorkbook.Worksheets("A").Name="a"
True

? ThisWorkbook.Worksheets("a").Name="A"
False
? ThisWorkbook.Worksheets("a").Name="a"
True

となりました。

は、非常にキモチワルイ挙動ですね……。

ExcelVBAer (id:x1xy2xyz3)さん

自分なら CodeName で判定しますかね。

シート名が変更される可能性が高い事が分かってるというのであれば、CodeName の方が無難な気がします。

同一ブック内で閉じた処理なら、シートの指定は全てオブジェクト名でやるようになっていましたが、ブックをまたがる処理のときには従来どおりインデックス名でアクセスしていました。今回、皆様のおかげでCodeNameというものを知りましたので、積極的に使っていこうと思いました。

おわりに

みなさん、ありがとうございました!!!!!!!!

もっと燃やせ!