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

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

詳細はこちら
VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

Q&A

解決済

1回答

8363閲覧

VBScriptでcsvファイルもしくはテキストファイル内の重複を削除してテキストファイルに書き出したい

clonoth

総合スコア5

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

0グッド

0クリップ

投稿2021/01/05 14:45

編集2021/01/11 12:28

csvファイルを読み込んでテキストファイルに書き出すところまではできたのですが、
csvファイル内の重複を削除する方法がわかりません。

AAA.csv

csv

10001,田中,東京 20002,森田,神奈川 30005,田山,東京 40011,清水,山形 50009,小野,東京

 
BBB.csv

csv

10004,長谷川,長野 20002,森田,神奈川 30008,白川,新潟 40018,水野,富山 50029,寺田,東京

 
例えば上記の2つのcsvファイル(2行目の森田が重複)を結合して
最終的に下記のように森田の重複を削除した状態のテキストファイルを作りたいです。
result.txt

txt

10001,田中,東京 20002,森田,神奈川 30005,田山,東京 40011,清水,山形 50009,小野,東京 60004,長谷川,長野 70008,白川,新潟 80018,水野,富山 90029,寺田,東京

csvを読み込む時点での重複削除でも
一度テキストファイルに全行書き出した上で重複を削除する方法でも
どちらでもいいので、どういったアルゴリズムを組めばいいか教えていただけますでしょうか?

追記

vbs

1Dim fso 2Set fso = WScript.CreateObject("Scripting.FileSystemObject") 3 4GetFiles "./CSV", CSV_PATH '※フォルダ以下のCSVファイルパスを取得 5For i = 0 To UBound(CSV_PATH) 6 IF fso.GetExtensionName(CSV_PATH(i))="csv" Then 7 ReadFile CSV_PATH(i), LineArrTemp '※ファイルのデータを配列に格納 8 If i = 0 then 9 LineArrM = LineArrTemp '※1ファイル目 10 Else 11 ListMerge LineArrTemp, LineArrM '※2ファイル目以降は重複をチェックしてマージ 12 End If 13 End If 14Next

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

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

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

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

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

guest

回答1

0

ベストアンサー

UTF-8のファイル読み書きを想定しました。
よろしければお試しください。

VBS

1'=================== 2' CSVを配列に格納 3'=================== 4Dim LineArrA() 5ReadFile "AAA.csv", LineArrA 6Dim LineArrB() 7ReadFile "BBB.csv", LineArrB 8 9'=================== 10' 重複を削除+マージ 11'=================== 12Dim LineArrM 13LineArrM = LineArrA 14 15'※配列Bの中から配列Aにない要素だけ配列Mに追加する 16For i = 0 To UBound(LineArrB) 17 For j = 0 To UBound(LineArrA) 18 if LineArrB(i) <> LineArrA(j) then 19 '※配列Aにないものは配列Mに追加 20 if UBound(LineArrA) = j then 21 redim Preserve LineArrM(UBound(LineArrM) + 1) '配列を+1拡張 22 LineArrM(UBound(LineArrM)) = LineArrB(i) 23 End If 24 Else 25 '※配列Aにあるものは配列Mに追加しない 26 Exit For 27 End If 28 Next 29Next 30 31'=================== 32' ファイル書き込み 33'=================== 34Dim output 35Set output = CreateObject("ADODB.Stream") 36output.Type = 2 37output.Charset = "UTF-8" 38output.Open 39 40for i = 0 To UBound(LineArrM) 41 output.WriteText LineArrM(i), 1 '[0:改行なし 1:改行コード付加] 42Next 43output.SaveToFile "outputText.txt", 2 44output.Close 45 46 47'======================== 48' CSV読み込みプロシージャ 49'======================== 50Sub ReadFile(ByVal filePath, ByRef dataList) 51 Dim input 52 Set input = CreateObject("ADODB.Stream") 53 input.Open 54 input.Type = 2 55 input.Charset = "UTF-8" 56 input.LineSeparator = 10 57 input.LoadFromFile filePath 58 59 ' 対象ファイルから1行ずつ読み込む 60 Dim line 61 Dim aryStrings 62 Dim i 63 i = 0 64 Do Until input.EOS 65 line = input.ReadText(-2) 66 redim Preserve dataList(i) 67 'dataList(i) = line 68 dataList(i) = Replace(line, vbCr, "") '改行コード削除(書込時に改行コード付加) 69 'msgbox dataList(0) 70 i = i + 1 71 Loop 72 73 input.Close 74End Sub 75

