質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

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

Q&A

解決済

3回答

5086閲覧

VBA フォルダ内ループの方法

cat_junko

総合スコア44

VBA

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

0グッド

0クリップ

投稿2015/11/14 11:05

ファルダ内ループについて教えてください。
グラフファイル@8ファイル”最大値”シートを、「計測内容」と言うファイルの”変位最大値”
へ書込みをしようとしています。

そのうちの一つについては、書込み成功しました。

Sub Book_Data_Copy2()
Dim wb_A As Workbook, wb_B As Workbook
Dim ws_A_HeniIchiran As Worksheet, ws_B_Saidai As Worksheet

'使用するブック、シートを変数に設定する。
Set wb_A = ActiveWorkbook '計測内容ファイル
Set wb_B = Workbooks.Open("C:\○良1908-11グラフ.xlsm") '最終的には、フォルダループしたい
Set ws_A_HeniIchiran = wb_A.Worksheets("変位一覧表")
Set ws_B_Saidai = wb_B.Worksheets("最大値")

'グラフからコピー
ws_B_Saidai.Activate '最大値をActiveにする
Range("I4:K5").Select '最大値の最初の項目が入っているセルを選択。ここは、全ファイル共通
Selection.Copy

'計測内容ファイルにペースト
wb_A.Activate '計測内容ファイルに移って
ws_A_HeniIchiran.Activate '変位一覧表シートをActivate
Range("C7").Select '変位量Xが入っているセルを選択。
ここは、ファイルが順番通り開く前提で+2づつ増やす。
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False

wb_B.Activate '元のブックに戻る
Range("J3").Select
ActiveWorkbook.Save
wb_A.Activate '元のブックに戻る
Range("J3").Select
ActiveWorkbook.Save

'グラフからコピー
ws_B_Saidai.Activate '最大値をActiveにする
Range("L4:M5").Select '変位量Z-XとZ-Yが入っているセルまとめて選択。ここは、全ファイル共通
Application.CutCopyMode = False
Selection.Copy

'計測内容ファイルにペースト
wb_A.Activate '計測内容ファイルに移って
ws_A_HeniIchiran.Activate '変位一覧表シートをActivate
Range("F7:G8").Select '変位量Z-XとZ-Yが入っているセルまとめて選択。ここは、ファイルが順番通り開く前提で+2づつ増やす。
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False

wb_B.Activate '元のブックに戻る
Range("J3").Select
ActiveWorkbook.Save
ActiveWorkbook.Close
wb_A.Activate '元のブックに戻る
Range("H3").Select
ActiveWorkbook.Save

End Sub

ただ、このままだとあまりいいプログラムとは思えないのでアドバイスもお願いします。
そして、フォルダ内を、ループする方法もご教示願います

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。

フォルダ内の処理について、既に回答で頂いているDir関数で目的の機能を実現できると思います。
対象のフォルダにExcel以外のファイルも存在しうるなら、以下のように拡張子まで書く等をします。

VBA

1fileName = Dir("c:\TargetFolder\*.xlsm")

後、少し気になった点がActivateSelectを使っている所でした。
質問で頂いている内容からすると対話的に処理を進めるのではなく、VBA内で順々に処理を進めていくように思えました。このような場合は、ActivateSelectを使わない手段があるなら避けた方が良いと考えています。

理由は、「アクティブなブックを閉じる」や「選択されたセルをコピーする」で利用されていると思いますが、OSやExcelが高負荷になっている際などで「期待するブックがアクティブでない」や「期待するセルが選択されていない」状況(タイミングの問題などで期待と異なる状態)発生の可能性が考えられるからです。(多くの場合、そうならないとは思いますが…)

繰り返しの中で**"状態に依存"**する書き方は避けた方が良いと思います。

ブックを閉じる際にアクティブにするのは、単純に冗長と言えるかも知れません。

例えば、以下はブックB(wb_B)からブックA(wb_A)へ指定範囲の内容をコピーペーストし、ブックBを閉じます。

コピーペーストはSelectionでなく、RangeのCopyやPaste(Special)を利用

ブックを閉じるのは、直接のWorkbookオブジェクトのCloseを利用

VBA

1Dim CopyRng As Range 'コピー元の範囲 2Dim PasteRng As Range 'ペースト先の位置 3 4' コピー元の範囲、ペースト先の位置を設定 5Set CopyRng = wb_B.Worksheets.Item("最大値").Range("I4:K5") 6Set PasteRng = wb_A.Worksheets.Item("変位一覧表").Cells(1,1) '←仮にA1セル 7 8'コピーペースト 9CopyRng.Copy 10PasteRng.PasteSpecial Paste:=xlPasteValues 'ほか必要に応じてオプション指定 11 12'ブックBを閉じる 13wb_B.Close() 14Set wb_B = Nothing

