CSVファイルの「"」について

このQ&Aのポイント
  • VB6でCSVファイルを読み込む際に、ダブルコーテーションの扱いに問題が生じることがあります。例えば、ダブルコーテーションの中にさらにダブルコーテーションが含まれている場合、1つの項目として正しく読み込むことができません。
  • この問題を解決する方法はありますか?ダブルコーテーションが入った項目を正しく読み込む方法を教えてください。
  • VB6のCSVファイル読み込みにおいて、ダブルコーテーションの扱いについて困っています。ダブルコーテーションの中にさらにダブルコーテーションがある場合、正しく読み込むことができません。解決策を教えてください。
回答を見る
  • ベストアンサー

CSVファイルの「”」について

VB6でCSVファイルを読み込みたいのですが、 以下のような項目だと、1項目として読み込むことができません。 例) AAA,"BBB,CCC,"" """,DDD "BBB,CCC,"" """ を1項目として読み込みたいのですが ダブルコーテーションの括りの中に、更にダブルコーテーションがあると うまくいかないみたいです。 何か方法がありますでしょうか? Open DownLoadFile For Input As #1 Len = 32000 Input #1, rec Do Until EOF(1) 処理1 Loop close #1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

>出力フォーマットを変更する事はできないので、 やはり処理を組み込むしかないようですね。 参考になればよいのですが、サンプルを作成しました。 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)

回答No.6

もう一つのサンプルを作成しました。 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/17068)
回答No.4

カンマの点から、Input#のステートメントに頼れないと思うので Line Input #ステートメントを使って、1行全部を文字列として受け取り、内容にしたがって、後はしたいように、切り出しを、ロジックを工夫してコーディングするより他ないと思う。 そのロジックは、規則性があるのかないのかも、質問に内容が掲示できてないので、判りません。 最悪Input¥ステートメトで指定文字数分受け取り、レコード分解も 自力でになるかも。

回答No.3

どんぴしゃ。とはいかないけど、 エクセルで開いて、セルを読んだら? 規則性はないんでしょ。

回答No.2

例) 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

回答No.1

解決策ではありませんが、、、、 このCSVのフォーマットは、もう確定ですか? というのは、 ・「カンマ」区切り ・文字列を「ダブルコーテーション」で囲む という仕様のCSVであれば、CSVのデータは ・「カンマ」 ・「ダブルコーテーション」 は禁則文字にすることが前提だと思います。 しかし、データとして存在しているからこそこういう問題が発生していると思うので、、、 ※出力フォーマットとして ・「TAB」区切りを利用する ・文字列を""で囲む事をしない というルールに変更が可能であれば、そちらをお勧めしたいです。

ddaaii
質問者

お礼

ありがとうございます。 解決策はありませんか。。。 でも、出力フォーマットを変更する事はできないので、 何か手を考えなければいけない・・・。

