🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

782閲覧

VBA 配列に入れたシートを条件を付けて開く

yama0131

総合スコア16

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/10/16 01:41

前提・実現したいこと

いつもお世話になっております。VBAに関する質問です。

複数のファイルを開いて1つのシートに集計をするため、ファイルを配列に入れて処理をしたのですが、配列に入れたファイルがない場合に処理が止まってしまいます。

そこで、条件などを付けてファイルを開く方法を知りたいです。

発生している問題・エラーメッセージ

インデックスが有効範囲にありません。

該当のソースコード

VBA

1Dim strFiles() As String 2 Dim i As Integer 3 Dim fileNum As Integer 4 5 With Application.FileDialog(msoFileDialogOpen) 6 .AllowMultiSelect = True 7 8 .Filters.Clear 9 .Filters.Add Description:="全てのファイル", Extensions:="*.*" 10 11 .Title = "ファイルを開く" 12 13 If Not .Show Then Exit Sub 14 15 fileNum = .SelectedItems.Count 16 ReDim strFiles(1 To fileNum) 17 18 For i = 1 To fileNum 19 strFiles(i) = .SelectedItems(i) 20 Next i 21 22 End With 23 24'処理をするファイルを複数指定 25 26Workbooks.Open strFiles(1) 27'処理1 28Workbooks.Open strFiles(2) 29'処理2 30Workbooks.Open strFiles(3) 31'処理3 32 33'選択したファイルが2つだと、Workbooks.Open strFiles(3) で上記のエラーメッセージが出る。 34

試したこと

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

VBAでは、ファイルを開けない等の例外が起きる可能性があるコードを実行する場合には、On Error文で、エラーが発生した時の処理を指定します。

On Error Goto ラベル名
を使うと、エラーが発生した時の飛び先(ラベル)が指定できます。

On Error Resume Next
を使うと、エラーが発生しても、知らんぷりして先に進みます。

ワークブックを開いてみて、失敗したらメッセージを表示してから次の処理(次のファイル名でワークブックを開いて忌むる)に進むようにするなら、以下のようなコードになります。
コメントで動作の説明をしているので、参考にしてください。

Dim strFiles() As String Dim i As Integer Dim fileNum As Integer Dim wb as WorkBook With Application.FileDialog(msoFileDialogOpen) .AllowMultiSelect = True .Filters.Clear .Filters.Add Description:="全てのファイル", Extensions:="*.*" .Title = "ファイルを開く" If Not .Show Then Exit Sub fileNum = .SelectedItems.Count ReDim strFiles(1 To fileNum) For i = 1 To fileNum strFiles(i) = .SelectedItems(i) Next i ' ファイルを開いてみて、失敗したら(ファイルが無かったら)スキップするループ On Error Goto FileNotFound '失敗したら、ラベル FileNotFoundに飛ぶように設定 For i = 1 to fileNum       wb = Workbooks.open strFiles(i) 'ワークブックを開いてみる ' ' ここに、開いたワークブックを使った処理を書く。 ' ワークブックを開くのに失敗した時は、ラベル FileNotFoundのところに飛ぶので、 ' ここに書いたコードは実行されない。 ' Goto NextLoop 'エラーが起きた際のメッセージを出す部分を飛ばす FileNotFound: 'ラベル  ワークブックが開けなかったら、ここに飛んでくる 'エラーが起きたのだから、その旨のメッセージを表示する       msgbox("ファイル " & strFiles(i) " を開くことが出来ませんでした") NextLoop: Next i End With

投稿2019/10/16 02:58

coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

最初の回答は忘れてください(忘れなくてもいいけど質問の本筋ではなかったです)

2個しか選んでいないのに3個目を開こうとしたときにエラーになるって話ですね。
ループで処理しましょう。

VBA

1Dim strFiles() As String 2 Dim i As Integer 3 Dim fileNum As Integer 4 5 With Application.FileDialog(msoFileDialogOpen) 6 .AllowMultiSelect = True 7 8 .Filters.Clear 9 .Filters.Add Description:="全てのファイル", Extensions:="*.*" 10 11 .Title = "ファイルを開く" 12 13 If Not .Show Then Exit Sub 14 15 fileNum = .SelectedItems.Count 16 ReDim strFiles(1 To fileNum) 17 18 For i = 1 To fileNum 19 strFiles(i) = .SelectedItems(i) 20 Next i 21 22 End With 23 24'処理をするファイルを複数指定 25 26For i = 1 To fileNum 27 Workbooks.Open strFiles(i) 28 '処理 29Next

以下は最初の回答

配列に入れなおす必要性に関しては他の回答通り無駄な処理と思いますが、本件の問題は、いざ開こうと思ったらファイルがなかったときの対応方法と思います。
仕様にもよるのですが、以下の3つの対応方法があると思います。

