省力化でコメントは重要

Excelのマクロなどにはあまり興味はないが、今まで溜まりにたまったものが大量にある。これを少し整理でもするかと思い立つことがある。昔作ったものがそのままで動作するものが大半である。しかし、中には「これはどうして使うものだったか」と思い出すのにも時間がかかるものがある。その内容はすっかり忘れているということである(笑)。

そういうものに限って、今実行してみると正常に動作しない。最悪の場合はExcelがフリーズする。この例が、昨日でくわした「同一内容の行を削除する」というマクロである。このマクロを使ったExcelのファイル自体はもう存在していない。マクロだけがテキストとして残っているだけである。これは自分の必要があって作ったものではない。今から15年以上も前に、ある商売をしている人から頼まれて作ったものである(だからなおさら忘れている)。

あの時は、最下行に次のような数個のデータを入力したときに、これと同じものがシート内の今まで入力した部分にあると困るから、同じデータの古いものを削除するようなものを作ってくれと言われた(と思う)。

商品名 商品CD 等級 数量 価格 仕入先 ようかん 67308 上 12 1500 玉屋

確かに、あの当時は正常に(想定したような)動作はしていた。あれから15年以上もたつ。こんなシートやデータは個人的にはまったく無縁のものだから今はない。マクロだけは後日の検討用の素材として残しておいたものである。

そこには「上の行から順次1行ずつ入力していって、最下行のデータ(今入力した行)と同一のデータがある行を上の行の中から検索して、その行を全部削除する。同一のデータがない場合は何もしない」というコメントがあるだけである。

当時の状況を再現するために似たような架空のデータを作って、このマクロをそのまま実行してみた。最初はこの通りになった。しかし、このマクロは長すぎるので、不要だと思われる部分は適当にカットして半分ぐらいの長さにした(これが問題だった)。そして再度実行するとExcelがフリーズ状態になった。ループを使うマクロでは頻出するパターンである。何らかのミスで無限ループに陥っているのである。

[Ctrl]+[Alt]+[Delete]でタスクマネージャーを起動してExcelを強制終了させる。再起動して、今度はとりあえず無限ループに陥りそうな部分を有限回数のループに変更して実行してみる。しかし、今度もまたフリーズする。となると、まだどこかに「隠れ無限ループ」があるようである。しかし、これがなかなか発見しにくい。文字通り「隠れ」ているのである。

あちこちさわりまわって、無限ループになりそうな感じのする部分には脱出部分を作って、3度目の実行である。そのせいか、今回は無限ループに陥ることはなかった。その「隠れ無限ループ」は次の部分あった。

プログラミング Do Set c = rng.FindNext(After:=ActiveCell) '省略 Loop While Not c Is Nothing

このままでは「While Not c Is Nothing」という条件が満たされることはない。したがって、無限にこの範囲をくり返すことになってしまったというわけである。15年後の今、ソースだけを見て、これで無限ループになることはないだろう、と思い込んだことが今回の間違いの原因だった。

しかし、この部分は15年前もこれと同じく記述していたはずである。そこで、その昔のソースの原文を見てみる。Do~Loopの中に次のような脱出する部分を入れていたことがわかる。

プログラミング If rwf = rwn Then Exit Do End If

これが今回は「While Not c Is Nothing」で無限ループは回避できると思い込んで、「If rwf = rwn Then」の部分を削除した。それが原因だった。当時でも「While Not c Is Nothing」が頼りにならないことは気が付いていたのかもしれない。結果的にはこの部分は無意味な記述だった。念のために書いておいたという可能性が高い。

しかし、こういう点の注意はコメントとして何も書いていない。これが無駄な時間を食ってしまった原因である。また何かあったときのために、この点は詳しくまとめておこう。

重要
コメントは詳しく書く。これが省力化の第一歩。

- 2018/02/08 -







Find/FindNextとActiveCell(exc_0121)
このツールを使うことはないが各種の動作のいい検討材料にはなる。