追記

実行ファイルと同じ階層の「CSV」フォルダ以下のファイルを対象に重複削除・ファイル出力の処理を作ってみました。「CSV」フォルダ以下にCSVファイルを配置して試してみてください。CSVファイルはUTF-8にしてください。

VBS

1Option Explicit 2 3'=========== 4' メイン処理 5'=========== 6Dim LineArrM 7Dim LineArrTemp() 8Dim CSV_PATH() 9Dim i 10 11GetFiles "./CSV", CSV_PATH '※フォルダ以下のCSVファイルパスを取得 12 13For i = 0 To UBound(CSV_PATH) 14 ReadFile CSV_PATH(i), LineArrTemp '※ファイルのデータを配列に格納 15 If i = 0 then 16 LineArrM = LineArrTemp '※1ファイル目 17 Else 18 ListMerge LineArrTemp, LineArrM '※2ファイル目以降は重複をチェックしてマージ 19 End If 20Next 21 22WriteFile "outputText.csv", LineArrM 'ファイル出力 23'<メイン処理はここまで> 24 25 26'<以下はSubプロシージャ> 27'=================== 28' ファイル書き込み 29'=================== 30Sub WriteFile(ByVal outputPath, ByVal arr) 31 Dim output, i 32 Set output = CreateObject("ADODB.Stream") 33 output.Type = 2 34 output.Charset = "UTF-8" 35 output.Open 36 37 for i = 0 To UBound(arr) 38 output.WriteText arr(i), 1 '[0:改行なし 1:改行コード付加] 39 Next 40 output.SaveToFile outputPath, 2 41 output.Close 42End Sub 43 44'=================== 45' 重複を削除+マージ 46'=================== 47Sub ListMerge(ByVal arrTemp, ByRef arrM) 48 Dim i,j 49 '※配列Tempで配列Mにない要素だけ配列Mに追加する 50 For i = 0 To UBound(arrTemp) 51 For j = 0 To UBound(arrM) 52 if arrTemp(i) <> arrM(j) then 53 '※配列Mにないものは追加 54 if UBound(arrM) = j then 55 redim Preserve arrM(UBound(arrM) + 1) '配列を+1拡張 56 arrM(UBound(arrM)) = arrTemp(i) 57 End If 58 Else 59 '※配列Mにあるものは追加しない 60 Exit For 61 End If 62 Next 63 Next 64End Sub 65 66'======================== 67' リスト取得プロシージャ 68'======================== 69Sub GetFiles(ByVal folderPath, ByRef fileList) 70 Dim objFileSys 71 Dim objFolder 72 Dim objFile 73 Dim i 74 i = 0 75 76 Set objFileSys = CreateObject("Scripting.FileSystemObject") 77 Set objFolder = objFileSys.GetFolder(folderPath) 78 79 For Each objFile In objFolder.Files 80 '取得したファイルのファイル名を表示 81 redim Preserve fileList(i) 82 fileList(i) = folderPath & "/" & objFile.Name 83 i = i + 1 84 Next 85 86 Set objFolder = Nothing 87 Set objFileSys = Nothing 88End Sub 89 90'======================== 91' CSV読み込みプロシージャ 92'======================== 93Sub ReadFile(ByVal filePath, ByRef dataList) 94 Dim input 95 Set input = CreateObject("ADODB.Stream") 96 input.Open 97 input.Type = 2 98 input.Charset = "UTF-8" 99 input.LineSeparator = 10 100 input.LoadFromFile filePath 101 102 '対象ファイルから1行ずつ読み込む 103 Dim line 104 Dim aryStrings 105 Dim i 106 i = 0 107 Do Until input.EOS 108 line = input.ReadText(-2) 109 redim Preserve dataList(i) 110 dataList(i) = Replace(line, vbCr, "") '改行コード削除(書込時に改行コード付加) 111 i = i + 1 112 Loop 113 114 input.Close 115End Sub 116

追記2

ANSI形式のCSVファイルを読み込めるように、ReadFileプロシージャを変更しました。
出力ファイルの形式もANSI形式になるように変更しました。

変更箇所
①WriteFileANSIプロシージャ追加
②ReadFileプロシージャ変更

VBS

