SAK 図書館

SAK Streets メインストリート 図書館・カフェ 一覧 SAK Streets 検索
| VB | SQL | Perl | PHP | ASP | JSP | C | PC | HP | FAQ | フリーソフト |

VB テクニック編33 - シーケンシャルマッチング、シーケンシャルマージ処理

■SAK 関数利用規程

  ・テクニック編で紹介する関数は、私こと Y.SAK の開発関数である。
  ・著作権明示部分の改編は認めない。
  ・個人、企業がこれらの関数を使用したり、一部を使用して新たなシステムや
    プログラムを開発することは自由です。
  ・但し、これらの関数を一部でも使用しているソフトウェアをシェアウェア、
    その他有償プロダクトとして配布・販売するには、私の許可が必要です。
    (無償のフリーソフトウェアなら、自由に配布しても良い。)
  ・これらの関数を使用して発生した、いかなる形での損害も私こと Y.SAK は
    賠償しません。

■シーケンシャルマッチング、シーケンシャルマージ処理

  ・二つの DB テーブル、二つの CSV ファイル、DB テーブルと CSV ファイル
    などのシーケンシャルマッチングやシーケンシャルマージは、次のように
    処理する。(DB テーブルマッチング、DB テーブルマージ処理)

  ・シーケンシャルマッチングは二つのファイルの件数が大量にある場合に効果
    を発揮する。(ランダム参照マッチングより超高速となる。)
    以下の例では、DB テーブルと CSV ファイルのレコードをマッチングして
    いるが、どちらかのリードロジックを他方に適用すれば、DB テーブル同士、
    または、CSV ファイル同士のマッチング処理が可能となる。
    DB は ADO でコードしているが、oo4o でも似た感じである。

  ・マッチングする二つのファイルのレコード順は、マッチングキーの順に
    ソートされていなければならない。マッチングキー順に並んでいない CSV
    ファイルの場合、ファイルソートロジックも必要になる。
    (手っ取り早く、DB テーブルにセットアップしても良いが。)

  ・マッチングキーは、処理判定の簡素化のため、文字列に変換してセットする。
    得意先CD が数値の場合は、mk2.tkcd = format(rec(3), "0000") のように
    桁揃えもすること。
    以下の例では、3 つの項目をマッチングキーとしているが、受注m の場合、
    実は受注番号でユニークとなるので、マッチングキーはひとつで良い。
    見本と言う意味で意味のない複数キーマッチを行っている。
    また、AT END 時のマッチングキーには最大キーとなるデータをセットする。
    この例では、chr(255) をセットしている。(半角の最大コード)

  ・CSV ファイルには見出し行はないものとして処理している。

  ・イニシャルリードフラグ rsnx は、DB がオープンと同時に 1 件目読まれる
    ので、その制御を行っている。

  ・実際のマッチング処理は、「'** マッチング or マージ」の
      '共にレコードにあるときの処理
      'DB レコードが CSV レコードにないときの処理
      'CSV レコードが DB レコードにないときの処理
    に記述する。
    ここにどのようなコードを書くかで、レコードマージになったり、マッチン
    グレコード抽出になったりする。
    この三つの判定は、一致する条件が多いものを上に持ってくる方が処理は
    速くなる。(微々たる速度差かもしれないが。)

  ・サンプルなのでエラー処理は行っていない。

Private Sub Command1_Click()

  Dim s3cn_ado As Variant
  Dim rs As Variant
  Dim fno As Integer
  Dim ct As Integer
  Dim i As Integer
  Dim mk1 As MATCH_KEY
  Dim mk2 As MATCH_KEY
  Dim mk1s As String
  Dim mk2s As String
  Dim rsnx As Boolean

'** ODBC 接続
  Set s3cn_ado = CreateObject("ADODB.Connection")
  s3cn_ado.Open "dsn=SAK3_ADO;uid=SAK;pwd=SAK"
  s3cn_ado.CursorLocation = 2  'adUseServer = 2

'** レコードセットオープン
  Set rs = s3cn_ado.Execute("select * from 受注m " _
    & " order by 受注番号, 得意先CD, 品番")

'** CSV 項目数取得
  ct = GetCntCSV("infile.csv")
  If ct < 1 Then
    MsgBox "エラー"
    End
  End If
  ct = ct - 1  '添字を rs と同じ開始 0 にする
  ReDim rec(ct) As String

'** ファイルオープン
  fno = FreeFile
  Open "infile.csv" For Input As fno Len = 32000

'** イニシャルリードフラグセット
  rsnx = False

'** DB イニシャルリード
  mk1s = NextReadMk1(rsnx, rs, fno, ct, rec(), mk1, mk2)

'** CSV イニシャルリード
  mk2s = NextReadMk2(rsnx, rs, fno, ct, rec(), mk1, mk2)

'** イニシャルリードフラグセット
  rsnx = True

'** マッチング or マージ
  Do Until rs.EOF And EOF(fno)
    Select Case True
      Case mk1s = mk2s
        '共にレコードにあるときの処理
        print "mk1s = mk2s - " & mk1s & " - " & mk2s
        '...

        '次のマッチリード
        mk1s = NextReadMk1(rsnx, rs, fno, ct, rec(), mk1, mk2)
        mk2s = NextReadMk2(rsnx, rs, fno, ct, rec(), mk1, mk2)
      Case mk1s < mk2s
        'DB レコードが CSV レコードにないときの処理
        print "mk1s < mk2s - " & mk1s & " - " & mk2s
        '...

        '次のマッチリード
        mk1s = NextReadMk1(rsnx, rs, fno, ct, rec(), mk1, mk2)
      Case mk1s > mk2s
        'CSV レコードが DB レコードにないときの処理
        print "mk1s > mk2s - " & mk1s & " - " & mk2s
        '...

        '次のマッチリード
        mk2s = NextReadMk2(rsnx, rs, fno, ct, rec(), mk1, mk2)
    End Select
  Loop

'** ファイルクローズ
  Close fno

'** レコードセットクローズ
  rs.Close

'** ODBC 接続解除
  s3cn_ado.Close

'** 処理終了
  MsgBox "処理終了"

End Sub

'** マッチングキーパターン(標準モジュールで定義)
  Type MATCH_KEY
    jcno As String * 10
    tkcd As String * 4
    prno As String * 16
  End Type

Public Function NextReadMk1(rsnx As Boolean, rs As Variant, fno As Integer, ct As Integer, rec() As String, mk1 As MATCH_KEY, mk2 As MATCH_KEY) As String

'** 次のレコードを読む
  If rsnx Then rs.movenext

'** マッチングキーセット
  If rs.EOF Then
    mk1.jcno = String(10, chr(255))
    mk1.tkcd = String(4 , chr(255))
    mk1.prno = String(16, chr(255))
  Else
    mk1.jcno = rs("受注番号")
    mk1.tkcd = rs("得意先CD")
    mk1.prno = rs("品番")
  End If

'** 正常終了セット
  NextReadMk1 = mk1.jcno & mk1.tkcd & mk1.prno

End Function

Public Function NextReadMk2(rsnx As Boolean, rs As Variant, fno As Integer, ct As Integer, rec() As String, mk1 As MATCH_KEY, mk2 As MATCH_KEY) As String

  Dim i As Integer

'** マッチングキーセット
  If EOF(fno) Then
    mk2.jcno = String(10, chr(255))
    mk2.tkcd = String(4 , chr(255))
    mk2.prno = String(16, chr(255))
  Else
   '** 次のレコードを読む
    For i = 0 To ct
      Input #fno, rec(i)
    Next
    mk2.jcno = rec(0)
    mk2.tkcd = rec(3)
    mk2.prno = rec(1)
  End If

'** 正常終了セット
  NextReadMk2 = mk2.jcno & mk2.tkcd & mk2.prno

End Function

■VB テクニック編資料
■VB 入門編資料
■VB 基礎編資料
■VB ビジュアル編資料
| VB | SQL | Perl | PHP | ASP | JSP | C | PC | HP | FAQ | フリーソフト |

SAK Streets メインストリート 図書館・カフェ 一覧 SAK Streets 検索



Copyright (C) 1999-2017 Y.SAK