
VBA超初心者なりに記述したのですが、どうしたらいいのかわからないのでお助けください。
例えば以下のような一定の命名規則のファイルが、r:\testに複数あります。
0123-20140301-abcd.txt
0124-20140302-efgh.txt
xxxx-20140301.csv
xxxx-20140302.csv
「通し番号4桁-日付8桁-4桁(不定).txt」に対応する「xxxx(固定)-日付8桁.csv」のファイルがあるかチェックしたいだけなのですが、以下の記述では一番古い日付の1個しかチェックしてくれません。
''''''''''''''''''''''''''''''''''''''''''''''''''
Dim buf As String
Dim cnt As Long
buf = Dir("r:\test\????-20*.txt")
Do While buf <> ""
If Dir("r:\test\xxxx-" & Mid(buf, 6, 8) & ".csv") <> "" Then
Call MsgBox(buf & "が存在します")
End If
cnt = cnt + 1
buf = Dir()
Loop
Call MsgBox(cnt & "個のファイルをチェック済み")
''''''''''''''''''''''''''''''''''''''''''''''''''
「xxxx-20140301.csv」が存在しない場合は「1個のファイルをチェック済み」と出て終わります。
本当は2個のファイルをチェックしてほしいのです。
なお、実際にファイルが何個あるかはその時々なので、いつでも使えるようにForNextではなくDoLoopを選びました。
If~Endifがなければ「2個のファイルをチェック済み」と出るので、その部分の記述が怪しいとは思うのですが。
なお、自宅のPCにはExcelがないので、VB2010Expressを入れて再現してみました。
msgboxの記述方法が違うくらいで、後は職場で悩んでいた内容そのままです。
どうぞよろしくお願いします。
No.1ベストアンサー
- 回答日時:
Dir 関数は、同一パスで繰り返し呼び出す場合、引数を書かずに実行するわけですが、その際、最後に指定していたパスで呼び出されることになります。
つまり引数なしとすると、テキストファイルと CSV ファイルのパスで交互に検索するというのは、できないということになりますね。また、引数ありで繰り返し実行しても、続きのファイルはヒットせず、Dir はずっと最初のファイル名を返し続けるので、「一番古い日付の1個」のみといった動作になります。
下のコードでは、いったん全てのテキストファイルのファイル名を動的配列の中にためておいて、それが終わってから、対応する CSV を探し始めるという手順にしています。これで様子を見てください。
Sub Macro1()
Dim p As String, textFileName As String, csvFileName As String, a() As String, cnt1 As Long, cnt2 As Long, i As Long
p = "r:\test\????-20*.txt"
textFileName = Dir(p)
ReDim a(0) As String
a(0) = textFileName
Do While textFileName <> ""
cnt1 = cnt1 + 1
textFileName = Dir()
ReDim Preserve a(cnt1) As String
a(cnt1) = textFileName
Loop
For i = 0 To cnt1
If a(i) <> "" Then
csvFileName = Dir("r:\test\xxxx-" & Mid(a(i), 6, 8) & ".csv")
If csvFileName <> "" Then
MsgBox csvFileName & " が存在します"
cnt2 = cnt2 + 1
End If
End If
Next i
MsgBox cnt2 & " 個の CSV ファイルを検出しました"
End Sub
この回答への補足
早速のご回答、ありがとうございます。
dir()でloop中にdir関数を使用したときの振舞いの謎が氷解し、感謝いたします。
変数に全ファイル名を入れて比較というのは先週試行錯誤していたときに思いついたのですが、ファイル数が不定なのでどれだけの変数を用意すればいいのかわからずあきらめていました。
動的配列のことを知り、勉強になりました。
ところでご教示いただいた内容をVBにそのままコピーして実行したところ、「配列変数を宣言するために'ReDim'ステートメントを使用することはできません」というエラーになりました。
ReDimとエラーについて調べたところ、最初の「Dim a() As String」だけで、a(0)やa(1)などを改めて宣言しなおす必要はないようです。
「As String」の部分だけを削ったら正常に動作しました。
ExcelのVBAだと宣言する必要があるのでしょうか。週明けに職場で試してみます。
No.2
- 回答日時:
>ReDimとエラーについて調べたところ、最初の「Dim a() As String」だけで、a(0)やa(1)などを改めて宣言しなおす必要はないようです。
すみません。おっしゃるとおりで、データ型を変更できるのは、Variant 型の変数のみです。ヘルプの「ReDim ステートメント」のページでもそのように説明されています。したがって 2 回目以降の「As String」は変更してないのでエラーにまではなりませんが、不要ですね。
注意点としては、Dim ステートメントにおいて始めから Variant の動的配列として宣言していて ReDim でデータ型を変更することは、できないということです。Dim において配列でない Variant の変数を宣言していて ReDim でデータ型を変更することは、できます。つまり () の有無により、エラーになったりならなかったりします。また、Variant の変数であっても、Preserve が付いていると変更できません。
成功
Dim a() As Long
ReDim a(0)
ReDim a(1)
成功
Dim a() As Long
ReDim a(0) As Long
ReDim a(1) As Long
エラー
Dim a() As Variant
ReDim a(0) As Long
ReDim a(1) As String
成功
Dim a As Variant
ReDim a(0) As Long
ReDim a(1) As String
エラー
Dim a As Variant
ReDim a(0) As Long
ReDim Preserve a(1) As String
エラー
Dim a As Long
ReDim a(0) As Long
variantの動的配列の再宣言のエラーについて、わざわざ試していただいてありがとうございます。
とは言え初心者ゆえvariant型の使いどころは理解が浅く、文字列や数列とはっきりしているときにはstringやlongを使う、としか考えておりません。
a() As Variant
a(1) = "data"
a(2) = 123
のようなデータがあれば、
b As String
b = a(1)
c As Long
c = a(2)
として別の変数に割り当てないと、むしろわからなくなってしまいます。申し訳ありません。
なお、学ばせていただいた通りに動的配列を試したところ、意図した動きをさせることができました。
すべてのファイル名をexcelのセルに出したり、解凍していないzipだけを解凍させるようなことも簡単にできました。
重ねてお礼申し上げます。
また何かございましたらよろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) Excel-VBAでのファイルの開き方 4 2023/02/14 11:01
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Excel(エクセル) Excel VBAどこが間違ってますか? 4 2023/07/17 10:04
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- Visual Basic(VBA) あるフォルダーのファイルを違う親フォルダーのサブフォルダーに移したい 11 2023/02/15 19:00
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) VBAでoutlook365が起動しません。 4 2022/08/25 13:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【Excel VBA】PDFを作成して,...
-
Microsoft Access エラー 3051
-
web.configファイル内、valueに...
-
エクセルVBA フォームを開く時...
-
VBAのDoLoopでファイルがあるか...
-
エクセルの質問です。
-
ファイルが別のPCで開けない
-
VBAでファイルパスが長すぎてコ...
-
ASP上でFileSystemObjectのDele...
-
"ダウンロード"のフォルダを消...
-
複数のテキストファイルをexcel...
-
batファイル処理でのテキストフ...
-
Accessでパソコンの情報を得るには
-
Excelでdatファイルを作成??
-
バッチによるショートカットの...
-
Excel VBAどこが間違ってますか?
-
bat ファイルでフォルダ作成&移動
-
バッチファイルが作成できない
-
WORDでたまにでてくる。
-
IEで複数のファイル選択方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
【Excel VBA】PDFを作成して,...
-
Microsoft Access エラー 3051
-
VBAでファイルパスが長すぎてコ...
-
FFFTPでサーバに新規フォルダが...
-
OCXのライセンス
-
エクセルVBA フォームを開く時...
-
Refreshで落ちる
-
VBAでFTPファイル転送がうまく...
-
ブラウザでASPファイルを開こう...
-
web.configファイル内、valueに...
-
ASP.NETで、別サーバーへファイ...
-
Excel VBA シートを指定して...
-
VBSで指定したフォルダにファイ...
-
BASP21のアップロードについて
-
フォルダ参照ではなくファイル...
-
ExcelVBAで、隠しフォルダにあ...
-
Adobe Reader について
-
VB2005 で encoding="Shift_JIS...
-
処理を別ファイルに書きたいん...
-
【python】pandasでExcel(...
おすすめ情報