関連するQ&A

  • Perlの正規表現について

    Perlの正規表現について質問です. ■質問 aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd eee" aaa bbb ccc ddd eee "fff ggg hhh iii" というような,文字列が書かれているファイルがあるとします. ※ダブルクォーテーションが無い行もあります. ※ダブルクォーテーション内のスペースの数は,行によってそれぞれ異なります. これを,ダブルクォーテーションの中にあるスペースだけ アンダーバーに置換する場合の正規表現を教えて下さい. つまり,下記の出力にしたいです. aaa bbb aaa bbb ccc "ddd" aaa bbb ccc "ddd_eee" aaa bbb ccc ddd eee "fff_ggg_hhh_iii" ■条件 ※ちょっと古いPerlでも動くよう,ゼロ幅肯定/否定後読((?<),(!<))は使わないでください. ※単に実現するだけなら, # cat inputfile | print -pe 'sub f(){}(shift;s/ /_/;return $_;); s/(\".*\")/&f($1)/e;' みたいな感じで置換できそうですが,「正規表現だけで簡単に書けるかどうか」が知りたいのです(正規表現だけで実現出来る場合,そのアルゴリズムを知りたいです).そのため,関数と/eオプションは使わないでください.

    • ベストアンサー
    • Perl
  • Excel VBAでのテキスト出力について

    excel vbaでの文字列出力について エクセルからテキスト(メモ帳とか)に出力したいのですが 下記のように出力できなくて困っております。 どなたか教えてほしいです。 ●入力エクセル AAA BBB CCC DDD EEE セル(1,1)~(1,5)にそれぞれ文字列が入っている状況です。 これを下記のように出力したいのです。 ●テキスト出力 "AAA","BBB",CCC,"DDD",EEE CCCとEEEをダブルクォーテーションを付けないで出力したいのです。 出力の方法でwriteとprintがありますが writeで Write #1, Cells(1,1),Cells(1,2),Cells(1,3),Cells(1,4),Cells(1,5) やると、自動で全ての文字がダブルクォーテーションで囲まれて、カンマが自動でつき "AAA","BBB","CCC","DDD","EEE" のようになってしまします。CCCとEEEのダブルクォーテーションが不要です。 printで Print #1, CStr(Cells(1,1)), & "," CStr(Cells(1,2)), & "," Cells(1,3), & "," CStr(Cells(1,4)), & "," Cells(1,5) とすると "AAA", "BBB", CCC, "DDD", EEE となり、カンマの後ろに空白が何個か入った状態になります。 (ブラウザでは空白が分かりづらいですが、テキストですと入っております。) Trim関数でTrim(",")とか色々試しましたが上手くいきません。 どうしたら望み通りの出力ができるでしょうか。 ぜひ教えて頂きたいです。 よろしくお願いします。

  • CSVに外部テキストファイルを列として追加する方法

    こんにちは。 CSVファイル(base.csv)の先頭列に、別のテキストファイル(add.txt)の中身を新規の列として挿入したいと考えているのですが、よい方法がわかりません。。。 どうのような方法を使えば対応することができるでしょうか? どうぞよろしくお願いいたします。 ■CSVファイル(master.csv) title,developer_name,seller_name,primary_genre_name,application_url AAA,BBB,CCC,DDD,EEE AAA,BBB,CCC,DDD,EEE AAA,BBB,CCC,DDD,EEE AAA,BBB,CCC,DDD,EEE ■テキストファイル(add.txt) id 000 111 222 333 ↓ ■目標としたファイル(master.csv) id,title,developer_name,seller_name,primary_genre_name,application_url 000,AAA,BBB,CCC,DDD,EEE 111,AAA,BBB,CCC,DDD,EEE 222,AAA,BBB,CCC,DDD,EEE 333,AAA,BBB,CCC,DDD,EEE

  • phpのCSVの保存について教えてください

    下記のようにinputタグから値をphpにおくり、csvファイルに保存しようとしています。 値1に12345 値2に67890 値3にあいうえお というように値を送って保存し、csvファイルを開くと、 12345," 67890",あいうえお というように、値2として送ったものの先頭にダブルコーテーションとスペース、最後にダブルコーテーションが勝手に入ってしまいます。なぜ何でしょうか?対処法も含め教えていただければありがたいです。よろしくお願いします。 --------------------html---------------------------------- <form action="send.php" method="post"> 値1:<input type="text" name="aaa" > 値2:<input type="text" name="bbb" > 値3:<input type="text" name="ccc" > <input type="submit" value="送信する"> </form> --------------------php---------------------------------- <?php $val[0] = $_POST['aaa']; $val[1] = $_POST['bbb']; $val[2] = $_POST['ccc']; $fp = fopen("valdata.csv", "a"); fputcsv($fp, $val); fclose($fp); ?>

    • ベストアンサー
    • PHP
  • CSVファイルをAccessに取りこみたい

    以下のような2つのCSVファイルがあるとします。 【hoge1.csv】 aaa,bbb,ccc,ddd 1,2,3,4 【hoge2.csv】 aaa,bbb,ddd,eee,fff 1,2,4,5,6 Accessをあまり使用したことがないので教えていただきたいのですが、 hoge1.csv、hoge2.csvを、以下のような形で Accessの1つのテーブルにインポートする事はできるのでしょうか? ---------------------------- | aaa | bbb | ccc | ddd | eee | fff | | 1 | 2 | 3 | 4 |  |  | | 1 | 2 |  | 4 | 5 | 6 | ---------------------------- ※「aaa」「bbb」…をフィールド名としたいです vb等でプログラムを自作するしかないのでしょうか? 何か良い方法がありましたら教えてください。お願いします。

  • 正規表現で一つ目の区切り文字で区切りたいのですが・・・

    aaa/bbb/ccc/ddd aaa/bbb/ccc/ddd/eee aaa/ccc/ddd $a=~/(.*)\/(.*)/; $1はそれぞれ aaa/bbb/ccc aaa/bbb/ccc/ddd aaa/ccc と成ってしまいます。 このように 「最後の/」で分けられてしまいます。 一つ目の/で分けるにはどうしたらよいでしょうか。

    • ベストアンサー
    • Perl
  • VBAでCSV内にある改行を取る方法

    あるシステムが吐くcsvファイルの項目の中に改行が入っているものがあります。 例) 01,aaa,bbb(改行)bbb,ccc(改行) 02,ddd,eee,fff(改行) 03,ggg(改行)ggg,hhh,iii(改行) このCSVファイルをエクセルのマクロで読み込んでシートに展開したい のですが、項目中にある改行で別レコードを認識してしまいます。 結果) A B C D ---+---+---+--- 01 aaa bbb  bbb ccc 02 ddd eee fff 03 ggg ggg hhh iii これを以下のようにしたいのですが・・・ A B C D ---+------+------+---- 01 aaa bbbbbb ccc 02 ddd eee fff 03 gggggg hhh iii どうやればよいでしょうか? ご教授お願いいたします。

  • ファイルの結合

    UNIX上で下記のようなfileA、fileBから fileA aaa,aaa,222 aaa,bbb,111 aaa,ccc,333 fileB aaa,aaa,111 aaa,bbb,222 aaa,ccc,333 aaa,ddd,999 下記のようなfileCを作ろうとしています。 fileC aaa,aaa,222 aaa,bbb,111 aaa,ccc,333 aaa,ddd,999 そこで、以下のように一列目と2列目をキーにして、sortすることにしました。 cat fileA fileB | sort -u -k1,2 -t, > fileC すると、fileCは下記のようになりました。(一行目の3列目が222ではなく、111になってしまいました) fileC aaa,aaa,111 aaa,bbb,222 aaa,ccc,333 aaa,ddd,999 キー項目以外はfileAを優先させたいのですが、なにか良い方法はないでしょうか?

  • 【エクセル】空セルを埋める方法

    お世話になります。 下記のような表があります。 1行目:AAA,BBB,CCC,DDD 2行目:空セル,BBB,CCC,DDD 3行目:空セル,BBB,CCC,DDD 4行目:aaa,BBB,CCC,DDD 5行目:空セル,BBB,CCC,DDD ・・・ こんなパターンの行が結構あります。 空セル部分を下記のように埋めたいのですが 1行目:AAA,BBB,CCC,DDD 2行目:AAA,BBB,CCC,DDD 3行目:AAA,BBB,CCC,DDD 4行目:aaa,BBB,CCC,DDD 5行目:aaa,BBB,CCC,DDD てっとり早く埋める方法ありませんか? いまは、【ctrl+↓】 ⇒【↑】⇒【ctrl+D】を延々繰り返しています。 宜しくお願いいたします。

  • ''で囲まれていない文字列にマッチする正規表現

    下記のような文字列($str)に対して置換を行い、 my $str = qq{ AAA = BBB - 'CCC' }; $str =~ s/★正規表現★/sprintf("DDD(%s)",$1)/xmsge ; 変換後 $str = DDD(AAA) = DDD(BBB) - 'CCC' ; を実現する★正規表現★を書きたいと思っています。  ・AAA,BBB,CCCは[\w]で構成される文字列です。 ですが、シングルクォーテーション('')で囲まれていない文字列にマッチする正規表現が書けなく困っています。 一度、シングルクォーテーションで囲まれているものも含めて全てDDD()をつけて、そのあとで、シングルクォーテーションを含むものは元に戻すことでやりたいことは実現できているのですが、1行で実現できる方法を探しています。 アドバイスよろしくお願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう