ブックを閉じて別フォルダに移動する(Excel)

f:id:akashi_keirin:20180610191139p:plain

Excelブックを移動する

この時期、あちこちから集めたデータ(笑)を集約するという作業が頻発する。

この手の業務は、VBAを使って瞬殺する私にとっては痛くも痒くもない。しかしながら、職場全体で見ると、この手のアホみたいな作業に膨大な時間を費やすというのが多数派。

別に人助けというわけではないけれど、最近は進んで他人のためにコードを書いている。本業の大半がクソつまらないものなので、却ってストレス解消にもなるし。

ブックを閉じて別のフォルダへ移す

近況報告はこのぐらいにして本題。

あちこちから集めたデータ(笑)を集約する、という作業に必ずつきまとうのが、

ブックを閉じる→別のフォルダに移動する

という操作。

集まってくるExcelブックが、ろくに下処理をしていない(データの入力規則を当てたり、ブックやシートの保護をかけたり、といった処理をろくにしていない)ものなので、フルオートにするよりも、

一つ一つのブックを開いて確認するところまでは手動、集約用シートへの転記以降は自動

にする方が安全なんである。

よって、「ブックを閉じる→別のフォルダへ移動する」という操作はやたら出てくるのであった。

別にその都度書いてもそれほどメンドウでもないんだけれど、メソッド化してみたというわけ。

ブックを閉じて別フォルダに移動するメソッド

リスト1 標準モジュール
Public Function moveBook(ByVal targetBook As Workbook, _
                         ByVal oldFullPath As String, _
                         ByVal newFullPath As String, _
                Optional ByVal canSaveChanges As Boolean = False) As Boolean '……(1)'
On Error GoTo errorHandler
  Application.DisplayAlerts = False    '……(2)'
  Call targetBook.Close(SaveChanges:=canSaveChanges)    '……(3)'
  Name oldFullPath As newFullPath    '……(4)'
  moveBook = True    '……(5)'
errorHandler:    '……(6)'
  Application.DisplayAlerts = True
  If Not moveBook Then moveBook = False
End Function

まず(1)の

Public Function moveBook(ByVal targetBook As Workbook, _
                         ByVal oldFullPath As String, _
                         ByVal newFullPath As String, _
                Optional ByVal canSaveChanges As Boolean = False) As Boolean

で引数と返り値を設定。

第1引数targetBookは、処理対象のWorkbookオブジェクト。

第2引数oldFullPathは、処理対象ブックの移動前のフルパス。

第3引数newFullPathは、処理対象ブックの移動後のフルパス。

第4引数canSaveChangesは、処理対象ブックを閉じるときに保存するかどうか。通常、転記処理後に上書き保存などする必要はないと思うので、省略可にして既定値をFalseにしてある。

返り値はBoolean型。無事ブックの移動が出来たらTrue、失敗したらFalseを返す。

コード自体はアホみたいに簡単なので、特に説明の必要はないと思うが、一応簡単に。

(2)の

  Application.DisplayAlerts = False

で、一旦警告表示を止める。通常、転記処理では処理対象ブックに変更を加えることなどないと思うが、今回手伝った事案で処理対象ブックに加工しないと集約できない、というケースがあったのでw

次に(3)の

Call targetBook.Close(SaveChanges:=canSaveChanges)

で処理対象ブックを閉じる。

targetBook.Close SaveChanges:=canSaveChanges

でも良いと思うが、引数がハダカになるのはやっぱりキモチワルイので……。

「ママー、裸じゃイヤ!」みたいな感じです。

(4)の

Name oldFullPath As newFullPath

はおなじみNameステートメント

「旧フルパス」と「新フルパス」の順序がよくごっちゃになる(いや、「As」の意味を考えたら割とすぐに分かるんですけどね!)ので、メソッドの中に閉じ込めてしまったわけですよ。

そもそも、なんで「As」なんているんでしょうねえ? 「Name 目的語 補語」で「○○を××と名づける」なんだから、別にName [OldFullName], [NewFullName]でいいと思うんですけど。

(4)が無事実行できたら(エラーにならなければ)、無事フォルダ移動が終わったということなので、(5)の

moveBook = True

で返り値をTrueにする。

普通だったら、ここで即returnすりゃいいってもんだが、

Application.DisplayAlerts = True

を2回も書きたくないので、エラーキャッチ用のブロックである(6)からの3行を

errorHandler:
  Application.DisplayAlerts = True
  If Not moveBook Then moveBook = False

こんなふうにした。

途中でエラーが出た場合も、エラーが出なかった場合も、このブロック内を実行するようにした。

かといって、すでにブックの移動が無事に終わった場合にFalseを返されてはたまらないので、

If Not moveBook Then moveBook = False

この時点で返り値がTrueでない場合にのみFalseを返すようにした。

おわりに

まあ、メリットといえば、NameステートメントApplication.DisplayAlertsまわりをラップしてメインのコードから隔離できることぐらいですけど。