【Excel VBA入門 第20回】ブックを開く・保存する・閉じる!Workbooksの基本操作

スポンサーリンク
Excel VBA

イントロダクション

前回(第19回)で、エラー処理編が完結した。今回からは新しいシリーズとして、3回にわたって「ブック・ファイル操作編」を取り上げよう。

  • 第20回(今回):ブックを開く・保存する・閉じる
  • 第21回:フォルダ内のファイルを一覧にする(Dir 関数、FileDialog)
  • 第22回:複数のブックを1つに集計する(実践)

これまでの回でも、第17回や第19回の例で Workbooks.Open を使ってきた。
ただし、そこではエラー処理を説明するための「例」として使ったものである。
今回は、その Workbooks.Open を中心に、ブックを扱う基本の操作を整理していこう。

「ブック」と「ファイル」の違い

本題に入る前に、先ずは「ブック」と「ファイル」という用語を整理しておこう。
どちらもExcelの .xlsx や .xlsm を指しているように見えるが、実は見ている状態が違う。

  • ファイル:パソコンのフォルダに保存されている状態。
    エクスプローラーに表示される C:\test\売上.xlsx がこれにあたる。
  • ブック:Excelで開いている状態。VBAで操作する対象であり、Workbook オブジェクトとして扱う。開いているブックの集まりが、Workbooks コレクションである。

つまり、ファイルをExcelで開くと、ブックとして操作できるようになる。逆に、ブックを保存すると、その内容がファイルに書き込まれる。第2回で学んだ Workbooks("Book1.xlsx") は、「開いているブック」を名前で指定する書き方であった。

ファイルブック
状態フォルダに保存されているExcelで開いている
VBAでの表し方パス(文字列):"C:\test\売上.xlsx"Workbook オブジェクト:wb、ThisWorkbook など
主な操作場所や名前を指定する、存在を確認する保存する、閉じる、シートやセルを操作する

この違いは、以下の操作にそのまま当てはまる。

  • ファイルをブックとして開く:Workbooks.Open
  • ブックを保存する・閉じる:Save、SaveAs、Close
  • フォルダ内のファイルを探す:Dir(第21回)

本記事では、原則として、保存されている状態を「ファイル」、開いて操作する対象を「ブック」と呼び分けることにする。

準備:サンプルファイルを用意する

今回は、次のサンプルファイルを用意しよう。

  • C:\test フォルダを作成する。
  • Excelで新しいブックを作り、A1セルに「売上一覧」と入力して、C:\test\売上.xlsx として保存する。(読み込み用のデータファイル)

本記事では、マクロを書くブックのファイルは、このデータファイルとは別のファイル(マクロ有効ブック .xlsm)を想定している。
ただし、第12回で作成し、これまでの回で使ってきたマクロ有効ブックをそのまま使ってもよい。
その際は既存の Module1 に追記しよう。
なお、新規作成の場合、コードは、VBEの[挿入]→[標準モジュール]で追加した Module1(標準モジュール)に書いていこう。
また、同じ名前のSubやFunctionは、重複して作ることができない。第17回にも「 ブックを開く」 というSubがあったため、追記する場合もあることから、今回は名前を変えている。

【注意】マクロ有効ブックを開き直したとき

マクロ有効ブックを保存して開き直すと、画面の上部に「マクロが無効にされました」という警告が表示されることがある。これはExcelのセキュリティ機能による通常の動作で、コードが壊れたわけではない。

  • 黄色いバーに「セキュリティの警告」と表示された場合:バーの[コンテンツの有効化]をクリックすると、マクロが使えるようになる。
  • 赤いバーに「セキュリティ リスク」と表示された場合:インターネットからダウンロードしたファイルなどで表示される。ブックを閉じ、エクスプローラーでファイルを右クリックして[プロパティ]を開き、[全般]タブの下のほうにある「許可する」にチェックを入れて[OK]を押してから、開き直す。

また、.xlsx で保存すると、マクロは保存されない。マクロを書いたブックは、必ず .xlsm で保存しよう。

ブックを開く

ブックを開くには、Workbooks コレクションの Open メソッドを使う。

Openメソッド
Workbooks.Open(FileName, ... , ReadOnly, ... )

最初の引数 FileName には、開くブックのフルパス(保存場所を含むファイル名)を指定する。
引数名を付けて指定する「名前付き引数」は、第6回で学んだとおりである。

Sub ブックを開いてみる()
    Dim wb As Workbook

    Set wb = Workbooks.Open(FileName:="C:\test\売上.xlsx", ReadOnly:=True)
    MsgBox wb.Name & " を開きました。"

    wb.Close SaveChanges:=False
End Sub

Workbooks.Open は、開いたブックを戻り値として返す。Set wb = ... で変数に受け取っておけば、以降は wb という名前でそのブックを操作できる。戻り値を受け取るときに引数を ( ) で囲むのは、第7回で学んだ書き方である。

主な引数は次のとおりである。

引数名説明
FileName開くブックのフルパス(必須)
ReadOnlyTrue を指定すると、読み取り専用で開く
Passwordパスワード付きブックを開くときの、パスワードを指定する

集計のために中身を読むだけのブックは、ReadOnly:=True で開いておくと、誤って書き換えてしまう心配がない。

ThisWorkbookとActiveWorkbookの違い

今回、マクロ有効ブック .xlsmでマクロを実行して、 売上.xlsx を開くと、マクロ有効ブック(マクロ有効ブック .xlsm)と 売上.xlsx の2つのブックが同時に開いている状態になる。
このとき、「どのブックを操作しているのか」を取り違えないことが大切である。
そこで、2つの似た名前を整理しておこう。

  • ThisWorkbook:マクロが書かれているブック(マクロ有効ブック .xlsm)
    どのブックがアクティブになっても変わらない。
  • ActiveWorkbook:現在アクティブ(操作対象)になっているブック。
    ブックを開いたり切り替えたりすると変わる。
Sub ブック名を確認()
    Dim wb As Workbook

    Set wb = Workbooks.Open("C:\test\売上.xlsx")

    Debug.Print "ThisWorkbook:" & ThisWorkbook.Name
    Debug.Print "ActiveWorkbook:" & ActiveWorkbook.Name

    wb.Close SaveChanges:=False
End Sub

実行して、VBEの「イミディエイトウィンドウ」(Ctrl + G)を見てみよう。
ThisWorkbook にはマクロ有効のブック名が、ActiveWorkbook には開いたばかりの 売上.xlsx が表示されるはずである。

ActiveWorkbook は、処理の途中で変わってしまうことがある。
そのため、開いたブックは変数(今回の wb)に入れて操作し、マクロ自身のブックは ThisWorkbook で指定するという使い分けが、取り違えを防ぐコツである。

ブックを保存する

保存には、次の2つのメソッドがある。

  • Save:今の名前のまま、上書き保存する
  • SaveAs:名前を付けて保存する
Sub 名前を付けて保存する()
    Dim wb As Workbook

    Set wb = Workbooks.Open("C:\test\売上.xlsx")

    ' 別名で保存する(元の売上.xlsxはそのまま残る)
    wb.SaveAs Filename:="C:\test\売上_コピー.xlsx"

    wb.Worksheets(1).Range("A1").Value = "コピーを更新しました"

    ' 上書き保存する(今の名前は「売上_コピー.xlsx」)
    wb.Save

    wb.Close
End Sub

ポイントは、SaveAs を実行した時点で、wb が新しい名前のブックに変わることである。
そのため、その後の Save は 売上_コピー.xlsx への上書き保存になり、元の 売上.xlsx は書き換わらない。

注意点が2つある。

  • 同じ名前のファイルがすでにあると、SaveAs の際に「上書きしますか?」という確認メッセージが表示される。このサンプルを2回目に実行する前に、売上_コピー.xlsx を削除しておこう(このメッセージの扱いは、第22回で取り上げる予定)
  • .xlsx 以外の形式で保存する場合は、FileFormat 引数で形式を指定する。
    たとえばマクロ有効ブック(.xlsm)なら xlOpenXMLWorkbookMacroEnabled を指定する

ブックを閉じる

閉じるには、Close メソッドを使う。引数 SaveChanges で、閉じるときの保存の扱いを指定できる。

指定動作
SaveChanges:=True保存してから閉じる
SaveChanges:=False保存せずに閉じる
省略変更があれば、保存するかどうかを確認するメッセージが表示される

マクロで自動処理をするときは、確認メッセージで止まってしまわないよう、True か False を明示しておくのが基本である。

また、開いたブックは、使い終わったら必ず閉じよう。開きっぱなしにしておくと、メモリを使い続けるうえ、ファイルがロックされて、他の人が編集できなくなることもある。

新しいブックを作る

新規ブックの作成には、Workbooks.Add を使う。Open と同じく、作成したブックが戻り値として返ってくる。第5回で学んだ Worksheets.Add と同じ考え方である。

Sub 新しいブックを作る()
    Dim wb As Workbook

    Set wb = Workbooks.Add
    wb.Worksheets(1).Range("A1").Value = "売上一覧(新規)"

    wb.SaveAs Filename:="C:\test\新規ブック.xlsx"
    wb.Close
End Sub

作成直後のブックは、まだ名前がない。そのため、SaveAs で名前を付けて保存する。
ここでも、同じ名前のファイルがあると上書き確認が出るので、2回目に実行する前に 新規ブック.xlsx を削除しておこう。

実践!エラー処理と組み合わせて安全に開く

ここまでの内容を、これまでの学びと組み合わせてみよう。「ブックを開く」処理を、第12回で学んだ Function にまとめる。第17回の On Error Resume Next と、第19回の Dir による事前チェックを組み合わせて、開けなければ Nothing を返すFunctionにしてみる。

Function ブックを安全に開く(パス As String) As Workbook
    ' ファイルが存在しなければ、Nothingを返して終わる
    If Dir(パス) = "" Then
        Set ブックを安全に開く = Nothing
        Exit Function
    End If

    ' 存在しても開けない場合(破損など)は、Nothingのままにする
    On Error Resume Next
    Set ブックを安全に開く = Workbooks.Open(FileName:=パス, ReadOnly:=True)
    On Error GoTo 0
End Function

呼び出す側は、戻り値が Nothing かどうかで、成功か失敗かを判断する。

Sub 売上を確認する()
    Dim wb As Workbook

    Set wb = ブックを安全に開く("C:\test\売上.xlsx")
    If wb Is Nothing Then
        MsgBox "ブックを開けませんでした。", vbExclamation
        Exit Sub
    End If

    MsgBox "A1セルの内容:" & wb.Worksheets(1).Range("A1").Value

    wb.Close SaveChanges:=False
End Sub

ファイル名を存在しないものに変えて、メッセージが表示されることも試してみよう。

この例では、失敗を「Nothing を返す」ことで伝えている。
第18回で学んだ Err.Raise で、原因を呼び出し元に伝える設計も考えられる。
どちらがよいかは、「失敗したときに、呼び出し元が原因を知る必要があるか」で選ぶとよいだろう。

まとめ

今回は、ブックを扱う基本の操作を学んだ。

  • ブックを開くには Workbooks.Open を使い、戻り値を変数に受け取って操作する
  • ThisWorkbook はマクロのブック、ActiveWorkbook は今アクティブなブックである
  • 開いたブックは変数に入れて操作すると、取り違えを防げる
  • 保存は Save(上書き)と SaveAs(名前を付けて保存)を使い分ける
  • 閉じるときは SaveChanges を明示し、使い終わったブックは必ず閉じる
  • 新規ブックは Workbooks.Add で作成する
  • エラー処理や事前チェックと組み合わせれば、開けない場合にも対応できる

次回(第21回)は、フォルダの中にあるファイルを一覧にする方法を解説する。Dir 関数を使ったループや、ダイアログでフォルダを選ぶ FileDialog を使って、「フォルダ内のブックをすべて処理する」ための準備を整えていこう。

コメント

タイトルとURLをコピーしました