
csvファイルの内容は、
"ID_A","ID_B","C","D","E" の5列でできたCSVがあります。
1行目は項目名です。
※デフォルトではShift-JIS、改行LFですが、可変可能です。
IDは13桁で、アルファベット大文字小文字、数字が入り混じっています。
ID_AとID_Bはほぼ同一なのですが稀に異なる場合があるのでそれだけ抽出したいのです。
CSVを選択して、ID_AとID_Bが異なる場合のみシートに書き出すようにするには
どうしたらよいでしょうか?
問題は、このCSVは300万行以上あるのでExcelシートで開くには分割する必要があり、
マクロで必要行だけ抽出できれば助かるのですが。。。
※また、最下行には7行のフッター情報が記載されており無視する必要があります。
よろしくお願いいたします。
A 回答 (13件中1~10件)
- 最新から表示
- 回答順に表示
No.13
- 回答日時:
まだ閉じられていませんが、解決していますよね?
#4で回答しましたが、
気になったのでスレッド汚しですみません。
>CSVを選択して、ID_AとID_Bが異なる場合のみシートに書き出すようにする(5列)
差異は稀とありますが、一応 インデックス1、2、3のシートを用意して
Sub CSV_Test()
Dim TS As Object
Dim Trg_csv As String, strTmp(1 To 1048576, 1 To 5) As String
Dim Ch As Variant, i As Long, j As Long: j = 1
Dim startTime As Double, endTime As Double, processTime As Double
Trg_csv = Application.GetOpenFilename("csv,*.csv,all,*.*")
If VarType(Trg_csv) = vbBoolean Or Trg_csv = "False" Then Exit Sub
Set TS = CreateObject("Scripting.FileSystemObject").OpenTextFile(Trg_csv, 1)
startTime = Timer
Do Until TS.AtEndOfStream
i = i + 1
Ch = Split(TS.ReadLine, ",")
If Ch(0) <> Ch(1) Then
strTmp(i, 1) = Ch(0)
strTmp(i, 2) = Ch(1)
strTmp(i, 3) = Ch(2)
strTmp(i, 4) = Ch(3)
strTmp(i, 5) = Ch(4)
End If
If i = 1000000 Then
Sheets(j).Range("A1").Resize(i, 5).Value = strTmp
i = 0: j = j + 1
Erase strTmp
End If
Loop
Sheets(j).Range("A1").Resize(i, 5).Value = strTmp
TS.Close
endTime = Timer
processTime = endTime - startTime
Debug.Print "処理時間:" & processTime
End Sub
CSVを出力するなら、、、、
Sub Extraction_Record()
Dim TS As Object
Dim Trg_csv As String, strTmp As String
Dim Ch As Variant
Dim startTime As Double, endTime As Double, processTime As Double
Trg_csv = Application.GetOpenFilename("csv,*.csv,all,*.*")
If VarType(Trg_csv) = vbBoolean Then Exit Sub
Set TS = CreateObject("Scripting.FileSystemObject").OpenTextFile(Trg_csv, 1)
startTime = Timer
With CreateObject("ADODB.Stream")
.Open
.Type = 2
.Charset = "UTF-8"
.WriteText = TS.ReadLine & vbLf
Do Until TS.AtEndOfStream
strTmp = TS.ReadLine
Ch = Split(strTmp, ",")
If Ch(0) <> Ch(1) Then
.WriteText = strTmp & vbLf
End If
Loop
.SaveToFile Format$("差分Data") & ".csv", 2
.Close
End With
TS.Close
endTime = Timer
processTime = endTime - startTime
Debug.Print "処理時間:" & processTime
End Sub
No.12
- 回答日時:
'VBE - ツールバー - ツール - 参照設定 - Microsoft Scripting Runtimeにチェックしてから、
'以下マクロを実行
Public Function get_diff_line()
Dim file_path As String
file_path = Application.GetOpenFilename("CSV, *.csv")
If file_path = "False" Then
MsgBox "キャンセルされました"
Exit Function
End If
Dim fso As New FileSystemObject
Dim f As TextStream
Dim str As String
Set f = fso.OpenTextFile(file_path)
Dim i As Long
i = 1
Do Until f.AtEndOfLine
Dim tmp As Variant
tmp = Split(f.ReadLine, ",")
If UBound(tmp) = 4 Then
If tmp(0) <> tmp(1) Then
ThisWorkbook.ActiveSheet.Cells(i, 1) = tmp(0)
ThisWorkbook.ActiveSheet.Cells(i, 2) = tmp(1)
ThisWorkbook.ActiveSheet.Cells(i, 3) = tmp(2)
ThisWorkbook.ActiveSheet.Cells(i, 4) = tmp(3)
ThisWorkbook.ActiveSheet.Cells(i, 5) = tmp(4)
i = i + 1
End If
End If
Loop
f.Close
MsgBox ("fin")
End Function
No.10
- 回答日時:
新規Bookに標準モジュールを追加して
try2、try3をその標準モジュールにコピペしただけで?
Excelの列表記、A、B、C・・がTRG、つまり13,995列目から始まってしまったと?
1列目から13,994列目はどうなってるんでしょうね?非表示?
コードをコピペしただけでそんな奇怪な現象が発生するのは初めて遭遇しました ;(
Excel再起動またはPCそのものを再起動してからもう一回試してみてもらえませんか
No.9
- 回答日時:
> 逆に行頭から英数字混在データの割合が高い場合は文字列データと判断され、
> 数値のみのデータが抽出されません
あいやそんな事はなく、フィールド全体が文字列データと判断される場合は数値のみでも文字列として扱ってくれたかも。
すみません、良く分からなくなりました。
try2、try3を新規ブック 標準モジュールに貼ったら、
A,B,C,,,,のエクセルのラベル表記が「TRG,TRH,TRI,,,」という表記になり、
try2も実行できず、、、
知識不足で申し訳ございません。
No.8
- 回答日時:
> IDは13桁で、アルファベット大文字小文字、数字が入り混じっています。
これは各データが英数字混在という意味ではないのでしょうか?
例えば#6のコメントのテスト用データのように数字のみ13桁の場合があり、
2行目から数行は数字のみ13桁の割合が高い、というケースに該当するのでしょうか?
a,b,c,d,e
A1111111x1111,A1111111x1111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
Z111111111111,X111111111111,3,4,5
1111411111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1116111111111,3,4,5
AA11111111111,A111111111111,3,4,5
実際もこのテスト用データのような組み合わせなら、フィールド全体が数値データと判断されたため
文字列データが抽出されません
逆に行頭から英数字混在データの割合が高い場合は文字列データと判断され、
数値のみのデータが抽出されません
こういったケースではQueryTablesやADOを使った手法では更に対策しないといけないので、
全レスのtry3を使ってください
速度的には少し遅くなる程度なので実用には耐えれるんじゃないかと思います
No.7
- 回答日時:
う~ム :(
> a,b,c,d,e
これフィールド名ですか?
wkSQL(2) = "WHERE [ID_A]<>[ID_B]"
質問文を基にここでフィールド名決め打ちしてますのでテスト用も合わせてほしかったですね
..まあ、いいですけど
Sub try2()
Dim wkCsv
wkCsv = Application.GetOpenFilename("csv,*.csv,all,*.*")
If VarType(wkCsv) = vbBoolean Then Exit Sub
Dim p As Long: p = InStrRev(wkCsv, "\")
Const ForReading As Long = 1
Dim buf() As String
With CreateObject("Scripting.FileSystemObject").OpenTextFile(wkCsv, ForReading)
buf = Split(.ReadLine, ",")
.Close
End With
With Sheets.Add
With .QueryTables.Add(Connection:="ODBC;Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=" & Left$(wkCsv, p), _
Destination:=.Range("A1"), _
Sql:="SELECT * FROM [" & Mid$(wkCsv, p + 1) & "] WHERE [" & buf(0) & "]<>[" & buf(1) & "]")
.AdjustColumnWidth = False
.Refresh BackgroundQuery:=False
.Delete
End With
End With
End Sub
Sub try3()
Dim wkCsv
wkCsv = Application.GetOpenFilename("csv,*.csv,all,*.*")
If VarType(wkCsv) = vbBoolean Then Exit Sub
Const ForReading As Long = 1
Const mx As Long = 1000000
Dim fs As Object 'Scripting.FileSystemObject
Dim ts As Object 'Scripting.TextStream
Dim tmp As String
Dim buf() As String
Dim x As Long
Dim y As Long
Dim i As Long
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(wkCsv, ForReading)
tmp = ts.ReadLine
buf = Split(tmp, ",")
x = UBound(buf)
ReDim ret(mx, x) As String
For i = 0 To x
ret(0, i) = buf(i)
Next
Do Until ts.AtEndOfStream
tmp = ts.ReadLine
If Mid$(tmp, 1, 13) <> Mid$(tmp, 15, 13) Then
y = y + 1
buf = Split(tmp, ",")
For i = 0 To x
ret(y, i) = buf(i)
Next
If y = mx Then
Sheets.Add.Range("A1").Resize(y + 1, x + 1).Value = ret
y = 0
End If
End If
Loop
ts.Close
Sheets.Add.Range("A1").Resize(y + 1, x + 1).Value = ret
End Sub
他の方からも具体策が出てますから試すなりなんなりリアクションされた方が良いかと思います
いや、大変失礼いたしました。
1行目は無視するだけで、項目名は動作に関係ないと見過ごしてました。
No.5、6 では項目名が「ID_A、ID_B」という前提だったんですね、
ちゃんと中身を見て今気づきました、申し訳ございません。
新たに提示していただいたソースは、その項目名に関わらず抽出できるようにしてくださったんですね?ありがとうございます!
私のサンプルCSVの項目名を「ID_A、ID_B」に修正したら、No.5のソースで動作しました。失礼いたしました。
ただし、求める結果ではなかったので報告します。
↓こういうデータで試したのですが抽出されませんでした。本来抽出されるべきなのですが。
AA11111111111,A111111111111,3,4,5
No.6
- 回答日時:
> SQL構文エラー..
ですか。では
>wkSQL(1) = Mid$(x, p + 1)
wkSQL(1) = "[" & Mid$(x, p + 1) & "]"
変更してみてください
また念の為QueryTables.Addの前に
Debug.Print Join(wkSQL)
など、SQL文字列確認してみてください
ファイル名に特殊文字が使われているんじゃないでしょうか
ありがとうございます。
一般ODBCエラーとなりました。
該当項目は、
wkQRY.Refresh BackgroundQuery:=False
でした。
ちなみにテスト用に用意したCSVファイルは
ファイル名:abc.csv
中身は、この通りです。
a,b,c,d,e
A1111111x1111,A1111111x1111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
Z111111111111,X111111111111,3,4,5
1111411111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1111111111111,3,4,5
1111111111111,1116111111111,3,4,5
No.5
- 回答日時:
300万行以上って厳しいだろうなぁ..と思いつ つ参考コード
Sub try()
Dim x
x = Application.GetOpenFilename("csv,*.csv,all,*.*")
If VarType(x) = vbBoolean Then Exit Sub
Dim wkSHT As Worksheet
Dim wkQRY As QueryTable
Dim wkCON(2) As String
Dim wkSQL(2) As String
Dim p As Long
p = InStrRev(x, "\")
wkCON(0) = "ODBC"
wkCON(1) = "Driver={Microsoft Text Driver (*.txt; *.csv)}"
wkCON(2) = "DBQ=" & Left$(x, p)
wkSQL(0) = "SELECT * FROM"
wkSQL(1) = Mid$(x, p + 1)
wkSQL(2) = "WHERE [ID_A]<>[ID_B]"
Set wkSHT = Sheets.Add
Set wkQRY = wkSHT.QueryTables.Add(Connection:=Join(wkCON, ";"), _
Destination:=wkSHT.Range("A1"), _
Sql:=Join(wkSQL))
wkQRY.Refresh BackgroundQuery:=False
wkQRY.Delete
End Sub
使いものにならない時は捨ててください :)
SQL構文エラーと出まして、結果が得られませんでした。
wkQRY.Refresh BackgroundQuery:=False
直せるスキルがなくてすみません。。
No.4
- 回答日時:
#2さんのアドバイスに賛成です
どうしてもExcelVBAでなら、結局、Windows Script Host Object Modelを参照してコマンドプロンプトを使う事になると思います。
銀鱗さんのコマンドを拝借すると
Dim cmd As String
cmd = "for /f " & """tokens=1,2,3,4,5 delims=, """ & " %i in ( souse.csv ) do ( if not %i==%j ( @echo %i,%j,%k,%l,%m >> make.csv ) )"
コマンドプロンプトで実行
CreateObject("WScript.Shell").Run "CMD.EXE /k " & cmd 'ディレクトリなど不具合確認のため /k にしてますが 実行時は /c でよろしいかと
これは、銀鱗さんのコマンドをVBAからコマンドプロンプトで実行しているにすぎません。
つまり、VBAでスタックを気にしながら色々やるより、コマンドプロンプトを使う方が良いと思います。
ディレクトリは、コマンドプロンプトで確認するか、適時変更してください。
コマンドプロンプトからCSVを操作したことがなかったので、銀鱗さんのコマンドは、大変勉強になりました。
(少し変えてしまいましたが、勝手に拝借してすみません)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) PowerQueryに詳しい方教えてください(Office365) 1 2022/07/24 21:11
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- Excel(エクセル) PowerQueryで行数の指定はできますか? 2 2022/08/26 11:13
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- その他(データベース) accessでの請求管理について 2 2022/06/13 21:51
- Excel(エクセル) Excelマクロの差分抽出のコードを教えていただきたいです。 2 2023/03/14 11:40
- Visual Basic(VBA) VBAで特定の場所にあるCSVファイル(複数)から特定場所を抜き出してExcelに転記したいです。 11 2023/05/23 16:29
- Ruby pandasでsqlite3にテーブル作成・追加・読み出しでindexの取り扱い方教えてください 5 2023/03/08 09:57
- その他(プログラミング・Web制作) DOSコマンドに詳しい方、お知恵をお貸しください 5 2022/11/04 20:55
- Access(アクセス) アクセス where句を使用して複数条件抽出をするには 2 2022/08/29 13:24
このQ&Aを見た人はこんなQ&Aも見ています
-
CSVファイルの指定列だけを読み込んでEXCELに表示したい
Excel(エクセル)
-
100万件越えCSVから条件を満たす行のみ抽出し、編集してエクセルシートに出力するには?
Ruby
-
エクセルVBA C列に特定の文字列を含む行のみを抽出し、一つのExcelにまとめたい。
Excel(エクセル)
-
-
4
VBAでの100万行以上のデータの取り込み
その他(プログラミング・Web制作)
-
5
エクセルVBA 2千万行のCSVファイルを開きたい
Visual Basic(VBA)
-
6
csvファイルを開かずに文字を検索し行を抽出したい
Visual Basic(VBA)
-
7
100万行のCSVを10万行ずつのファイルに区切るには?(UTF-8、改行LF)
Excel(エクセル)
-
8
VBAでブックを非表示で開いて処理して閉じる方法
Excel(エクセル)
-
9
巨大なCSVの加工(指定列のみの抽出)について
Visual Basic(VBA)
-
10
Excel:任意の列だけCSV形式で出力したい。
Excel(エクセル)
-
11
Access VBAで行ラベルが定義されていないというエラーが出ます
Access(アクセス)
-
12
Excelで数値→文字列変換で指数表示になったものをいっぺんに直したい
Excel(エクセル)
-
13
【VBA】テキストファイルを指定行数からの読み込み
Visual Basic(VBA)
-
14
エクセルVBA 大容量CSVファイルの読み込み
Visual Basic(VBA)
-
15
CSV形式にすると出てくる空白を消したいです。
その他(Microsoft Office)
-
16
バッチでテキストファイルから任意の行のみ取得したい
その他(プログラミング・Web制作)
-
17
VBAでCSVファイルを途中行まで読んだ後で最初の行から読み直す方法はありますか?
その他(プログラミング・Web制作)
-
18
VBA:Openステートメントで開いたCSVファイルの特定行を削除する方法
その他(プログラミング・Web制作)
-
19
[エクセル VBA]テキストファイルから特定の行のみを抜き出したい 下記のようなテキストファイルから
Excel(エクセル)
-
20
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Vba Array関数について教えてく...
-
【マクロ】シートの変数へ入れ...
-
【VBA】 結合セルに複数画像と...
-
【マクロ】並び替えの範囲が、...
-
【マクロ】開いているブックの...
-
VBAでCOPYを繰り返すと、処理が...
-
【マクロ】売上一覧YYYYMMDDHHS...
-
【ExcelVBA】5万行以上のデー...
-
vbsでのwebフォームへの入力制限?
-
エクセルのマクロについて教え...
-
vb.net(vs2022)のtextboxのデザ...
-
Vba セルの4辺について罫線が有...
-
エクセルのVBAコードと数式につ...
-
エクセルの改行について
-
VBA ユーザーフォーム ボタンク...
-
Excelマクロで使うVBAコードを...
-
VBAの質問(Msgboxについて)です
-
VBAでセルの書式を変えずに文字...
-
【ExcelVBA】値を変更しながら...
-
【マクロ】変数を使った、文字...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAでcsvファイルもシートもあ...
-
Excelマクロ 空白セルを無視し...
-
【ExcelVBA】300万件越えCSVか...
-
ダブルコーテーション付きでCSV...
-
ファイル名を変数で書きこむfwr...
-
VBAで複数のCSVからレコードセ...
-
CSVデータの文字列置換
-
複数のファイルをまたぐエクセ...
-
CSVファイルの比較と結果の取得...
-
【C#】 csvファイルをバイナリ...
-
PowerShellからGhostscriptを動...
-
EXCEL→CSV保存時のダブルクォー...
-
VB.NETでオブジェクトの内容を...
-
パイソン文法で ファイルオープ...
-
VB.netでShellExecuteがしたい
-
PowerShellでファイルの連結方法
-
Rubyを使用してcsvファイルを処...
-
rubyを用いたCSVファイルの分割...
-
バッチファイルでcsvファイルに...
-
エクセルの任意のシートをcs...
おすすめ情報