- ベストアンサー
エクセルマクロでcsvファイルをまとめる方法
- エクセルマクロを使用して、「csv」フォルダ内の複数のcsvファイルの一部のデータをまとめる方法を紹介します。
- エクセルマクロを実行すると、csvファイルを順番に開き、指定したセルのデータを「まとめ」ファイルに貼り付けます。
- csvファイルを処理し終わるまで、繰り返し処理を行います。アレンジは可能ですが、この方法はシンプルで効率的です。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
大変申し訳ございません。 私、チェック用のデータの作成を間違えていました。 Sub Sample() Dim bk As Workbook, sh As Worksheet, ts As Worksheet Dim a As Variant, b As Variant, i As Integer, c As Long Dim f As String, p As String Set ts = ThisWorkbook.ActiveSheet a = Array(1, 19, 24, 29) b = Array("B1", "B18", "B23", "F23", "B27", "F27", "C36", "C900") p = "D:\Programing\Test_01" f = Dir(p & "\*.csv") c = 0 Application.ScreenUpdating = False Application.DisplayAlerts = False Do Until f = "" Set bk = Workbooks.Open(p & "\" & f) Set sh = bk.ActiveSheet c = c + 1 For i = 0 To 3 sh.Range(b(i * 2) & ":" & b(i * 2 + 1)).Copy If i = 1 Or i = 2 Then ts.Range(ts.Cells(a(i), c), ts.Cells(a(i), c)).PasteSpecial Paste:=xlPasteValues, Transpose:=True Else ts.Range(ts.Cells(a(i), c), ts.Cells(a(i), c)).PasteSpecial Paste:=xlPasteValues, Transpose:=False End If Next i bk.Close Set sh = Nothing Set bk = Nothing f = Dir() Loop Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub おっしゃるとおり、縦横の値の書き込みが間違っていました。 今回は、「Copy・Paste」を使って、縦横も正確に処理していると思うのですが・・・ 申し訳ないのですが、今一度、ご確認ください。
その他の回答 (5)
- Prome_Lin
- ベストアンサー率42% (201/470)
今一度、データを作成して、確認したのですが、 元B1~B18をコピー まとめ先A1~A18へ入力 元B23~F23をコピー まとめ先A19~A23へ入力 元B27~F27をコピー まとめ先A24~A28へ入力 元C36~C900をコピー まとめ先A29~A893へ入力 という前提条件が合っていれば、間違いなく動いています。 「B1~B18」→「A1~A18」など、合っていますか?
補足
度々すみません。 元B1~B18をコピー まとめ先A1~A18へ入力 これはok 元B23~F23をコピー まとめ先A19~A23へ入力 これはng B23のみの値がすべて入っています。 元B27~F27をコピー まとめ先A24~A28へ入力 これはng B27のみの値がすべて入っています。 元C36~C900をコピー まとめ先A29~A893へ入力 これはok 行方向のコピーから列方向へ並べて貼り付け、がうまくいってないのでしょうか。 マクロはそのままコピーしており指定するフォルダ名しか変更してないです。 状況の方伝わりますでしょうか。 すみませんがよろしくお願い致します。
- Prome_Lin
- ベストアンサー率42% (201/470)
遅くなり、申し訳ございません。 一応、動作確認はしたつもりなのですが、問題があれば言ってください。 今回は、「csv」ファイルを、テキストファイルとして読み込むのではなく、いったん、エクセルのファイルとして開いて、そこから指定の範囲の値を、マクロを走らせているブックに書き込んでいます。 ★★★8行目を質問者の環境に合わせてから、実行してください★★★ Sub Sample() Dim bk As Workbook, sh As Worksheet, ts As Worksheet Dim a As Variant, b As Variant, i As Integer, c As Long Dim f As String, p As String Set ts = ThisWorkbook.ActiveSheet a = Array(1, 18, 19, 23, 24, 28, 29, 893) b = Array("B1", "B18", "B23", "F23", "B27", "F27", "C36", "C900") p = "D:\Programing\csv_01\csv" f = Dir(p & "\*.csv") c = 0 Application.ScreenUpdating = False Do Until f = "" Set bk = Workbooks.Open(p & "\" & f) Set sh = bk.ActiveSheet c = c + 1 For i = 0 To 3 ts.Range(ts.Cells(a(i * 2), c), ts.Cells(a(i * 2 + 1), c)).Value = _ sh.Range(b(i * 2) & ":" & b(i * 2 + 1)).Value Next i bk.Close Set sh = Nothing Set bk = Nothing f = Dir() Loop Application.ScreenUpdating = True End Sub 一応、簡単な説明をしておきます。 Set ts = ThisWorkbook.ActiveSheet 「ThisWorkbook」は、マクロを走らせているブックで、「ActiveSheet」は、前面に出ている、処理対象になっているシートのことです。 a = Array(1, 18, 19, 23, 24, 28, 29, 893) b = Array("B1", "B18", "B23", "F23", "B27", "F27", "C36", "C900") 指定の範囲を、配列変数に格納しています。 たとえば、「b(0) = "B1"」、「b(1) = "B18"」、・・・「b(7) = "C900」としています。 p = "D:\Programing\csv_01\csv" 「csv」ファイル群が存在するフォルダです。 f = Dir(p & "\*.csv") そのフォルダ内の「csv」ファイルを読み込んでいます。 c = 0 実際に書き込む、列カウント用変数の初期化。 Application.ScreenUpdating = False ファイルを開いたり閉じたりすると、画面がチカチカするのと、時間もかかるので、「画面の更新を停止」しています。 Do Until f = "" そのフォルダ内の「csv」ファイルが処理し終わるまで繰り返し。 Set bk = Workbooks.Open(p & "\" & f) 「csv」ファイルを開いています。 Set sh = bk.ActiveSheet そのファイルのアクティブシートを「sh」にセットしています。 これで、「sh.Range("A1").Value」などと記述すれば、「開いたブックのアクティブシートのセルA1の値」と記述しているのと同じで、今現在、どのブックやシートがアクティブになっているか気にする必要がありません。 c = c + 1 1列カウント。 For i = 0 To 3 全部で処理する範囲が4組ありますので、4回繰り返します。 ts.Range(ts.Cells(a(i * 2), c), ts.Cells(a(i * 2 + 1), c)).Value = _ sh.Range(b(i * 2) & ":" & b(i * 2 + 1)).Value これで、1行です。 「i * 2」は、「i」が「0」のときは、「0、2、4、6」と変化します。 したがって、「i * 2 + 1」は、「1、3、5、7」です。 これは、「a = Array(1, 18, 19, 23, 24, 28, 29, 893)」に対応していて、「a(0) = 1」、「a(1) = 18」が1組、「a(2) = 19」、「a(3) = 23」が1組、「a(4) = 24」、「a(5) = 28」が1組、「a(6) = 29」、「a(7) = 893」が1組です。 またその下も「b(0) = "B1"」、「b(1) = "B18"」が1組で、「a(0)」、「a(1)」の組に対応しています。 これで、開いた「csv」ファイルは、セルの位置を固定で読み込んで、マクロを走らせているブックには、ファイルを開くごとに、横へ横へと書き足してゆきます。 Next i を、4組実行しています。 bk.Close Set sh = Nothing Set bk = Nothing ファイルを閉じています。 f = Dir() ファイルを内容を更新しています。 Loop を、「csv」ファイルがなくなるまで、繰り返します。 Application.ScreenUpdating = True 「画面の更新」を再開しています。
補足
ご丁寧に回答いただきありがとうございます。 動作の方確認しました。 一部のみデータがおかしい箇所がありますので確認していただけますでしょうか。度々申し訳ありません。 データコピー後ファイルのA列のみ捉えて言うと、 A19~A23とA24~A28の部分において、 同じ数字が並ぶようになってしまっています。 A19には元のB23の数字が入っており間違いはないですが、続いてのA20~A23にもB23の値が入っているようです。(ほんとはC23~F23の値が入ってほしい) A24~A28でも同じ症状です。 その他は問題無さそうです。 すみませんがよろしくお願い致します。
- Prome_Lin
- ベストアンサー率42% (201/470)
こういうことでしょうか? 6行目の「p = "D:\Programing\Test_01\"」は、今は、私の環境ですので、質問者の環境に合わせてから、実行してください。 なお、「"csv"フォルダ」を開いておく必要はありません。 最後に、簡単な説明をしますので、読んで、質問者の使いやすいように変更してください。 Sub Sample() Dim n() As String, f As String Dim m As Long, p As String Dim i As Long, j As Long Dim x As String, a As Variant p = "D:\Programing\Test_01\" f = Dir(p & "*.csv") m = -1 Do Until f = "" m = m + 1 ReDim Preserve n(m) n(m) = p & f f = Dir() Loop For i = 0 To m - 1 For j = i + 1 To m If n(i) > n(j) Then x = n(i) n(i) = n(j) n(j) = x End If Next j Next i For i = 0 To m Open n(i) For Input As #1 Line Input #1, x a = Split(x, ",") Close #1 Cells(1, i + 1).Value = a(0) Cells(2, i + 1).Value = a(1) Next i End Sub 簡単な説明です。 p = "D:\Programing\Test_01\" 「csv」ファイル群が存在するフォルダを「p」に入れていますが、最後に「\」を忘れないでください。 f = Dir(p & "*.csv") そのフォルダ内のすべての「csv」ファイルが「f」に入りました。 m = -1 「csv」ファイルの個数をカウントする変数の初期化。 Do Until f = "" すべての「csv」ファイルを1つずつ処理。 m = m + 1 1個カウント(最初は「0」になります)。 ReDim Preserve n(m) 配列変数を用意。 n(m) = p & f 配列変数にフォルダとファイル名を格納しています。 f = Dir() Loop を、すべての「csv」ファイルで繰り返しています。 For i = 0 To m - 1 For j = i + 1 To m If n(i) > n(j) Then x = n(i) n(i) = n(j) n(j) = x End If Next j Next i 念のため、ファイル名をソートしています。 For i = 0 To m ソートされた結果の順番で読み込みます。 Open n(i) For Input As #1 ファイルを、「読み込み専用」で開いています。 Line Input #1, x 1行読み込んで、「x」に入れています。 a = Split(x, ",") 「Split()」というのは、区切り記号(今回はもちろん、「,」(カンマ)が区切り記号です)を使って配列変数に格納します。 たとえば、読み込んだ1行が、「a,b,c」の場合、「a(0) = "a"」、「a(1) = "b"」、「a(2) = "c"」となります。 この「a(0)」が、エクセルで言う「A1」に当たり、「a(1)」が「B1」に当たります。 Close #1 閉じています。 Cells(1, i + 1).Value = a(0) Cells(2, i + 1).Value = a(1) セルに書き込んでいます。 もちろん、ファイルを読み込むごとに、右へ右へと書き込んでいます。 Next i を、すべての「csv」ファイルで繰り返しています。
補足
ご回答ありがとうございました。 データ取り込みのところでアレンジしようかと試みましたが理解不足で本当に申し訳ありません。詳細を書かせていただきますのでもう少しご教示いただけますでしょうか。 元B1~B18をコピー まとめ先A1~A18へ入力 元B23~F23をコピー まとめ先A19~A23へ入力 元B27~F27をコピー まとめ先A24~A28へ入力 元C36~C900をコピー まとめ先A29~A893へ入力 その後、まとま先はB列、C列と並んでいくといった感じです。
- nan93850673
- ベストアンサー率32% (179/553)
>"csv"フォルダと"まとめ"ファイルは既に開かれている状態とします。 既に「"csv"フォルダを開いている」というのは、どういった状態でしょうか
補足
分かりにくくて申し訳ありません。 "csv"フォルダは予めダブルクリックして開かれており、タスクバーに存在(表示)している状態という説明で分かりますでしょうか。 マクロで指定するよりそちらの方がシンプルになるかと思いましたのでそのような前提で考えました。よろしくお願い致します。
- watabe007
- ベストアンサー率62% (476/760)
Sub Test() Dim objFSO As Object, objCsv As Object Dim v As Variant, col As Long Set objFSO = CreateObject("Scripting.FileSystemObject") For Each objCsv In objFSO.GetFolder("F:\csv").Files 'ホルダーのパスを明記 If objCsv.Name <> "まとめ.csv" Then 'まとめ.csvファイルは除外処理 With objFSO.OpenTextFile(objCsv) v = Split(.ReadLine, ",") .Close End With col = col + 1 'まとめ.csvファイルがアクティブな状態 ActiveSheet.Cells(1, col).Value = v(0) ActiveSheet.Cells(2, col).Value = v(1) End If Next End Sub
お礼
今回は別の方の回答より試させていただきましたが、自身の勉強のためこのマクロも動作を確認してみます。ご回答ありがとうございました。
お礼
目的通りの動作を確認できました。 最後までやり取りしていただき本当に感謝です。 この手の知識がある方は尊敬しますね。 私は生産技術をやってますが回答者様のような能力があれば仕事の効率が格段に上がると思います。 今回のをベースに色々勉強していきます。 ありがとうございました。