- ベストアンサー
CSVファイルの「"」について
- VB6でCSVファイルを読み込む際に、ダブルコーテーションの扱いに問題が生じることがあります。例えば、ダブルコーテーションの中にさらにダブルコーテーションが含まれている場合、1つの項目として正しく読み込むことができません。
- この問題を解決する方法はありますか?ダブルコーテーションが入った項目を正しく読み込む方法を教えてください。
- VB6のCSVファイル読み込みにおいて、ダブルコーテーションの扱いについて困っています。ダブルコーテーションの中にさらにダブルコーテーションがある場合、正しく読み込むことができません。解決策を教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>出力フォーマットを変更する事はできないので、 やはり処理を組み込むしかないようですね。 参考になればよいのですが、サンプルを作成しました。 ExcelのVBAで動いたので多分大丈夫だとは思うのですが、、、 ダメっぽかったらそちらで修正して^^; Option Explicit Public Const DEF_CHR34 As String = """" 'ダブルコーテーション Public Const DEF_SPLIT_CHAR As String = "," '区切り文字 Sub Main() Dim l_strバッファ As String Dim l_str一行 As String Dim l_strAryバッファ() As String Dim i As Integer Dim l_strAry一行() As String 'ファイルを一気に読み込む l_strバッファ = ファイル読込み("C:\test.csv") '改行コードで配列化を行う l_strAryバッファ = Split(l_strバッファ, vbCrLf) '改行数のループ処理を行う For i = LBound(l_strAryバッファ) To UBound(l_strAryバッファ) l_str一行 = l_strAryバッファ(i) Debug.Print l_str一行 '文字が存在していなければ、ループを抜ける If RTrim$(l_str一行) = "" Then MsgBox i + 1 & "行目が空データなので、ループをぬける" Stop Exit For End If Stop '一行を区切り文字で配列化する If Not 変換_ライン_配列(l_str一行, l_strAry一行, DEF_SPLIT_CHAR) Then MsgBox "えらー終了" Stop Exit For End If Stop Next i End Sub Public Function ファイル読込み(ByVal p_strファイル名 As String) As String Dim intFile As Integer Dim lngLen As Long Dim bytBuff() As Byte intFile = FreeFile lngLen = FileLen(p_strファイル名) If lngLen = 0 Then Exit Function End If ReDim bytBuff(0 To lngLen - 1) Open p_strファイル名 For Binary Access Read As intFile Get intFile, , bytBuff Close intFile ファイル読込み = StrConv(bytBuff, vbUnicode) End Function '文字列を、指定の区切りキャラで、配列化を行う Public Function 変換_ライン_配列( _ ByVal p_str一行 As String, _ ByRef p_strAry一行() As String, _ Optional ByVal p_str区切 As String = "," _ ) As Boolean Dim l_bln実行結果 As Boolean Dim l_strAry区切() As String Dim l_str文字列 As String Dim i As Integer Dim l_intカウント取得数 As Integer Dim l_strAry返却() As String l_bln実行結果 = True '区切り文字で配列化する l_strAry区切 = Split(p_str一行, p_str区切) '配列要素数でループを行う For i = LBound(l_strAry区切) To UBound(l_strAry区切) '取得する If Not 補正取得(l_strAry区切, i, l_str文字列, p_str区切) Then 'エラー処理 l_bln実行結果 = False Exit For End If '取得した文字列を、配列として記憶する ReDim Preserve l_strAry返却(l_intカウント取得数) l_strAry返却(l_intカウント取得数) = l_str文字列 l_intカウント取得数 = l_intカウント取得数 + 1 Next i '記憶した配列を返却する p_strAry一行 = l_strAry返却 '取得結果のステータスを返却する 変換_ライン_配列 = l_bln実行結果 End Function Private Function 補正取得( _ ByRef p_strAry区切() As String, _ ByRef p_int開始位置 As Integer, _ ByRef p_str取得文字 As String, _ ByVal p_str区切 As String _ ) As Boolean Dim l_bln実行結果 As Boolean Dim i As Integer Dim l_str文字 As String Dim l_strAryChr34() As String Dim l_intカウントChr34 As Integer Dim l_str文字連結 As String l_str文字 = p_strAry区切(p_int開始位置) If Left$(l_str文字, 1) = DEF_CHR34 Then 'ダブルコーテーションで文字列が始まる場合 For i = p_int開始位置 To UBound(p_strAry区切) l_str文字 = p_strAry区切(i) '初回のループでなければ、区切りキャラを追加する If i <> p_int開始位置 Then l_str文字連結 = l_str文字連結 & p_str区切 End If '文字列の連結を行う l_str文字連結 = l_str文字連結 & l_str文字 '内部に存在するダブルコーテーションの数を取得する l_strAryChr34 = Split(l_str文字, DEF_CHR34) l_intカウントChr34 = l_intカウントChr34 + UBound(l_strAryChr34) '一番右の文字がダブルコーテーションである 且つ ダブルコーテーションのカウントが偶数である If (Right$(l_str文字, 1) = DEF_CHR34) And ((l_intカウントChr34 Mod 2) = 0) Then '先頭と最後のダブルコーテーションを抹消 p_str取得文字 = Mid$(l_str文字連結, 2, Len(l_str文字連結) - 2) '呼び出し元のループカウンタのポジションを進める p_int開始位置 = i '正常処理であることを通知 l_bln実行結果 = True Exit For End If Next i Else 'ダブルコーテーションで文字列が始まらない場合 '取得した値をそのままセット p_str取得文字 = l_str文字 '正常処理であることを通知 l_bln実行結果 = True End If '取得結果のステータスを返却する 補正取得 = l_bln実行結果 End Function
その他の回答 (5)
- 1050 円(@1050YEN)
- ベストアンサー率69% (477/687)
もう一つのサンプルを作成しました。 OLEDBドライバ+ADOでのサンプルです。 OLEDBがテキストに対応していたら、テキストをデータセットとして取得することも出来ます。 おそらくテキストの拡張子が txt csv tab asc であれば可能だと思います。 Public Const DEF_CHR34 As String = """" 'ダブルコーテーション Sub テスト() Dim l_adoRec As Object 'ADODB.Recordset Dim l_adoFld As Object 'ADODB.Field Dim i As Integer Dim l_intCount As Integer Set l_adoRec = GetAdoRecordSet("C:\test.asc", False) Do Until l_adoRec.EOF l_intCount = l_intCount + 1 If IsNull(l_adoRec.Fields(0)) Then Debug.Print l_intCount & "件目の先頭が未設定なので、処理を抜けました" Exit Do End If Debug.Print String(15, "-") Debug.Print l_intCount & "件目" Debug.Print String(15, "-") For Each l_adoFld In l_adoRec.Fields 'ADOの仕様で、ダブルコーテーション2個は1個に置き換えられるので、それを戻す処理も同時に行う Debug.Print Replace(l_adoFld.Value, DEF_CHR34, String(2, DEF_CHR34)) Next l_adoRec.MoveNext Loop End Sub Private Function GetAdoRecordSet(ByVal p_strPath As String, p_bln先頭がヘッダ項目 As Boolean) As Object Dim l_adoCnn As Object 'ADODB.Connection Dim l_strCnn As String Dim l_strSQL As String Dim l_fsoFile As Object 'Scripting.File Dim l_strヘッダオプション As String 'テキストの先頭がヘッダを含むかどうかの設定 If p_bln先頭がヘッダ項目 Then l_strヘッダオプション = "YES" Else l_strヘッダオプション = "NO" End If 'ファイルを取得する Set l_fsoFile = GetFsoFileObject(p_strPath) 'コネクションオープン Set l_adoCnn = CreateObject("ADODB.Connection") l_strCnn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _ & l_fsoFile.ParentFolder.Path _ & ";Extended Properties=""Text;HDR=" & l_strヘッダオプション & """" l_adoCnn.Open l_strCnn 'レコードセットを取得 l_strSQL = "SELECT * FROM [" & l_fsoFile.Name & "]" Set GetAdoRecordSet = l_adoCnn.Execute(l_strSQL) End Function Private Function GetFsoFileObject(ByVal p_strPath As String) As Object Set GetFsoFileObject = CreateObject("Scripting.FileSystemObject").GetFile(p_strPath) End Function
- imogasi
- ベストアンサー率27% (4737/17069)
カンマの点から、Input#のステートメントに頼れないと思うので Line Input #ステートメントを使って、1行全部を文字列として受け取り、内容にしたがって、後はしたいように、切り出しを、ロジックを工夫してコーディングするより他ないと思う。 そのロジックは、規則性があるのかないのかも、質問に内容が掲示できてないので、判りません。 最悪Input¥ステートメトで指定文字数分受け取り、レコード分解も 自力でになるかも。
- otto0001otto
- ベストアンサー率25% (64/249)
どんぴしゃ。とはいかないけど、 エクセルで開いて、セルを読んだら? 規則性はないんでしょ。
- Hayashi_Trek
- ベストアンサー率44% (366/818)
例) AAA,"BBB,CCC,"" """,DDD を読み込んだときどのような結果を希望しているのでしょうか? 2つ連続するダブルクォーテーションはデータのダブルクォーテーションとみなす というルールなら、左側から1文字ずつ読んで 項目1=AAA 項目2=BBB,CCC," " 項目3=DDD ということになると思います。 項目分けは自力で行うしかないでしょう。 Open DownLoadFile For Input As #1 Len = 32000 Do Until EOF(1) Line Input #1, rec recを先頭から1文字ずつ見て項目分けする処理 処理1 Loop close #1
- 1050 円(@1050YEN)
- ベストアンサー率69% (477/687)
解決策ではありませんが、、、、 このCSVのフォーマットは、もう確定ですか? というのは、 ・「カンマ」区切り ・文字列を「ダブルコーテーション」で囲む という仕様のCSVであれば、CSVのデータは ・「カンマ」 ・「ダブルコーテーション」 は禁則文字にすることが前提だと思います。 しかし、データとして存在しているからこそこういう問題が発生していると思うので、、、 ※出力フォーマットとして ・「TAB」区切りを利用する ・文字列を""で囲む事をしない というルールに変更が可能であれば、そちらをお勧めしたいです。
お礼
ありがとうございます。 解決策はありませんか。。。 でも、出力フォーマットを変更する事はできないので、 何か手を考えなければいけない・・・。