ざっくりした書き方になっていますが、後はループの中に組み込んで、想定できるエラーへの対処を追加すると良いと思います。
・"最大値"という名前のシートが存在しない可能性の有無

投稿2015/11/17 08:24

sgr-2

総合スコア294

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

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

cat_junko

2015/11/17 10:46

回答ありがとうございます。 難しいですね…???? 頂いたコードを、利用して打ち直ししてみて実行したらよく分からないことになってしまいました。 ネットワークが、不安定って言うのもあるのか分かりませんが一行ずつ実行すると止まってしまいます。 Wb_Bのクローズの位置が違うのでしょうか? また、close()となっているとエラーになってしまうのですが。
sgr-2

2015/11/17 11:29

こんばんは。 失礼しました、Closeの後ろの括弧は駄目でしたね… 私の間違いです。「wb_B.Close」が正しいです 止まってしまうというのは、エラーなのですかね? # 単純に対象のExcelファイルが大きいなど?? ネットワークが不安定という状況ですと、場合によってはVBA側かネットワーク側か原因の切り分けがややこしくなってしまうかも知れません。 テスト用にローカルにwb_Bにあたるファイルを手作りするのも良いかも知れません。 見た限りですと、シート名が「最大値」で「I4:K5」と「L4:M5」に値が入っていれば良いようですので
cat_junko

2015/11/17 12:28

こんばんわ。 早急の返信、ありがとうございます。 はい、最大値シートのその2つ部分だけ書き出しています。 一発で、書ければ一番いいのですが二つ目がセルが結合していてうまくいかないんです。 (いくのかな?) 明日、再度修正してから教えて頂いたようにすっきりしたコードに書き直してみたいと思います。 そうですね、ネットワーク上ではなくて一端ローカルでやってみるといいのかもしれませんね。 最近、インターネットにも中々繋がらないのでLANケーブルを抜き差ししているのも原因かもしれないです。 また、アドバイス宜しくお願いします❗
cat_junko

2015/11/17 23:39

