CSVファイルの中のある文字列の突合処理をするには?


VB初心者  2006-03-29 05:44:17  No: 94806

VBに関して、まったくの初心者ですので、簡単な内容だと思いますが、
どなたかご教授願います。

VB6.0で例えば以下に示すようなCSVファイルがあるとします。
  "aaa","abc","",""
  "bbb","def","",""
  "ccc","ghi","",""
  "aaa","","jkl",""
  "bbb","","mno",""
  "ccc","","pqr",""
  "aaa","","","stu"
  "bbb","","","vwx"
  "ccc","","","yzz"

このファイルを1行目から順に読み込み、1列目の文字列をキーとして突合処理を行ない、下記のようなファイルで出力したい場合、どのようにコーディングすればよろしいでしょうか?

【出力したいCSVファイル内容】
  "aaa","abc","jkl","stu"
  "bbb","def","mno","vwx"
  "ccc","ghi","pqr","yzz"

一応、私なりにDo関数や配列等を用いてプログラムを組んでみましたが、
うまくいきませんでしたので・・・。


魔界の仮面弁士  2006-03-29 06:22:55  No: 94807

私なら、Dictionary を使って管理しますね。

> 一応、私なりにDo関数や配列等を用いてプログラムを組んでみましたが、
Do は関数ではなく、ステートメントです。

という突っ込みはさておき、配列でも組めない事は無いはずなので、
うまくいかなかったというプログラムを見せてもらえないでしょうか。


VB初心者  2006-03-29 06:58:41  No: 94808

早速ありがとうございます。
どのようにして"aaa"や"bbb"や"ccc"をキーとして突合処理をすれば
よいのかがさっぱり分かりません。

一応、以下に示すようにして作ってみましたが、分からない箇所が
多すぎまして・・・。

Private Sub SAMPLE_REC()
    
    Dim strAAA(9) As String
    Dim strBBB(9) As String
    Dim strCCC(9) As String
    Dim strDDD(9) As String
    Dim I As Long, j As Long         '添字   
    Dim intFileNo1 As Integer  'ファイル番号
    Dim intFileNo2 As Integer  'ファイル番号
    
    intFileNo1 = FreeFile
    Open C:\TEMP\SAMPLEIN.CSV For Input As #intFileNo1
    intFileNo2 = FreeFile
    Open C:\TEMP\SAMPLEOUT.CSV For Output As #intFileNo2
    
    Do While Not EOF(intFileNo1)     
        I = 0
        '配列のクリア
        For j = 0 To 9
            strAAA(j) = ""
            strBBB(j) = ""
            strCCC(j) = ""
            strDDD(j) = ""
        Next j

        Input #intFileNo1, strWWW, strXXX, strYYY, strZZZ

        strAAA(I) = strWWW
        strBBB(I) = strXXX
        strCCC(I) = strYYY
        strDDD(I) = strZZZ
  (このあたりもこの書き方でいいのか分からない)
        I = I + 1
    LOOP
        (このあたりの書き方もよく分からなくて・・・)

    Close intFileNo1
    Close intFileNo2
End Sub

こんな感じですが・・・。宜しくお願い致します。


魔界の仮面弁士  2006-03-29 13:13:35  No: 94809

> 以下に示すようなCSVファイルがあるとします。
ひとつ注意事項を。

Input ステートメントは、CSV を読み込むための命令ではありませんので、
CSV ファイルの形式によっては、正常に読めない場合もあります。元のデータ形式が、
Input ステートメントに対応した物である事がわかっている場合のみ使用してください。

--------
さて…本題に入る前に、幾つか前提条件の確認をさせてください。

(1) 元となるデータですが、提示されたサンプルでは、「9行4列」となっていますが、
    この行数は、常に 9行なのでしょうか? それとも可変なのでしょうか?

(2) 『Dim strAAA(9) As String』というコードがありましたが、これの意味としては、
    strAAA(0)〜strAAA(9)までの、「10個の要素を持つ一次元配列」を定義している事に
    なるわけですが…今回、要素数を「10」にした事について、何か理由がありますか?

(3) 突然、CSVファイルが 2つ登場してきたようですが、これらは、SAMPLEIN.CSV が
    元データとなり、それらの突合結果を SAMPLEOUT.CSV として出力させようと
    しているのでしょうか?

(4) 最初に例示した CSV データの場合、最終的には、今回用意した strAAA(9) などの
    配列の中身が、どのようになって欲しかったのでしょうか?

---------
> (このあたりの書き方もよく分からなくて・・・)
これは、処理の手順(ロジック)が想像できない、という意味でしょうか?
それとも、ロジックは思いついたが、それを VB という言語にて
表現する事ができない、という意味でしょうか?

ちなみに私なら、最終結果となる
  "aaa","abc","jkl","stu"
  "bbb","def","mno","vwx"
  "ccc","ghi","pqr","yzz"
を格納するために、それらを『Dictionary』を使って保持するか、
または、『二次元配列』を使って保持するようにすると思います。

たとえばDictionary を使って管理した場合には、上記の結果は、
  dict("aaa")(0) = "abc"
  dict("aaa")(1) = "jkl"
  dict("aaa")(2) = "stu"
  dict("bbb")(0) = "def"
  dict("bbb")(1) = "mno"
        :
などのようなイメージで管理する事ができるでしょうし、あるいは、
二次元配列をつかって管理していた場合には、
  matrix(0, 0) = "aaa"
  matrix(0, 1) = "abc"
  matrix(0, 2) = "jkl"
  matrix(0, 3) = "stu"
  matrix(1, 0) = "bbb"
  matrix(1, 1) = "def"
  matrix(1, 2) = "mno"
        :
などのような管理方法が可能です。

そして、二次元配列を使うにしろ、Dictionaryを使うにしろ、
今回のケースでいえば、その処理ロジックは、

  1. (必要であれば)配列等のクリアを行う。
  2. 入力CSVを開く。

  3. 先頭行のデータを読み込む(ここから、ループ処理の開始)
  4. "aaa","abc","","" というデータが読み込まれるので、"aaa" をキーとみなす。
  5. 既に "aaa" のキーを格納済みか調べる → 見つからないので、"aaa" を新規に登録。
  6. その行にある "abc" というデータを、"aaa" のキーと一緒に格納する。

  7. 2行目のデータを読み込む(ループ処理の2回目)
  8. "bbb","def","","" というデータが読み込まれるので、"bbb" をキーとみなす。
  9. 配列内に "bbb" のキーを格納済みか調べる → 見つからないので、"bbb" を新規に登録。
  10. その行にある "def" というデータを、"bbb" のキーと一緒に格納する。

  11. 以下同様に、3行目のデータも配列に保存していく。

  12. 4行目のデータを読み込む(ループ処理の4回目)
  13. "aaa","","jkl","" というデータを読み込み、"aaa" をキーとみなす。
  14. 配列内に "bbb" のキーを格納済みか調べる → 発見したので、その配列位置を取得。
  15. そこで得た配列位置を元に、格納済みの("bbb")キーの内容に、"jkl" という情報を加える。

  16. 同様に、5行目〜9行目の読み込みと、キーの格納済み確認、情報の更新/新規登録を繰り返す。

  17. 最終行まで読み終わった時点で、ループ完了。これにて突合処理も完了。
  18. あとは、できあがった配列の中身を取り出していくだけ。

のような感じで処理されるように作れば、多分、うまくいくかと。

で、こうした突合処理として最も重要なのは、上記の『キーが既に格納済みか調べる』という部分の処理ですよね。

この時、キーを「配列」に格納しているのだとすれば、そのキーが、既に取得済みのものか
どうかを調べるために、さらなるループ処理を書かなければならないと思います。

ですが、先に書いた「Dictionary」という物を使えば、
  If Dict.Exists("bbb") Then
    '既に bbb というキーを登録済み
  Else
    'まだ bbb というキーは登録されていない
  End If
のように、「Exists メソッド」を使うだけで簡単に判定できるので、難易度を
下げる事ができるかも知れません。

Dictionary の使用方法は、ヘルプに書かれていますので、一度検討してみては如何でしょう。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加