マクロでほかのファイルを開いてうんちゃらかんちゃらする、というのはよくありますよね。
パスワード付きファイルを開く、というのはよくやってたのですが「そういえば、書き込みパスワードがついてるときはどうやって開くんだろう」と思って調べたところWriteResPasswordという引数があることを初めて知りました。
で、この機会によく迷子になるのでWorkbooks.Open関連のところをまとめておくことにしました。
1.エクセルファイルを開く
基本です。
エクセルファイルを開くには
WorkBooks.Open 開きたいファイルのパス
と書きます。
たとえば、Cドライブのテストフォルダの「test」ファイルを開くには
WorkBooks.Open “C:\テストフォルダ\test.xlsx”
と書きます。
マクロ実行ファイルと同じフォルダにあるtestファイルを開くにはThisWorkBook.Pathが使えます。ThisWorkBook.Pathとエクセルファイル名をつなぐ「¥」を忘れずに!
WorkBooks.Open ThisWorkbook.Path & “\test.xlsx”
拡張子はなくても開くことは開きますが、ちゃんとつけた方がいいでしょう。
田中先生の記事によると、今開いているエクセルブックたちがWorkBooksコレクションであり、WorkBooksコレクションのメソッドOpenでエクセルファイルを開き、WorkBooksコレクションに新たに加える、ということのようです。
だから?という感じですが、実はこれを理解しているとあとあと色々「あ、だからか」とわかることがあります。
Excelでは、同時に複数のブックを開くことができます。開いているそれぞれのブックはWorkbookオブジェクトとして操作できます。このWorkbookオブジェクトの集合体がWorkbooksコレクションです。新しいブックを開くということは、この集合体に、新しいメンバーを加えるということです。だからWorkbooksコレクションのOpenメソッドです。
http://officetanaka.net/excel/vba/file/file01.htm
もっとも簡単なコードです。マクロ実行ファイルと同じフォルダのtestエクセルファイルを開きます。
Sub test()
'エクセルファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
Workbooks.Open trgPath
End Sub
WorkBooks.Openには以下の引数があります。
引数 | 省略 | 定数 | 説明 |
Filename | 不可 | – | 開きたいファイルパス |
Password | 可 | – | ファイルパスワード(読み取り)を指定 |
WriteResPassword | 可 | – | ファイルパスワード(書き込み)を指定 |
ReadOnly | 可 | True/False | True:読み取り専用で開く False:読み取り専用で開かない(普通に開く) |
引数を指定して書くと、より丁寧な感じがします。
WorkBooks.Opne 引数名1:=引数, 引数名2:=引数
という感じで書きます
Sub test()
'エクセルファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
Workbooks.Open Filename:=trgPath
End Sub
WorkBookオブジェクトを用意しておいて、開いたファイルをWorkBookオブジェクトにセットすることもできます。このあと、開いたブックにあれやこれやする場合にはセットしておいた方が便利ですよね。
Set wbobject = WorkBook.Open(Filename:=trgPath, ReadOnly:=True)
等と書きます。イコールの右側にくる場合は、引数を()でくくらないとエラーになります。
Sub test()
'エクセルファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
Dim wb As Workbook
Set wb = Workbooks.Open(trgPath)
End Sub
WorkBooks.openでファイルを開くと、開いたファイルがアクティブになるので、アクティブファイルをどうこうする、という書き方もできます。
Sub test()
'エクセルファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
Workbooks.Open trgPath
'開いたエクセルファイル=アクティブブックとなる
With ActiveWorkbook
.Worksheets(1).Range("A1").Value = 1
.Close True
End With
End Sub
エクセルブックの種類には、以下の3種類の拡張子があります。
最近のエクセル→ .xlsx
古いエクセル→ .xls
マクロ付きエクセル→ .xlsm
この拡張子が違っていると開きません。例えばCドライブのテストフォルダにあるマクロ付きの 「ファイル1.xlsm」ファイルを開くのに
Workbooks.Open “C:\テストフォルダ\ファイル1.xlsx”
とすると、開きません。
Workbooks.Open “C:\テストフォルダ\ファイル1.xlsm”
とすると、開きます。
2.パスワード付きファイルを開く
パスワード付きファイルを開く場合は引数Passwordにファイルパスワードを指定します。
WorkBooks.Open Filename:=path, Password:=”1234″
パスワードを変数や定数に入れておいて、変数(または定数)で指定することもできます。
pw = “1234”
WorkBooks.Open Filename:=path, Password:=pw
Sub test()
'パスワード付きファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\testPass.xlsx"
Workbooks.Open Filename:=trgPath, Password:="1234"
End Sub
定数でパスワードを指定した例(変数でもいいんですけどね。)
Sub test()
'パスワード付きファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\testPass.xlsx"
'定数pwにファイルパスワードを代入
Const pw As String = "1234"
Workbooks.Open Filename:=trgPath, Password:=pw
End Sub
なお、パスワード付きファイルにパスワードを指定しないでWorkBooks.Openすると、エラーにはならず、パスワード入力画面が開きます。ここでパスワードを入力すると、マクロは次に進みます。
3.書き込みパスワード付きのファイルを開く
書き込みパスワードのついているエクセルファイルを開く、というシーンは読み取りパスワード付きファイルより断然少ないかと思います。
私は自分が更新するけどほかの人もファイルを開いて数字を見たりする可能性のある共有ファイルには書き込みパスワードを設定しています(勝手に変更されて、そのあげくに「間違ってるじゃないか!」と責められたことがあるので)
書き込みパスワード付きファイルを開く場合は引数WriteResPasswordにパスワードを指定します。
WorkBooks.Open Filename:=path, WriteResPassword:=”abc”
Sub test()
'書き込みパスワード付きファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\testWritePass.xlsx"
'定数writePasswordに書き込みパスワードを代入
Const writePassword As String = "abc"
Workbooks.Open Filename:=trgPath, WriteResPassword:=writePassword
End Sub
読み取りパスワードも書き込みパスワードもついているときは両方指定します。
Sub test()
'読み取りパスワード、書き込みパスワード付きファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\testPass2.xlsx"
Workbooks.Open Filename:=trgPath, Password:="12345", WriteResPassword:="abc"
End Sub
なお、「読み取り専用を推奨する」で保存されている場合、読み取り専用で開くことを促すメッセージが出てしまいます。DisplayAlartをFalseにしておくことで、このメッセージが出ることを防げます。
Sub test()
'書き込みパスワード付きファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\testWritePass.xlsx"
'読み取り専用で開けよメッセージを出すのを防止
Application.DisplayAlerts = False
Workbooks.Open Filename:=trgPath, WriteResPassword:="abc"
'アラート出さないを解除
Application.DisplayAlerts = True
End Sub
3.読み取り専用で開く
逆に、開いたファイルに変更を加えるのでなく「ただ内容を読み取りたい」「開いたファイルは原本で、変更は加えるけど別名で保存する」という場合は、読み取り専用で開くのがおススメです。
なにがよいかというと、
・間違って変更を加えることがない
・共有ファイルでもしほかのだれかが開いている場合、メッセージが出てマクロが止まる、ということがない
Sub test()
'読み取り専用で開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
Dim wb As Workbook
Set wb = Workbooks.Open(filename:=trgPath, ReadOnly:=True)
With wb
'ファイルに変更を加え
.Worksheets(1).Range("A1").Value = 1
'別名保存
.SaveAs Filename:=ThisWorkbook.Path & "\testtest.xlsx"
'閉じる
.Close
End With
End Sub
4.Dir関数でファイルの存在確認をしてから開く(エラー回避)
ファイルを開くときに予想できるエラーは回避しておいた方がいいですよね。
予想できるエラー:開こうとするファイルがない!
まず、Dirでファイルがあるかどうかを確認するコードを入れておくといいです。
Dir(ファイルのパス) でファイル名(拡張子付き)が返ります。
Dir関数の引数のファイルパスにはフォルダ名、拡張子付きファイル名を指定します。
指定したファイルパスのファイルがない場合は空白の文字列が返ります。
戻ってきたファイル名が空白だった場合はメッセージを出して処理を終了する、という流れにすることが多いです。
Sub test()
'エクセルファイルを開く
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
'開きたいファイルパスが正しいかDirで検査
Dim filename As String
filename = Dir(trgPath)
'Dirの戻り値が空白の場合ファイルパスが正しくないということ
If filename = "" Then
MsgBox "ファイルがありません"
Exit Sub
End If
'Dirの戻り値が空白でない場合はファイルパスが正しいので処理継続
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=trgPath, ReadOnly:=True)
End Sub
5.Dir関数でファイル名を取得してから開く(ワイルドカードの利用)
エクセルブックの種類には、以下の3種類の拡張子があります。
最近のエクセル→ .xlsx
古いエクセル→ .xls
マクロ付きエクセル→ .xlsm
フォルダ名やファイル名はわかるんだけど、.xlsx .xls のどっちで保存されているか不明、という場合など、ワイルドカードを使用してファイル名を指定するとよいです。
Sub test()
'エクセルファイルを開く。拡張子が不明なためワールドカード使用
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xls*"
Debug.Pirnt(trgPath)
'開きたいファイルパスが正しいかDirで検査
Dim filename As String
filename = Dir(trgPath)
'Dirの戻り値が空白の場合、ファイルがないということなので、処理を終了する
If filename = "" Then
MsgBox "ファイルがありません"
Exit Sub
End If
'Dirの戻り値が空白でない場合はファイルがあるので処理継続
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=trgPath, ReadOnly:=True)
End Sub
trgPath = ThisWorkbook.Path & “\test.xls*“
.xls* と、ワイルドカード(*)を使用して、最後の文字を何が来てもいいし、なくってもいいという状態にしています。
もし存在するファイルがCドライブのテストフォルダにある「test.xlsx」だった場合、Debug.Printで出力される trgPath は
C:\テストフォルダ\test.xlsx
となります。
もし存在するファイルがCドライブのテストフォルダにある「test.xls」だった場合、Debug.Printで出力される trgPath は
C:\テストフォルダ\test.xls
となります。
6.ほかの人がファイルを開いている場合は処理をやめる
会社などで共有ドライブを使用している場合、使いたいファイルをほかの人が開いていて「読取専用」となってしまってファイルを更新できないことがありますよね。
VBAでもほかのファイルを開いて、書き込み処理をしてそのファイルを保存して閉じる、等の処理をすることがあります。しかし、やはりほかの人が更新したいエクセルブックを開いている場合、読取専用になるため処理が止まってしまいます。
それを回避するためには、開いたエクセルブックが「読取専用」状態かを調べて、「読取専用」状態の場合は処理をストップする、という処理を入れておくとよいです。
WorkBookオブジェクトのReadOnlyプロパティを調べることで実現できます。
WorkBookが「読取専用」の場合、ReadOnlyプロパティは ture になります。
以下の例では workbook.ReadOnly が true の場合、メッセージを表示し、そのブックを保存せずに閉じて、処理を終了しています。
Sub test()
'ファイルパスを変数trgPathに代入
Dim trgPath As String
trgPath = ThisWorkbook.Path & "\test.xlsx"
'ファイルを開く
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=trgPath)
'ファイルが読取専用の場合、メッセージを表示し、ファイルを閉じて処理を中断する
If wb.ReadOnly = True Then
MsgBox "ファイルが読取専用です。処理を中断します"
wb.Close False
Exit Sub
End If
'読取専用でない場合、処理継続
With wb
.Worksheets(1).Range("A1").Value = "aaa"
.Close True
End With
MsgBox "処理完了"
End Sub
7.最後に
今回は以上になります。
そのうち続編(フォルダ化のファイルを次々開く)をやりたいと思います
お読みいただきありがとうございました。
8.参考文献・記事
【VBA】パスワードが設定されたエクセルファイルを開く
https://excel-toshokan.com/vba-excel-open-password/
Workbook.ReadOnly プロパティ (Excel)
https://learn.microsoft.com/ja-jp/office/vba/api/excel.workbook.readonly
コメント