SAK 図書館
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 ビジュアル編資料