1.エラーを無視する

開けなかったとしても無視して処理を進める場合です。
関数内冒頭にOn Error Resume Nextを宣言しましょう。

VBA

1Dim strFiles() As String 2On Error Resume Next 3

2.エラーが出たらメッセージを出して次の処理へ進める

さすがにエラー無視はあれなんでメッセージくらいは出しましょう。
関数内冒頭でOn Error Gotoを宣言して、エラーをハンドリングできるようにします。

VBA

1Sub sample1() 2 On Error GoTo ERRHDL 3 Workbooks.Open "A.xlsx" 4 Workbooks.Open "B.xlsx" 5 Exit Sub 6 7ERRHDL: 8 MsgBox Err.Description 9 Resume Next 10End Sub

3.開く前にファイルがあるかチェックする

普通はこれです。
エラーが起きないように作るようにしましょう。
以下のサンプルはファイル名をべた書きしてるので上長ですが、配列に入っているのですからループで回せば簡単ですね。

VBA

1Sub sample1() 2 If Dir("a.xlsx") <> "" Then 3 Workbooks.Open "a.xlsx" 4 Else 5 MsgBox "A.xlsxは存在しません" 6 End If 7 If Dir("B.xlsx") <> "" Then 8 Workbooks.Open "B.xlsx" 9 Else 10 MsgBox "B.xlsxは存在しません" 11 End If 12End Sub

上記に挙げたのはあくまでもサンプルなので、あとはご自分のコードに適用してみてください。
.

投稿2019/10/16 02:35

編集2019/10/16 04:39
ttyp03

総合スコア17000

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

SelectedItems自体はコレクションで配列みたいなものですので、わざわざ配列に入れなおすのは無駄ですね。

SelectedItemsにファイル名が格納されているので、それに対して、Forループで回して処理すればいいのでは。


コード例

vba

1Public Sub OpenBooks() 2 3 With Application.FileDialog(msoFileDialogOpen) 4 .AllowMultiSelect = True 5 .Filters.Clear 6 .Filters.Add Description:="全てのファイル", Extensions:="*.*" 7 .Title = "ファイルを開く" 8 9 If Not .Show Then Exit Sub 10 11 Dim i As Integer 12 For i = 1 To .SelectedItems.Count 13 Workbooks.Open strFiles(i) 14' 処理i 15 Next 16 End With 17 18End Sub

コード例2
For Each でループしてみました。個人的にはこちらの方が読みやすいと思います。

vba

1Public Sub OpenBooks2() 2 3 With Application.FileDialog(msoFileDialogOpen) 4 .AllowMultiSelect = True 5 .Filters.Clear 6 .Filters.Add "Excelブック", "*.xls; *.xlsx; *.xlsm", 1 7 .Title = "ワークブックを開く" 8 9 If Not .Show Then Exit Sub 10 11 Dim SelectedBook As Variant 12 For Each SelectedBook In .SelectedItems 13 Workbooks.Open SelectedBook 14' 処理 15 Next 16 End With 17 18End Sub

処理の部分が長いなら、関数に分割するといいでしょう。


SelectedItemsに対してはForで回せば、ファイルが存在しないということは通常はあり得ないですか、
処理途中で削除されたとか、排他ロックさていて開けないとか、ファイルが壊れていて開けないとか、、、
いろいろあると思いますので、その場合のエラー処理も追加したコード例

vba

1Public Sub OpenBooks() 2 3 With Application.FileDialog(msoFileDialogOpen) 4 .AllowMultiSelect = True 5 .Filters.Clear 6 .Filters.Add "Excelブック", "*.xls; *.xlsx; *.xlsm", 1 7 .Title = "ワークブックを開く" 8 9 If Not .Show Then Exit Sub 10 11 Dim SelectedBook As Variant 12 For Each SelectedBook In .SelectedItems 13 Call ProcessToBook(ProcessToBook) 14 Next 15 End With 16 17End Sub 18 19Public Sub ProcessToBook(BookName As String) 20 Dim wb As Workbook 21 Set wb = Workbooks.Open(BookName) 22 If Err.Number <> 0 Then 23 MsgBox Err.Description 24 ProcessToBook = False 25 Exit Sub 26 End If 27 On Error GoTo 0 28 29 'ここにブックへの処理を記述 30 'これ以降でエラー処理が必要なら、上記のブックが開けなかった場合のエラー処理とは別に 31 ’ここからOn Error を記述 32 33 wb.Close: Set wb = Nothing 34End Sub

この辺りはいろいろ好みがあると思いますので、自分が書くならというコード例です。
参考までに。

投稿2019/10/16 02:04

編集2019/10/16 04:26
hatena19

総合スコア34073

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問