![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
以前同じ質問をさせて頂いたのですが、説明不足であったため再投稿いたします。
【エクセル VBA】
VBAを使って複数のCSVを結合させたいのですが、コンマ区切りの値がデータ上に存在するため上手くまとまりません。
バッチ等でまとめる方法ではなく、どうしてもVBAでやらなければならないので、その方法をご教授下さい。
また、結合するCSVはエクセルを開いた時に選択できるようにしたいです。
(特定のファイル上を対象等では無く。)
現在使用しているVBAは以下のものになります。
-----------------------------------------------------
Sub CsvIn()
'CSVファイルの読み込み
Dim CsvFileName As Variant
Dim Li As String
Dim Bf() As String
Dim R As Long
Dim ShMain As Worksheet
Dim FlNo As Integer
Dim FFlNo As Integer
With ThisWorkbook 'シート&パスの設定
Set ShMain = .Worksheets("Sheet1")
ChDrive .Path
ChDir .Path
End With
'複数のファイルの選択を可に設定
CsvFileName = Application.GetOpenFilename _
(filefilter:="CSVファイル(*.csv),*.csv", _
Title:="CSVファイル選択", MultiSelect:=True)
If VarType(CsvFileName) = vbBoolean Then Exit Sub 'キャンセル時の処置
R = 1 '行の初期値
For FlNo = 1 To UBound(CsvFileName) 'ファイル数分ループ
FFlNo = FreeFile '---使用可能なファイル番号取得
Open CsvFileName(FlNo) For Input As #FFlNo
Do Until EOF(FFlNo) '最終行までループ
Line Input #FFlNo, Li '一行読み込み
Bf = Split(Li, ",") 'カンマで分割し配列に代入
If UBound(Bf) >= 0 Then '空白行の処理を飛ばす
With ShMain '1行分のデータをセルに出力
.Range(.Cells(R, 1), Cells(R, UBound(Bf) + 1)).Value = Bf
End With
End If
R = R + 1
Loop
Close #FFlNo
Next FlNo
End Sub
-----------------------------------------------
参考になりそうなサイト
http://excel-ubara.com/excelvba5/EXCELVBA257.html
よろしくお願いします。
No.14ベストアンサー
- 回答日時:
No.13 に対する補足コメントについて
ですから!
そのダメな所のデータを数行抜き出したものでCSVファイルを作成して実験してみてください。
それでも症状が出るならばその数行のデータを提示してください。
大変申し訳ないのですが、こちらはそちらの状況が見えないので「特段ルールが異なるようなことはございませんでした。」は、あなたが気づかないだけの場合が多いのでそれを提示していただきたいのです。
「同じ列に似た値があると上書かれてしまうということはありませんでしょうか?」については1文字ずつ「"」「,」が有った時だけ特別な作業をしているだけなので考えにくいです。
もしかしての考えられそうなものとして
・文字コードのせいで1つの2バイト文字が「"」や「,」と何かに分解されてしまっている可能性も有るかもしれません。
・1つの行中で「"」が偶数個でないと誤動作する可能性はあります。
・CSVファイルに特殊な制御コードになりそうな文字が含まれている。
・これは故意にしているのですが空白だけの行は削除していますが問題ないですよね?
とにかく、こちらではそちらの状況が見えないので、ダメな状況を具体的に提示していただけないと実験などが出来ないのです。もしも具体的な提示が出来ないのならばそう言ってください。あなたの事は無視するようにします。
よろしくお願いいたします。
No.15
- 回答日時:
こんばんは。
#7で回答した者です。
>消えている部位の元データを見てみたのですが、特段ルールが異なるようなことはございませんでした。
>複数のファイルを読み込んだ際に、一部データが消えてしまっている(または取り込めていない)状態です。
よくあることですが、こういう話には、抜けている部分がいくつかあります。
まず、違うOSから吐き出したCSVの場合があります。取り扱う本人が、その辺りについて気がつかないままに、作成依頼しても、九分九厘失敗します。
ファイルは、SJISのようですが、Windows形式の CRLF 改行でしょうか。そこらが違っていると、うまくいくほうがおかしかったりします。
もうひとつは、特別なバイナリコードや誤動作を起こす外字が混じっている可能性があります。テキスト処理するプログラムは、こういう場合は、とても弱いです。
Excelの場合は、Clean 関数というものがありますが、使えるかどうかは不明です。そもそも、VBAで、Clean 関数に頼ること自体が、プログラミングとしては逸脱しているのですが、これは、プリンターを制御したりする、エスケープシーケンスを取り除くための関数でした。それが、適するかは、こちらからでは分かりません。
消えた部分の元ファイルをバイナリで調べてください、と言って分かるでしょうか。もし無理なら、例えば、メモ帳やテキストエディタで、フルテキストが入るかどうかぐらいは調べられるのではないかと思います。その時に、ファイル情報で、UCS-2 (Unicode), UTF-8, SJIS などをチェックします。こういう場合に、特殊なインポートの仕方があります。ただ、正確な情報がないと作れません。
それと、マクロの仕様全体の問題なのですが、連続してインポートするように考えられているようですが、それを、もう一度、1つずつのファイルを入れて、最後尾にインポートをすることにしてみるとか。
CSV は、Excelのファイルの専売特許のように思われがちですが、実際は、Excelでは、最低限のインポートしかしませんから、不具合そのものはしょうがないのです。
最後に、http://excel-ubara.com/ ではQueryTable(外部データの取り込み) の効用を書いているようです。QueryTable で可能になったら、記録マクロから、実際のVBAプログラムに変える方法もあります。また、CSV エディターのようなものが、フリーソフトであります。CSV の中には、特殊信号が含まれているものがあり、本人は、CSVだと信じ込んでいるのですが、実は違っていることがあります。
余談になりますが、私の、掲示板の10年以上の経験では、今回のような一旦不明のトラブルに陥ったCSVのインポートの成功率は、皆無に近いです。それを阻む原因が、質問者さんが、出力のソース元を明らかにしないのと、データをふつうのCSVだと信じ切っていたりすることです。中には、POSシステムの出力データだったりしたこともありました。昔、九天社というところで、そうした処理技術を公開はしていましたが、それは、質問者側から提示されたものが、明らかに、それに該当するものでなくては無理なのです。
それと、Windowsでは、Windowsの中で使えるUnixツールが現在になると、貧弱で使い物にならないことに気が付きました。それで、私個人は、伝家の宝刀として、NotePad++ (テキストエディタ)を利用することにしています。Excelで、インポートし易いように加工しても良いのではないかと思います。回答者は掃いて捨てるほどいるとは思いがちでしょうが、この種のものは、基本的にはだいたい考えていることは同じですから、イレギュラーな問題を解決するには、それなりに、身を切って公開しなければ無理ということもあります。
No.13
- 回答日時:
まさかとは思いますが、複数ファイルの選択方法が判らないと言う事ではありませんよね?
[Shist]キーや[Ctrl]キーを押しながらクリックして選択するのですが、違いとかも判りますよね?
No.12
- 回答日時:
No.11 に対する補足コメントについて
ダメな例と、どのようにダメな結果になったかを提示していただかないとこちらでは調べようがありません。
ちなみに先ほどの例はそちらではどのようになっているのでしょうか?
No.11
- 回答日時:
No.8 に対する補足コメントについて
こちらで実行したら以下のように問題なさそうに取り込めましたがどんなふうにダメなのかを提示してください。
☆1行目
マシン名
2017/08/02
~情報
K22
4/3/2014
☆2行目
マシン名1
2017/08/02
~情報
SN Tr
Stop
C:\wi\Syst\snp.exe
ユーザ名
☆3行目
マシン名2
2017/08/02
~情報
ehmsas.exe
C:\Wi\win\-win5.exe
Ms Cor
6,1,30,1
Ms Sys
2009/07/14
No.10
- 回答日時:
No.8 のさらに追補
「""」を文字列の区切りではなく「"」の文字として扱う事が多いですが、これはそんなこと考えていません「"」がただ2つあるとして扱います。
No.8
- 回答日時:
チョットしかテストしていませんがお試しください。
-------------------------------------------------------------------------------------------
Sub Sample()
Dim CsvFile As Variant
Dim FileName As Variant
Dim FileNo As Variant
Dim RowData As String
Dim ColumnData As String
Dim RowNo As Long
Dim ColumnNo As Long
Dim Character As Boolean
Dim Position As Long
Cells.Delete Shift:=xlUp
ChDir ThisWorkbook.Path
CsvFile = Application.GetOpenFilename(FileFilter:="CSV ファイル (*.csv),*.csv", MultiSelect:=True)
If IsArray(CsvFile) Then
For Each FileName In CsvFile
FileNo = FreeFile
Open FileName For Input As #FileNo
Do Until EOF(FileNo)
Line Input #FileNo, RowData
RowData = Trim(RowData)
If RowData <> "" Then
RowNo = RowNo + 1
ColumnNo = 1
For Position = 1 To Len(RowData)
If Mid(RowData, Position, 1) = Chr(34) Then
Character = Not Character
If Character Then ColumnData = Chr(39)
Else
If Mid(RowData, Position, 1) = Chr(44) Then
If Character Then
ColumnData = ColumnData & Mid(RowData, Position, 1)
Else
Cells(RowNo, ColumnNo).Value = ColumnData
ColumnData = ""
ColumnNo = ColumnNo + 1
End If
Else
ColumnData = ColumnData & Mid(RowData, Position, 1)
End If
End If
Next
Cells(RowNo, ColumnNo).Value = ColumnData
ColumnData = ""
ColumnNo = 0
End If
Loop
Close #FileNo
Next
End If
End Sub
-------------------------------------------------------------------------------------------
※ 一度保存してから実行してください。
No.7
- 回答日時:
こんばんは。
この前から書かれている「データ内」という意味がやっと分かりました。
私は、てっきり途中から、CSV が始まるものだと思いました。
文字列内という意味だったのですね。
叩き台として、このコードを出しておきます。
'//標準モジュール
Sub CsvImport()
'CSVファイルの読み込み
Dim CsvFileNames As Variant
Dim txtLine As String
Dim Bf() As String
Dim lastRow As Long
Dim Sh As Worksheet
Dim FlNo As Integer
Dim i As Long, f As Variant
With ThisWorkbook 'シート&パスの設定
Set Sh = .ActiveSheet
ChDrive .Path
ChDir .Path
End With
'複数のファイルの選択を可に設定
CsvFileNames = Application.GetOpenFilename _
(filefilter:="CSVファイル(*.csv),*.csv", _
Title:="CSVファイル選択", MultiSelect:=True)
If VarType(CsvFileNames) = vbBoolean Then Exit Sub 'キャンセル時の処置
lastRow = Cells(Rows.Count, 1).End(xlUp).Row + 1 '行の初期値
i = i + lastRow
For Each f In CsvFileNames 'ファイル数分ループ
FlNo = FreeFile()
Open f For Input As #FlNo
Do Until EOF(FlNo) '最終行までループ
Line Input #FlNo, txtLine '一行読み込み
If Len(Trim(txtLine)) > 0 Then
If InStr(1, txtLine, """") > 0 Then
txtLine = REReplace(txtLine)
End If
Bf = Split(txtLine, ",") 'カンマで分割し配列に代入
With Sh '1行分のデータをセルに出力
.Cells(i, 1).Resize(, UBound(Bf) + 1).Value = Bf
End With
End If
i = i + 1
Loop
Close #FlNo
Next
End Sub
Function REReplace(enter_text)
Dim RegEx As Object
Dim Ms
Set RegEx = CreateObject("VBScript.RegExp")
Dim ret As String, rep As String
With RegEx
.Global = True: .IgnoreCase = False: .MultiLine = True
.Pattern = "("".*,.*"")"
Set Ms = .Execute(enter_text)
End With
ret = Ms(0).SubMatches(0)
rep = Replace(ret, ",", "")
rep = Replace(rep, """", "")
REReplace = Replace(enter_text, ret, rep)
End Function
No.6
- 回答日時:
No.6 の追加(以下も考えられますね)
例 1-3:「123,45,"678,90"」→「123」「45」「"678,90"」
例 1-4:「123,45,"678,90"」→「123」「45」「678,90」
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数のCSVファイルを横に並べて...
-
VBAでCSVの1行目だけを書き換え...
-
エクセルの指数を無効にしたい
-
CSVファイルの結合(重複データ...
-
二つのCSVファイルを照らし合わ...
-
EXCELにcsv形式の外部データを...
-
excelインポート時の「実行時エ...
-
フォルダ内の全ブックのシート...
-
複数のデータ系列の線の太さを...
-
エクセル終了時の保存確認メッ...
-
VBA[Private Sub]のコードをシ...
-
ExcelVBAで今開いているユーザ...
-
最初の1回のみにボタンクリッ...
-
エラー内容が分かりません
-
Excelのラジオボタンにチェック...
-
Excelマクロ ファイル名が変わ...
-
エクセル2010 Shapeをクリップ...
-
Excelファイルがxslからxslmに??
-
エクセル2007 テキストボ...
-
vbsで、フォルダ内にあるcsvフ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルの指数を無効にしたい
-
複数のCSVファイルを横に並べて...
-
excelインポート時の「実行時エ...
-
「ほかのアプリケーションを無...
-
VBAでCSVの1行目だけを書き換え...
-
EXCELにcsv形式の外部データを...
-
大量のCSVデータを1つのエ...
-
複数のcsvファイルを1つのEXCEL...
-
Excel VBAを使った複数のCSVフ...
-
CSVファイルの結合(重複データ...
-
二つのCSVファイルを照らし合わ...
-
datファイル→csvファイル→datフ...
-
【VBA初心者】同じフォルダ内の...
-
同じ形のCSVファイルを複数同時...
-
EXCELLの動きが遅い
-
CSVファイルを読み込んだときに...
-
VBAでユーザーフォーム上に参照...
-
エクセル2003 CSVファイルの取...
-
複数の同じ様式のエクセルデー...
-
エクセルでcsvデータを自動読み...
おすすめ情報
問題点:
文字列にコンマが入っている場合がある(ここではあるセル上のバージョン情報が12,3,0,0のように表示されている)ため、CSVをエクセルに取り込んだ際に12、3、0、0と区切られてしまいます。
これをVBAで文字列内のコンマを削除するという処理を追加できればと思っています。
例を挙げると以下のサイトに似たことが書いてあります。
http://pasonal.com/vba-partition/
Copyコマンドを使用し、ただ単にCSVファイルを結合しておりました。
CSVを結合した後に、決まった作業があるのですが、なるべく一つのファイル(Excel)で全ての作業を完結させたいと考えておりますので、どうしてもVBAでCSVの結合も行いたいと考えております。
私の説明不足&知識不足で困惑させてしまい申し訳ありません。
イメージしている順序は
1、VBAを含むエクセルを起動(現在作成しようとしているもの)
2、結合したいCSVファイルを選択
3、エクセルにCSVデータが取り込まれる
4、普段行っている決まった作業を行う(ここもVBAでするつもりですが、ここに関しては何とかなりそうです)
5、VBAで行えない作業を手動で行う
6、保存
になります。
そのため、ファイル名は保存する際に自由に決められるようにします。
よろしくお願いします。
列によって場合分けをする感じではなく、
基本的にデータ内(セル内)にコンマがある場合はすべて無視したいです。
(エクセル側がコンマをセルの区切り目と捉えてしまうため)
例えは、捕捉で張らせていただいたリンク先にあります。
説明が下手で申し訳ありません。
①で間違いありません。
---------------------
①「"」で囲まれた中にある物は文字列として扱い、その中にある「,」は区切り記号としてはつかわないが、それ以外の「,」は区切り記号として扱う。
例 1-1:「123,45,"678,90"」→「123」「45」「"67890"」
例 1-2:「123,45,"678,90"」→「123」「45」「67890」
----------------------
わかりやすい質問ありがとうございます
GooUserラックさん、Windfallerさん
ご回答有り難うございました。大変感謝しております。
特にラックさんは分かりやすい質問を何度も投げ掛けてくださり、助かりました。
明日試し、結果を報告させていただきます。
コンマ区切りの値も問題なく取り込むことができました。
しかし、ファイルを結合した際に、一部のデータが消えてしまっているみたいです。
大変申し訳なくは思うのですが、原因が私にはわからない状態です。
ファイルを見せることができれば早いのですが、一部機密情報がふくまれているため、元データを変換して一部を張り付けさせて頂きます。 何か分かられれば幸いです。
"マシン名","2017/08/02","~情報","K22","4/3/2014"
"マシン名1","2017/08/02","~情報","SN Tr","Stop","C:\wi\Syst\snp.exe","ユーザ名"
"マシン名2","2017/08/02","~情報","ehmsas.exe","C:\Wi\win\-win5.exe","Ms Cor","6,1,30,1","Ms Sys","2009/07/14"
複数のファイルを読み込んだ際に、一部データが消えてしまっている(または取り込めていない)状態です。
データの一部は、何かデータが取り込めていない理由に関連しているかと思い張り付けさせて頂きました。
ご迷惑をおかけします..
もし難しそうでしたら、元ファイルのカンマを置換する→取り込む
手順も考えております。
返答が遅くなり申し訳ありませんでした。
複数選択の方法は分かりますが、複数ファイルを取り込んだ際に、一部のデータが消えてしまっている(または取り込めていない)状態です。
同じ列に似た値があると上書かれてしまうということはありませんでしょうか?
また消えている部位の元データを見てみたのですが、特段ルールが異なるようなことはございませんでした。
補足ですが、データ量は結構多くまとめた際に2万行程になります。