Seek関数を使いこなすには

解決


umebaind  2005-02-03 05:13:23  No: 119399

始めまして、UMEBAINDといいます。
VBAは初心者なもので教えていただきたいのですが、
以下のようなプログラムを作りSEEK関数を利用して
ファイルから検索している文字が見つかれば
新たに検索する文字を入れ替え
見つかった行のその次の行から検索し処理を
短時間で終了させるような事をやりたいのですが
<<<このPGの本体とも言うべきプログラムは約25万件の処理を
行う為>>>
どうかご教授ください。
よろしくお願いします。

プログラム↓

Sub FSEEK()
'MsgBox "引数=" & Mails
   Dim s As String
   Dim MyArray
   Dim d
   s = CurDir                   'カレントフォルダを取得する
    MyArray = Split(s, "\", -1)  'カレントフォルダを"¥"で分割する
    'カレントフォルダを再構成する
    s = MyArray(0) & "\" & MyArray(1) & "\" & MyArray(2) & "\" & "デスクトップ\ファイルシーク"
    
    ChDir s                      'カレントフォルダを変更する
    Dim strFILENAME2 As String
    strFILENAME2 = s & "\FILESEEK2.txt"
 
    Dim strREC  'オーバーフローの為
    
    Dim setlist As Variant          'SPLITの戻り値はバリアント型の為
    Dim n, comt, counter
  
    'strFILENAME2 = s & "\FILESEEK2.txt"
    Dim intFileno As Integer
    Dim i
    Dim jjj As Variant
    Dim uuu As Long
    Dim dse, A1, A2 As String
    Open strFILENAME2 For Input As #1
    Dim strtest
    Dim ddd As String
    Dim FPos As Long
    
    counter = 0
    i = 1
    Do Until EOF(1)
        
       Line Input #1, strREC
        
        jjj = Split(strREC, ",")
        dse = jjj(1)

A1 = "6columsyori"
A2 = "12columsyori"

        If StrComp(dse, A1) = 0 Then
            
            MsgBox i & "行目" & "で見つかりました!" & A1 & "行目の処理:" & Loc(1)
        
            FPos = Seek(1)
            
            MsgBox FPos & "⇔本当の現在位置"
            
            A1 = ""
            A1 = A2 '処理の入れ替え
            Seek #1, FPos + 1 '見つかった位置から検索する
        
        End If
       i = i + 1
       
    Loop
    
'
    Close #intFileno

End Sub

データは以下のファイルです。・**************************************

\FILESEEK2.txt

1FILESEEKTESTNOW,1columsyori
2FILESEEKTESTNOW,2columsyori
3FILESEEKTESTNOW,3columsyori
4FILESEEKTESTNOW,4columsyori
5FILESEEKTESTNOW,5columsyori
6FILESEEKTESTNOW,6columsyori
5FILESEEKTESTNOW,7columsyori
5FILESEEKTESTNOW,8columsyori
9FILESEEKTESTNOW,9columsyori
10FILESEEKTESTNOW      ,10columsyori
11FILESEEKTESTNOWSEEEK ,11columsyori
12FILESEEKTESTNOW      ,12columsyori
13FILESEEKTESTNOWSEEEK,13columsyori
14FILESEEKTESTNOW      ,14columsyori
15FILESEEKTESTNOW      ,15columsyori
16******************** ,16columsyori
17  uu           ,17columsyori
18 uuuu         ,18columsyori
19FILESEEKTESTNOW,19columsyori
20FILESEEKTESTNOW,20columsyori
21FILESEEKTESTNOW,21columsyori
22FILESEEKTESTNOW,22columsyori
23  g         ,23columsyori
24  g          ,24columsyori
25  g          ,25columsyori
26  g          ,26columsyori
27  g          ,27columsyori
28  g          ,28columsyori
29  g          ,29columsyori
30  g          ,30columsyori


。。。  2005-02-03 07:43:28  No: 119400

Line Inputでよみこんでいるんだから次の読み込み位置は
自動的に次の行になっているんじゃないの?

つまりSeekを使う必要がないんじゃないかということです。


むーん  2005-02-03 09:27:39  No: 119401

いつの間にかVBAの話になっていたのねw
前の質問の続きならVB6かと思ってた。


。。。  2005-02-03 09:51:03  No: 119402

その行に目的の文字列が含まれているかどうかだけ分かればいいのであれば
下記の方法も有りかと。
どっちが速く処理できるかは実際試して見ないと分かりませんが。

If InStr(strRec,A1)>0 Then
以下略

If strRec Like "*" & A1 & "*" Then
もしくは
If strRec Like "*" & A1 Then
以下略

ところで続き物だったんですか?
できれば参考のため前のURLも入れて下さい。


猫夜叉  2005-02-03 12:16:26  No: 119403

ロジック的に大丈夫なの?

A1 = A2 '処理の入れ替え  としているが
少し上のほうで
A1 = "6columsyori"
A2 = "12columsyori"
としているぞ。

Do Untilの前に出さなければ、ずっと"6columsyori"を探していることになるんでないかい?


umebaind  2005-02-03 18:45:32  No: 119404

すみません
A1 = "6columsyori"
A2 = "12columsyori"の定義はDo Untilの前ですね
それと後、A2が見つかればEXIT DOですね。

。。。←さんえ、データがソートされて昇順になっているので
また頭からぐりぐり廻すのではなくて
見つかった行から処理する方が早いと思われるので(25万件の処理)


。。。  2005-02-03 21:38:10  No: 119405

>見つかった行から処理する方が早いと思われるので
いや、だから見つかったところから続けてやるのならSeekはいらないと
いうことをいってるんですが。

ファイルを閉じて再度開いてSeekするのなら分かりますが、提示のコード
はそうしてないでしょ?


いな  2005-02-03 21:45:40  No: 119406

>>また頭からぐりぐり廻すのではなくて

このレスで、やりたいことがわからなくなった。


umebaind  2005-02-03 22:39:38  No: 119407

Sub FSEEK()

'概要:ファイルシークによる多重ループの高速化
'前提条件: *****、メールアドレスが昇順でソートされている事
'機能:
'******を見つけたファイルポインタをGLOBAL変数に記憶する
'次回処理されたら、前回処理された位置から処理するように
'GLOBAL変数から値を取り出しファイルポインタに設定する
'もし見つからなければファイルポインタを最初に設定し
'検索をやり直す、そして前回処理された場所まで処理する

'MsgBox "引数=" & Mails

   Dim s As String
   Dim MyArray
   Dim d
   s = CurDir                   'カレントフォルダを取得する
    MyArray = Split(s, "\", -1)  'カレントフォルダを"¥"で分割する
    'カレントフォルダを再構成する
    s = MyArray(0) & "\" & MyArray(1) & "\" & MyArray(2) & "\" & "デスクトップ\ファイルシーク"
    
    ChDir s                      'カレントフォルダを変更する

    Dim strFILENAME2 As String
    strFILENAME2 = s & "\FILESEEK2.txt"
 
'    Dim strFILENAME3 As String
    'Dim setlist(200) As String
'    strFILENAME3 = "kihon_dl.csv"
    
'    Dim strREC As String            ' 読み込んだレコード内容
    Dim strREC  'オーバーフローの為
    
    Dim setlist As Variant          'SPLITの戻り値はバリアント型の為
    Dim n, comt, counter
  
    'strFILENAME2 = s & "\FILESEEK2.txt"
    Dim intFileno As Integer
    Dim i
    Dim jjj As Variant
    Dim uuu As Long
    Dim dse, A1, A2 As String
    
    Open strFILENAME2 For Input As #1
'    Close #intFileno
 
    Dim strtest
    Dim ddd As String
    
    Dim FPos As Long
    
    counter = 0
    i = 1
    
Dim gcounter
A1 = "6columsyori"
A2 = "7columsyori"
    
    Do Until EOF(1)
        
       Line Input #1, strREC
        
        jjj = Split(strREC, ",")
        dse = jjj(1)
        
        If gcounter = 2 Then Exit Do
        If StrComp(dse, A1) = 0 Then
            gcounter = gcounter + 1
            
            MsgBox i & "行目" & "で見つかりました!" & A1 & "行目の処理:" & Loc(1)
        
            FPos = Seek(1)
            
            MsgBox FPos & "⇔本当の現在位置"
            
            A1 = ""
            A1 = A2 '処理の入れ替え
            
            Seek #1, FPos  '見つかった位置から検索する
'            Seek #1, FPos + 1 '見つかった位置から検索する
        
        End If

        
       i = i + 1
       
    Loop
    
'
    Close #intFileno

End Sub
解決しました、有難う御座います。
今までより少し早くなったようです
30分→500件、10分350→件


LESIA  2005-02-04 01:46:24  No: 119408

解決したと書いてますが、これで、本当に解決したんでしょうか?
コードをみると、グローバル変数なんて使ってないし、毎回必ずファイルの
最初から検索してますけど(^^;
それから、A1が見つかったら、その次の行からA2を検索してるけど、
その部分はLine Inputで読んでいけばわざわざSeekする必要もないのでは?


特攻隊長まるるう  2005-02-04 02:06:34  No: 119409

http://www.accessclub.jp/bbs3/wforum.cgi?no=39759&reno=no&oya=39759&mode=msgview&page=0
↑こーゆー指摘も受けてますが…(^^;)
>    Dim dse, A1, A2 As String
の前2つの変数は[VBA]でも Variant では?とか
全体的に変数とその型についてあやふや…つっこみだすと
きりがないとは思います。…質問が
>Seek関数を使いこなすには
だから『Seekする必要ない』って言われたら終わっちゃうとか?w


。。。  2005-02-04 03:35:22  No: 119410

本人が満足しているみたいなんで何もいいませんが

>Seek #1, FPos  '見つかった位置から検索する

これあってもなくても一緒。


通りすがり  2005-02-04 06:07:28  No: 119411

正しくコメントを入れるとこんな感じかな?
FPos = Seek(1) '見つかったら現在の位置を取得
Seek #1, FPos  '現在の位置へ移動(意味ねーよ!)

あと少し早くなったのは、A2が見つかったらExit Doしてるからだと
思われる。


ガッ  2005-02-04 07:25:28  No: 119412

Sub foo(ByRef fn As Integer)
    
    '( ´Д`)<もっといいのがあるが、ちょと言いたかったので。
    
    Const FindStr1      As String = "6columsyori"
    Const FindStr2      As String = "7columsyori"
    
    Dim lineSt          As String
    Dim status          As Long
    
    status = 0
    Do While Not EOF(fn)
        Line Input #fn, lineSt
        Select Case status
            Case 0
                'find FindStr1
                If InStr(1, lineSt, FindStr1) Then
                    status = 1
                    Debug.Print FindStr1 & "が見つかりました"
                End If
            Case 1
                'find FindStr2
                If InStr(1, lineSt, FindStr1) Then
                    Debug.Print FindStr2 & "が見つかりました"
                    Exit Do
                End If
        End Select
    Loop
    
End Sub

※汚くてスマソ&終レスに投稿スマソ…(orz


ガッ  2005-02-04 07:25:58  No: 119413

と思ったら誤爆してるな…適当に直してくれ;;


LESIA  2005-02-04 18:28:15  No: 119414

検索する文字列
A1 = "6columsyori"
A2 = "7columsyori"
が、ファイルの中に何個所もあり、呼び出す毎に、見つかった位置から
次のA1・A2を検索するのなら、こんな感じかも。
まぁ、Seek関数を使いこなしてはいないが(^^;

でも、質問者は解決したと思っているのでもう見てないかな?

Private Sub FSEEK()
    Dim fso As Object
    Dim ts As Object
    Dim lngSkipLine As Long
    Dim strFileName As String
    Dim A(1 To 2) As String
    Dim iCounter As Integer
    Dim strBuffer As String
    Dim dse As String
    
    Static FPos As Long
    
    Const ForReading = 1
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    strFileName = "F:\CKJフェイシング表\mast.csv"
    Set ts = fso.OpenTextFile(strFileName, ForReading)
    
    '前回見つかった位置から検索する
    For lngSkipLine = 1 To FPos
        ts.SkipLine
    Next lngSkipLine
    
    iCounter = 1
    A(1) = "6columsyori"
    A(2) = "7columsyori"
    Do Until ts.AtEndOfStream
        strBuffer = ts.ReadLine
        
        dse = Split(strBuffer, ",")(1)
        
        If StrComp(dse, A(iCounter)) = 0 Then
            MsgBox ts.Line & "行目" & "で見つかりました!" & A(iCounter) & "行目の処理"
        
            '見つかった位置を記憶
            FPos = ts.Line
            
            '処理の入れ替え
            iCounter = iCounter + 1
            If iCounter > UBound(A) Then
                Exit Do
            End If
        End If
    Loop
    
    ts.Close
    
    Set ts = Nothing
    Set fso = Nothing
End Sub


umebaind  2005-02-07 20:39:28  No: 119415

すみません、UMBAINDですこちらの処理のほうが断然早いと解りました
同じ処理でも今までの処理では5時間かかっていたものが(データ1万件)
5分で終了するようになりました

    'ハッシュぽい処理
    '****************************
    '読者番号関連の処理を簡素化し
    'ループを1つ破棄し処理全体を
    '早める為に行う
    '使用されるデータの上限は6万件までとする
    '****************************
    Dim xlApp2 As Object

    Dim strHasyu As String
    Dim get_data
    Dim set_data As Variant
   
    strHasyu = s & "\jjjjj.txt"
    
    Open strHasyu For Input As #3
        'オブジェクトの生成
    
    Set xlApp2 = CreateObject("Scripting.Dictionary")
    
    Do Until EOF(3)
    
        Line Input #3, get_data
        
        'ファイルバッファの分割
        set_data = Split(get_data, ",")
        
        'メモリへの展開 'XXXXXXをキーに、XXXXXXをDATAとして格納する
        xlApp2.Add set_data(1), set_data(0)
    
    Loop
    'ハッシュぽい処理 END**********************


UMEBAIND  2005-03-16 19:42:34  No: 119416

ありがとうございました、マルチポストに対してはそれだけ「必死」
ということで勘弁してください
ファイルシークで処理することなくVBAの辞書機能を
使用することにより22時間かかる処理が60分まで短縮しました
Set xlApp2 = CreateObject("Scripting.Dictionary")


・・・  2005-03-16 21:57:17  No: 119417

そーゆー問題じゃないでしょうが。
なんで、この掲示板って利己主義な質問者ばかりなの?


ぬるぽ  2005-03-24 18:55:44  No: 119418

そうゆう質問者にちゃんとした回答つけちゃうからいなくならない。


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

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






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