sgr-2さん 完成しました。 また、「最大値」シートがあることを前提にこの書き込み作業を行う予定なのですが それでも、やはり今後のためにエラー処理はあった方がよいですか? ---------------------------------------------- Sub Book_Data_Copy2() Dim wb_A As Workbook, wb_B As Workbook Dim i Dim CopyRng1 As Range 'コピー元の範囲 Dim PasteRng1 As Range 'ペースト先の位置 Dim CopyRng2 As Range 'コピー元の範囲 Dim PasteRng2 As Range 'ペースト先の位置 '使用するブック、シートを変数に設定する。 Set wb_A = ActiveWorkbook '計測内容ファイル Dim vlFileName As String vlFileName = Dir("\\------------\グラフ\") i = 7 Do While (vlFileName <> vbNullString) Set wb_B = Workbooks.Open("\\-------\グラフ\" & vlFileName) ' コピー元の範囲、ペースト先の位置を設定 Set CopyRng1 = wb_B.Worksheets.Item("最大値").Range("I4:K5") Set PasteRng1 = wb_A.Worksheets.Item("変位一覧表").Cells(i, 3) '←C7セル 'コピーペースト CopyRng1.Copy PasteRng1.PasteSpecial Paste:=xlPasteValues 'ほか必要に応じてオプション指定 ' コピー元の範囲、ペースト先の位置を設定 Set CopyRng2 = wb_B.Worksheets.Item("最大値").Range("L4:M5") Set PasteRng2 = wb_A.Worksheets.Item("変位一覧表").Cells(i, 6) '←F7セル 'コピーペースト CopyRng2.Copy PasteRng2.PasteSpecial Paste:=xlPasteValues 'ほか必要に応じてオプション指定 'ブックBを閉じる wb_B.Close Set wb_B = Nothing vlFileName = Dir i = i + 2 Loop End Sub
sgr-2

2015/11/18 00:47

cat_junkoさん 完成しましたか、良かったです。 "最大値"シートのエラー処理については、運用(ルール)として「存在している(存在していないといけない)」となっているなら、書かなくて良いと思います。 Excelではないファイルだったり、"最大値"シートが無いファイルが含まれるかも知れないかな?と考えて色々書いていました。 なので、"起こり得ない事"なら書かなくて良いと思います。 # 私なら、完成したVBAを"誰が"使うのか?も書く/書かないの判断材料にします。 # VBAを全然分からない人も利用して、かつ誰かがフォルダに間違ったファイルを置いてしまった場合に、エラーが起こりえる。と考えた時にエラーで止まると困るかな?あたりを考えます。 ----- 最初のコードだと、ブックの上書き保存が入ってましたがしなくて大丈夫ですか? wb_Bの方は、コピー元にしているだけなので良いかも?と思ってましたが、wb_Aで保存が必要なら、LoopとEnd Subの間に「wb_A.Save」のように書くと良いかと思います。
cat_junko

2015/11/18 02:24

sgr-2さん そういうことなんですね。 今回は、たぶん今のフォルダにはエクセルのこのグラフ情報しか存在しないとは思いますが今後次工事等の他の方が使うことかんがえたらエラー処理は必要ですね! はい、wb_Bファイルは、コピーのみなのであえて保存作業は外しました。 そうでした。wb_Aに、保存入れていませんでしたね。 とりあえず、書き込みを目で確認して手作業で保存しています。 次回、作成時にはその部分を修正したいと思います。 ただ、エクセルではないものが存在する可能性はあるのでここも修正します。
sgr-2

2015/11/18 03:05

Excel以外のファイルや"最大値"シートが存在しない場合の対策であれば さわり部分ですが… (a)Excel以外のファイルを排除  Dir("c:\TargetFolder\*.xlsm")のようにすると良さそうです。  # xlsファイル(旧形式)とxlsmが混在する場合は少し考えないといけないですが (b)最大値シートが存在しない  関数の先頭に「On Error Resume Next」を書いて  例えば、以下のように書くと判別できます。  -----  Err.Clear  Set ws_Saidai = wb_B.Worksheets.Item("最大値")  If Err.Number = 0 Then   '最大値が存在する  Else   '最大値が存在しない   '実際にはErr.Numberに9が入る事が考えられますが、   'そこまで厳密に見なくても良いと思います。  End If  -----  # 後は、最大値シートが無いブックのファイル名をメッセージボックス等で知らせてあげると親切かなと思います。 何かあれば、新規質問やコメント等頂ければと思います。
cat_junko

2015/11/18 05:29

sgr-2さん コメント書いたつもりが・・・。 上記、追加情報ありがとうございます。 また、メッセージボックスの載せ方等もご教示いただけないでしょうか? そして、新たな質問が別件で出てきてしまったのでつい先ほど質問も立てました。 宜しくお願い致します。
sgr-2

2015/11/18 06:01

cat_junkoさん メッセージボックスの表示は「MsgBox関数」があります。 MsgBox "メッセージ", vbOKOnly, "タイトル" のような書き方で使う事が出来ます。 プログラムの処理と絡めて考えると、以下のような形をイメージしていました ----- Dim errMsg As String errMsg = "" Do While (...) If Err.Number <> 0 Then '最大値のシートが存在しない errMsg = errMsg + vlFileName + "には「最大値」シートが存在しません" + Chr(10) Else '最大値のシートが存在する End If Loop MsgBox errMsg, vbOKOnly, "メッセージ" ----- # メッセージボックスは多くの情報を載せる手段としてはスマートでないので、多いと思ったらメッセージボックス自体に表示する内容は簡潔なもの(省略)した方が良いと考えています。(多い少ないの明確な線引きは?と言われると辛いですが…)
guest

0

VBA

1 Dim vlFileName As String 2 Dim vlIndex As Long 3 4 vlFileName = Dir("c:\temp\") 5 vlIndex = 1 6 7 Do While (vlFileName <> vbNullString) 8 Me.Range("A" & vlIndex) = vlFileName 9 vlIndex = vlIndex + 1 10 vlFileName = Dir 11 Loop

dojikkoさんが言うようにシートにファイル名の一覧を出すといいと思いますよ
上記の場合は、「c:\temp\」の中にあるファイルを列挙します。

--追記--
Set wb_B = Workbooks.Open("C:\○良1908-11グラフ.xlsm") '最終的には、フォルダループしたい
ここをループして複数のシートを処理したいと思いますので、これの前に処理を追加して

VBA

1 Dim vlFileName As String 2 3 vlFileName = Dir("c:\temp\") 4 5 Do While (vlFileName <> vbNullString) 6 7 Set wb_B = Workbooks.Open("C:\\" & vlFileName) 8 ~以下処理~ 9 10 wb_B.close() 11 vlFileName = Dir 12 Loop

こんな感じでループすればよいと思いますよ。

投稿2015/11/17 05:42

編集2015/11/17 06:35
trick

総合スコア366

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

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

cat_junko

2015/11/17 06:13

早急の回答ありがとうございます。 これは、今あるマクロ内に折り込むのでしょうか? 一度は、ファイル名書き出しのみで作成(ネットより)したのですが 折り込んでそこからファイル呼び出して処理ができるのであればそうしたいのですが 当方初心者過ぎてついていけません。 ご教示願います。
cat_junko

2015/11/17 08:16

回答ありがとうございます。 ループは、出来て処理をしているようなのですが一つ目のファイルを8回書き出ししているようなんです。 --------------------------------------- Sub Book_Data_Copy2() Dim wb_A As Workbook, wb_B As Workbook Dim ws_A_HeniIchiran As Worksheet, ws_B_Saidai As Worksheet Dim i '使用するブック、シートを変数に設定する。 Set wb_A = ActiveWorkbook '計測内容ファイル Dim vlFileName As String vlFileName = Dir("\\●●●\●●●\●●●●●\●●●\グラフ\") Do While (vlFileName <> vbNullString) Set wb_B = Workbooks.Open("\\●●●\●●●\●●●●●\●●●\グラフ\" & vlFileName) Set ws_A_HeniIchiran = wb_A.Worksheets("変位一覧表") Set ws_B_Saidai = wb_B.Worksheets("最大値") i = 5 For i = 5 To 21 'グラフからコピー ws_B_Saidai.Activate '最大値をActiveにする Range("I4:K5").Select '最大値の最初の項目が入っているセルを選択。ここは、全ファイル共通 Selection.Copy '計測内容ファイルにペースト wb_A.Activate '計測内容ファイルに移って ws_A_HeniIchiran.Activate '変位一覧表シートをActivate Range("C" & i + 2).Select '変位量Xが入っているセルを選択。 'ここは、ファイルが順番通り開く前提で+2づつ増やす。 Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False wb_B.Activate '元のブックに戻る Range("J3").Select ActiveWorkbook.Save wb_A.Activate '元のブックに戻る Range("J3").Select ActiveWorkbook.Save 'グラフからコピー ws_B_Saidai.Activate '最大値をActiveにする Range("L4:M5").Select '変位量Z-XとZ-Yが入っているセルまとめて選択。ここは、全ファイル共通 Application.CutCopyMode = False Selection.Copy '計測内容ファイルにペースト wb_A.Activate '計測内容ファイルに移って ws_A_HeniIchiran.Activate '変位一覧表シートをActivate Range("F" & i + 2).Select '変位量Z-XとZ-Yが入っているセルまとめて選択。ここは、ファイルが順番通り開く前提で+2づつ増やす。 Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Next wb_B.Activate '元のブックに戻る Range("J3").Select ActiveWorkbook.Save ActiveWorkbook.Close wb_A.Activate '元のブックに戻る Range("H3").Select ActiveWorkbook.Save vlFileName = Dir Loop End Sub ------------------------------------- 何が、いけないのでしょうか?
trick

2015/11/17 08:22

デバッグにて、ループしているファイル名が変わっているか確認してみてください。 また、wb_B は使い終わったら、close したほうが良いと思います。
sgr-2

2015/11/17 09:03

横からすいません。 >cat_junkoさん 多分原因はFor Nextの部分です Do Whileの中でFor Nextを使ってiを回していますが、「i = i + 2」のように書いてファイルを進める度に加算させる必要があると思います。 ざっくりですが、以下のような形にする必要があるように思います。 -------------------- i = 5 '初期化(最初の位置) Do While 'コピーペースト処理(Range指示の中でiに2を加算する必要はないと思います) i = i + 2 'Loopの直前に書く Loop -------------------- >trickさん wb_Bはアクティブにして閉じてますね。 wb_B.Activate ActiveWorkbook.Close
trick

2015/11/17 10:29

sgr-2さん 本当ですね閉じてますね あまり見て無かったです。
cat_junko

2015/11/17 10:59

sgr-2さん ForNextを、使ったからいけなかったんですね…???? 確かに、これではForNextは回るけど肝心のDoLoopが無意味になっていました。 明日、練り直しします。 trickさん 度々、すいません。 明日、再度修正してみます。 そして、アドバイス宜しくお願いします。
cat_junko

2015/11/17 23:43

trickさん sgr-2さん (コードは、上に貼り付けてしまいました・・・) たくさんのアドバイスありがとうございました。 また、改善案等あればアドバイスを頂けると嬉しく思います。 宜しくお願い致します。
guest

0

Dir関数を使えばフォルダにあるファイルを列挙できます

ループの概念が理解できないうちは、作業用のワークシートにファイルの一覧を書き出してからそれを順番に処理していくようなコードを書くことをおすすめします
処理途中の一時的な情報や、処理結果等もその作業用のワークシートに都度書き出す様にしておけば、何ができて、何ができなかったかもわかるようになります

投稿2015/11/14 18:08

dojikko

総合スコア3939

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

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

cat_junko

2015/11/16 20:37 編集

作業用ファイルに、書き出してからそれを順番に書き出すというのの具体的なコードが知りたいです。 宜しくお願いします。 書き出すとこまでは、出来ました。
cat_junko

2015/11/17 23:46

dojikkoさん アドバイスありがとうございました。 なんとか、Dir関数でのループを完成させることができました。 これから、少しづつもっと理解できるよう勉強していきたいと思います。 また、宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問