1Option Explicit 2 3'=========== 4' メイン処理 5'=========== 6Dim LineArrM 7Dim LineArrTemp() 8Dim CSV_PATH() 9Dim i 10 11GetFiles "./CSV", CSV_PATH '※フォルダ以下のCSVファイルパスを取得 12For i = 0 To UBound(CSV_PATH) 13 ReadFile CSV_PATH(i), LineArrTemp '※ファイルのデータを配列に格納 14 If i = 0 then 15 LineArrM = LineArrTemp '※1ファイル目 16 Else 17 ListMerge LineArrTemp, LineArrM '※2ファイル目以降は重複をチェックしてマージ 18 End If 19Next 20 21WriteFileANSI "outputText.csv", LineArrM 'ファイル出力(ANSI) 22'WriteFile "outputText.csv", LineArrM 'ファイル出力(UTF-8) 23 24'<メイン処理はここまで> 25 26 27'<以下はSubプロシージャ> 28'======================== 29' ファイル書き込み(UTF-8) 30'======================== 31Sub WriteFile(ByVal outputPath, ByVal arr) 32 Dim output, i 33 Set output = CreateObject("ADODB.Stream") 34 output.Type = 2 35 output.Charset = "UTF-8" 36 output.Open 37 38 for i = 0 To UBound(arr) 39 output.WriteText arr(i), 1 '[0:改行なし 1:改行コード付加] 40 Next 41 output.SaveToFile outputPath, 2 42 output.Close 43End Sub 44 45'======================== 46' ファイル書き込み(ANSI) 47'======================== 48Sub WriteFileANSI(ByVal outputPath, ByVal arr) 49 Dim outputFile, fso 50 Set fso = WScript.CreateObject("Scripting.FileSystemObject") 51 Set outputFile = fso.OpenTextFile(outputPath, 2, True) 52 for i = 0 To UBound(arr) 53 outputFile.WriteLine arr(i) 54 Next 55 56 outputFile.Close 57End Sub 58 59'=================== 60' 重複を削除+マージ 61'=================== 62Sub ListMerge(ByVal arrTemp, ByRef arrM) 63 Dim i,j 64 '※配列Tempで配列Mにない要素だけ配列Mに追加する 65 For i = 0 To UBound(arrTemp) 66 For j = 0 To UBound(arrM) 67 if arrTemp(i) <> arrM(j) then 68 '※配列Mにないものは追加 69 if UBound(arrM) = j then 70 redim Preserve arrM(UBound(arrM) + 1) '配列を+1拡張 71 arrM(UBound(arrM)) = arrTemp(i) 72 End If 73 Else 74 '※配列Mにあるものは追加しない 75 Exit For 76 End If 77 Next 78 Next 79End Sub 80 81'======================== 82' リスト取得プロシージャ 83'======================== 84Sub GetFiles(ByVal folderPath, ByRef fileList) 85 Dim objFileSys 86 Dim objFolder 87 Dim objFile 88 Dim i 89 i = 0 90 91 Set objFileSys = CreateObject("Scripting.FileSystemObject") 92 Set objFolder = objFileSys.GetFolder(folderPath) 93 94 For Each objFile In objFolder.Files 95 '取得したファイルのファイル名を表示 96 redim Preserve fileList(i) 97 fileList(i) = folderPath & "/" & objFile.Name 98 i = i + 1 99 Next 100 101 Set objFolder = Nothing 102 Set objFileSys = Nothing 103End Sub 104 105'================================== 106' CSV読み込みプロシージャ(ANSI専用) 107'================================== 108Sub ReadFile(ByVal filePath, ByRef dataList) 109 Dim fso,i 110 Dim inputFile 111 Set fso = WScript.CreateObject("Scripting.FileSystemObject") 112 Set inputFile = fso.OpenTextFile(filePath, 1, False, 0) 113 i=0 114 Do Until inputFile.AtEndOfStream 115 redim Preserve dataList(i) 116 dataList(i) = inputFile.ReadLine 117 i = i + 1 118 Loop 119 120 inputFile.Close 121End Sub

追記3

CSVファイルのみを対象にする

VBS

1'======================== 2' リスト取得プロシージャ 3'======================== 4Sub GetFiles(ByVal folderPath, ByRef fileList) 5 Dim objFileSys 6 Dim objFolder 7 Dim objFile 8 Dim i 9 i = 0 10 11 Set objFileSys = CreateObject("Scripting.FileSystemObject") 12 Set objFolder = objFileSys.GetFolder(folderPath) 13 14 For Each objFile In objFolder.Files 15 IF objFileSys.GetExtensionName(objFile.Name)="csv" Then 16 '取得したファイルのファイル名を表示 17 redim Preserve fileList(i) 18 fileList(i) = folderPath & "/" & objFile.Name 19 i = i + 1 20 End If 21 Next 22 23 Set objFolder = Nothing 24 Set objFileSys = Nothing 25End Sub

投稿2021/01/05 19:23

編集2021/01/11 13:19
KazuSaka

総合スコア640

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

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

clonoth

2021/01/06 14:52

ご回答ありがとうございます。コードも書いていただき大変ありがとうございます。 csvファイルは2ファイル固定ではなく、0以上で増減します。 「"あるフォルダ内のcsvファイルすべて"を対象とする」という処理にするとどうなりますでしょうか?
KazuSaka

2021/01/06 16:52

回答に追記しました。 複数ファイルを想定した処理を書いてみました。
clonoth

2021/01/09 05:58

追記いただきありがとうございます。 リスト取得プロシージャの Set objFolder = objFileSys.GetFolder(folderPath) のところで「パスが見つかりません」のエラーnなってしまいます。 vbsファイルと同じフォルダに「CSV」を作り 「CSV」フォルダ内にcsvファイルを格納するフォルダ構成で正しいでしょうか?
KazuSaka

2021/01/09 11:21 編集

vbsファイルと同じフォルダに「CSV」を作り 「CSV」フォルダ内にcsvファイルを格納するフォルダ構成で正しいでしょうか? ➡その認識で問題ないです。 Set objFolder = objFileSys.GetFolder(folderPath) のところで「パスが見つかりません」のエラーnなってしまいます。 ➡エラー行の前に「msgbox folderPath」を書いて実行して、folderPathの値を見てみてください。「./CSV」が表示されますよね? ➡あとは、「GetFiles "./CSV", CSV_PATH」の行の相対パス(./CSV)を絶対パスにして実行するとどうなりますか? 例:Cドライブ直下の場合:「GetFiles "C:\CSV", CSV_PATH」 ※パスに日本語が入らないようにしてください
clonoth

2021/01/09 13:01

相対パスだと「./CSV」が表示されました。 絶対パスにしたところ、フォルダパスに日本語が入っているため文字化けしてしまいました。(vbsファイルの文字コードをANSIに変更したところ文字化けせずに表示されました) 追記にて「CSVファイルはUTF-8にしてください」と記入いただいていますが、vbsファイルもcsvファイルもANSIで作成したいのですが可能でしょうか?
KazuSaka

2021/01/09 13:24

VBSファイル(ANSI)、CSVファイル(UTF-8)の組み合わせではプログラムは正常動作しますか? (もともとのCSVファイルがANSIだから、ANSIで読み込みたいってことですよね?) CSVファイル読み込みの部分をANSI用に書き換えれば、ANSI形式を読み込めると思います。 ちょっと作ってみます。
KazuSaka

2021/01/09 14:21

ANSI読み込み用に修正しました。 試してみてください。
clonoth

2021/01/11 06:41

VBSファイル(ANSI)、CSVファイル(UTF-8)の組み合わせではプログラムは正常動作しますか? →エラーにはなりませんでしたが、文字化けされた状態出力されました。  ANSIのcsvでしたら、文字化けせずにかつ、重複が削除されて出力されてるっぽいです。 本当にありがとうございます!
KazuSaka

2021/01/11 07:45

うまくいったようで、良かったです。 お疲れ様でした。
clonoth

2021/01/11 12:28

何度もすみません。 CSVフォルダ内にはcsvファイル以外も存在し 名前に".csv"を含むファイルのみを読み込みたいです。 追記にて、 メイン処理のFor文直下にIF文を追記し GetExtensionNameで拡張子を取得し、"csv"だったら その下の処理に行く。という処理を記載させていただきましたが こちらで問題なさそうでしょうか? ※一応、当方の確認では問題なさそうでしたが  ほかにもっと良い方法があれば教えていただきたいです。
KazuSaka

2021/01/11 12:53

まったく問題ないと思います。 ただリスト取得のところで、フォルダ以下のファイルをすべて取得して配列に入れているので、この段階でcsvファイル以外は除外したほうがシンプルかと思います。(追記3参照)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問