[リストへもどる]
一括表示

投稿時間:2003/04/09(Wed) 10:23
投稿者名:mitu
Eメール:
URL :
タイトル:
RichTextBox使用のファイル比較
度々で申し訳ありませんが、よろしくお願いします。

今、CSVファイルを比較するものを作っています。
リッチテキストボックスにファイルを展開して比較をします。

行単位の比較ではなく、カンマ区切り毎の比較をし、
異なる部分に色を付けるのですが、
前質問のような、カラム数=35、行数=10000 のファイルになると、
セル毎の比較処理、
また、色づけに関しましても、
SelStart、SelLength、SelColor で1カラム毎かえているので、
かなり、時間が掛かってしまっています。

現在は、1行ずつ取得後、各セル毎値を取得し、比較しています。
その後、描画フラグを見て、色を変えている作業です。

高速で行える方法がありましたら、ご教授よろしくお願いします。

投稿時間:2003/04/09(Wed) 11:16
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: RichTextBox使用のファイル比較
回答ではありません。
現在どのようなコードで実行されているか投稿して頂いた方が
レスが早いのでは?
でないとそれより、早いか、遅いか解らないのでは!
ファイルの操作にも色々あるので
ここの逆引きヘルプの テキストファイルの読込表示比較 を参照

それと、遅い、早いは個人的な主観もあるのでどれ位掛かるものを
どれ位早くしたいかを書いて頂いた方がいいかと思います。

投稿時間:2003/04/09(Wed) 13:14
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: RichTextBox使用のファイル比較
1) Sel系プロパティの使用は、最低限度に留めてください。
可能であれば、Sel系プロパティを使わないコーディングを試みてください。
個人的な経験から言えば、SelColor等で少しずつ色を変更していくのではなく、
RTFテキストを自前で作成し、それをTextRTFプロパティに一括指定するようにすると、
処理速度がかなり向上します。(RTFコードの仕様に関しては、MSDNライブラリを参照してください)


2) RTFコードの生成が面倒であれば、他のコントロールの使用を検討してみてください。
表示のみで良ければ、例えば、MSHFlexGridなどが使えるかもしれません。
(MSHFlexGrid/MSFlexGridで編集を行いたい場合は、このサイトのサンプルが参考になるでしょう)

投稿時間:2003/04/10(Thu) 09:56
投稿者名:mitu
Eメール:
URL :
タイトル:
Re^2: RichTextBox使用のファイル比較
説明不足ですみません。

myTextにテキスト文字列が入っています。

   For i = 0 To maxRow - 1
      'リターンコード検索
      rtLen = InStr(1, myText, vbCrLf)
      '1行取得
      onetxt = Mid$(myText, 1, rtLen + 1)
      '各セルの値を取得
      Call Get_CellStr(onetxt, Dno())

      --- 比較 ---
      
      '残りの文字列
      myText = Mid$(myText, rtLen + 2)
   Next i

Private Sub Get_CellStr(str As String, Dno() As String)
   Dim strLen As Long
   Dim strCnt As Long
   Dim vi     As String
   Dim p      As Long

   vi = str
   strCnt = 1
  
   Do
      '","調査
      strLen = InStr(1, vi, ",")
      If strLen = 0 Then Exit Do
      strCnt = strCnt + 1
      vi = Mid$(vi, strLen + 1)
   Loop While (1)
  
   ReDim Dno(strcnt - 1)
    
   vi = str
   p = 1

   Do
      '","調査
      strLen = InStr(1, vi, ",")
      If strLen <> 0 Then
         '番号格納
         Dno(p - 1) = Left$(vi, strLen - 1)
         vi = Mid$(vi, strLen + 1)
         p = p + 1
      End If
      
      If p = strCnt Then
         Dno(p - 1 ) = vi
         Exit Do
      End If
   Loop While(1)
End Sub

長くなってしまいましたが、このような感じで、
それぞれのテキストから
1行取得して、各セルの値を取得して、比較する。
というのを行数分行っています。

遅くなる気は、しているのですが、
他に早くなる方法が思いつきませんでした。
最後まで、行ってないので、正確な時間はわかりませんが、
5分以上は掛かります。

色につきましては、魔界の仮面弁士さんよりご指摘頂いた
RTFについて調べます。

よろしくお願いします。

投稿時間:2003/04/10(Thu) 14:46
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: RichTextBox使用のファイル比較
文字列に色を指定する処理だけを省略した場合としない場合では
処理時間はどうなのでしょうか?
試していないので解りませんが、この比較処理に掛かっている時間
が大きいのではないでしょうか?
一旦テキストボックスに読込んでから処理されているようですが
ファイルから読込む時に同時に比較処理をした方が無駄がないような気も
します。
VBのバージョンが6.0ならSplit関数が使えますし、ファイルの比較処理
事態に多くの時間が掛かっているようでしたら ここの 複数行テキストボックス
の指定行の文字列を取得する。のようにAPIを使って見るとか又はFileSystemObject
オブジェクトを使って見るとかすればもう少し早くなるように思います。
FileSystemObject関係のテキストファイルの読込表示比較を見て頂ければ
解るかと思います。そこで処理速度を測っているのと同じようにして測りながら
色々コードを試されたらいいかと思います。

今思いついたのですが SelStart、SelLength の部分が影響しているようでしたら
前回,効果のあった APIの SendMessage RichTextBox1.hwnd, EM_SETSEL, 10, ByVal 20&
(10バイト目から20バイト目までの10バイト選択)を試してみてはどうでしょう?
  

投稿時間:2003/04/10(Thu) 22:58
投稿者名:mitu
Eメール:
URL :
タイトル:
Re^4: RichTextBox使用のファイル比較
ご指摘、ありがとうございます。

文字列に色を指定する部分は、セル毎に違う部分だけ色を変えているので、
違う部分が多い場合に遅くなってしまうだけでした。

やはり、比較処理をする段階の読み込み時で、相当時間が掛かっていました。
ファイルの読み込みは、早いですが、同時に比較となりますと、
RichTextBoxは、編集可能なので、常にRichTextBoxのテキストで比較を考えています。
花ちゃんさんのご指摘のSplit関数や、API関数は、まだ試してはいませんが、
FileSystemObject関連で、相当早くなりました。
比較に関しましては、If文なので、それほどの速度向上は望めないかと思っています。

ただ、MsFlexGridで行う方法も考えています。
MsFlexGridの方が、見た目綺麗な気がしますが、
行数、列数の指定が限られてしまいますし、
ファイル比較には、
RichTextBoxとMsFlexGridのどっちが適しているのでしょう?

そこで、MsFlexGridでお尋ねしたいのですが、
セルの色を変えるのに、

   With grdData
      For i = 0 To 9999
         For j = 0 To 34
            .Row = i
            .Col = j
            .CellBackColor = vbRed    
         Next j
      Next i
   End With

のような、一つ一つ変える他に方法はあるでしょうか?
また、各セルのテキストを全て取得するのにも
  
   With grdData
      For i = 0 To 9999
         For j = 0 To 34
            myStr(i,j) = .TextMatrix(i,j)
         Next j
      Next i
   End With

以外に方法はありますか?

宜しくお願いします。

投稿時間:2003/04/10(Thu) 23:22
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: RichTextBox使用のファイル比較
> ファイル比較には、
> RichTextBoxとMsFlexGridのどっちが適しているのでしょう?

当然 MsFlexGrid の場合はデータが個別になっている分処理が1ステップ省かれますよね
ただ、処理時間は実際測定して見ないと、ひょっとしたらMsFlexGridの方が遅いかも知れません

コード的には書いておられるようになるかと思います。只、35万セルまでしか扱えないので
大きなデータは無理ですよね、分割するなりしないと。
後は、ご存知かと思いますが処理中はMsFlexGrid を非表示にする位ですかね。

投稿時間:2003/04/11(Fri) 01:50
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^5: RichTextBox使用のファイル比較
> ファイルの読み込みは、早いですが、同時に比較となりますと、
> RichTextBoxは、編集可能なので、常にRichTextBoxのテキストで比較を考えています。
プロパティの使い方にもよりますが、一般的には、プロパティの読み書きというのは、
変数の読み書きよりも低速になりますので、その点は気を付けてくださいね。

> のような、一つ一つ変える他に方法はあるでしょうか?
残念ながら、個別に変えるより他ありません。

隣接しているセルであれば、ColSel, RowSel等を併用する事で、
色を一括して変える事もできますけれどね。。。


> また、各セルのテキストを全て取得するのにも
Clipプロパティを試してみてください。

投稿時間:2003/04/11(Fri) 13:55
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: RichTextBox使用のファイル比較
> 今、CSVファイルを比較するものを作っています。
> リッチテキストボックスにファイルを展開して比較をします。
面白そうなので、私も同じような物を作って見ました。

> 前質問のような、カラム数=35、行数=10000 のファイルになると、

テスト用のデータとして、上記仕様のCSVファイルを2つ作ってみました。
ファイルサイズは、それぞれ2.7MB前後です。
(両者には、350,000のセル中、約5%程度の差異を含ませてあります)


で、『これらのファイルをセル単位で比較し、異なる部分に色を付けた
RTFファイルを作成するプログラム』をためしに書いてみたところ、
私の環境では、平均で「14秒43」程度の処理時間が必要でした。


ただ問題は、これを表示する部分にありました。

できあがったRTFファイルは、それぞれ 4.3MB程度になるのですが、
これらを LoadFileメソッドで読み込もうとすると、
実に10分以上もの時間がかかってしまいます。

ここまでのデータサイズとなると、RichTextBoxでは苦しいかもしれませんね。

投稿時間:2003/04/11(Fri) 20:19
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^2: RichTextBox使用のファイル比較
> 私の環境では、平均で「14秒43」程度の処理時間が必要でした。
> ただ問題は、これを表示する部分にありました。
> できあがったRTFファイルは、それぞれ 4.3MB程度になるのですが、
> これらを LoadFileメソッドで読み込もうとすると、
> 実に10分以上もの時間がかかってしまいます。

それでしたらMSFlexGridの方が早そうですね
読込み表示と比較色づけで2分もかからないようです。

同様のファイルで試してみたら
読込表示に   26秒 (2ファイル読込)
比較色付けに  8.7 秒

Pen4 1.7GHz WinXP VB6.0

投稿時間:2003/04/16(Wed) 00:21
投稿者名:mitu
Eメール:
URL :
タイトル:
Re^3: RichTextBox使用のファイル比較
魔界の仮面弁士さん、花ちゃんさん、
返信ありがとうございます。
そして、試して頂きまして、嬉しい限りです。

> 実に10分以上もの時間がかかってしまいます。
そんなにかかってしまうんですね。
実は、RichTextBoxではなく、MsHFlexGridを使って作成しました。

> それでしたらMSFlexGridの方が早そうですね
> 読込み表示と比較色づけで2分もかからないようです。
>
> 同様のファイルで試してみたら
> 読込表示に   26秒 (2ファイル読込)
> 比較色付けに  8.7 秒
>
> Pen4 1.7GHz WinXP VB6.0

MsHFlexGridで作成したところ、
ファイルのドラッグ&ドロップでGridに表示  20秒   (1ファイル)
文字列データ取得、比較                    25秒   (2ファイル)
色づけ                                    1分30秒(2ファイル)

比較開始ボタンを押してから、合計で約2分30秒程かかってしまいました。
Celeron 750Hz Win2000 VB6.0
です。

Grid表示は以下のようにやっています。

Public Sub Set_CSV_In_Grid(strText As String, maxRow As Long, grd As MSHFlexGrid)
    Dim oneTxt()  As String
    Dim colC()    As Long
    Dim dumCell() As String
    Dim maxCol    As Long
    Dim putFixed  As String
    Dim pp        As Long
    Dim i         As Integer
    Dim j         As Integer
    
    ReDim oneTxt(maxRow - 1)
    ReDim colC(maxRow - 1)
    '各行の文字列取得
    oneTxt = Split(strText, vbCrLf)
    
    For i = 0 To maxRow - 1
        'カラム数取得
        colC(i) = Get_Column_Count(oneTxt(i))
        '最大カラム数
        If maxCol < colC(i) Then maxCol = colC(i)
    Next i
    '再割り当て
    ReDim dumCell(maxCol - 1)
    
    With grd
        .Clear                      'クリア
        .Rows = maxRow + 1          '行数
        .Cols = maxCol + 1          '列数
      
        For i = 1 To maxRow
            '固定行
            .TextMatrix(i, 0) = i
            If oneTxt(i - 1) <> "" Then
                '各セルの値取得
                dumCell = Split(oneTxt(i - 1), ",", colC(i - 1))
                '列最大数分繰返し
                For j = 1 To colC(i - 1)
                    '各セルの値 PUT
                    .TextMatrix(i, j) = Trim$(dumCell(j - 1))
                Next j
            End If
        Next i
    End With
End Sub

データ取得は
With grd
    For i = 0 To maxRow - 1
        For j = 0 To maxCol - 1
            strText(i, j) = .TextMatrix(i + 1, j + 1)
        Next j
    Next i
End With

比較は
For i = 0 To maxRow - 1
    For j = 0 To maxCol - 1
        If (strTxt1(i, j) <> strTxt2(i, j)) Then
            DrawF1(i, j) = 1
            DrawF2(i, j) = 1
        End If
    Next j
Next i                    
です。データ取得と比較は別関数です。

色付けは、
With grd
    For i = 0 To xRow - 1
        For j = 0 To xCol - 1
            If (DF(i, j) = 1) Then
                .Row = i + 1
                .Col = j + 1
                .CellBackColor = vbRed
                .CellForeColor = vbWhite
            End If
        Next j
    Next i
End With
これを2回呼んでいます。

長くなってしまいましたが、
こうすれば早くなるなどありましたらお願いします。

宜しくお願いいたします。

投稿時間:2003/04/16(Wed) 00:24
投稿者名:mitu
Eメール:
URL :
タイトル:
Re^4: RichTextBox使用のファイル比較
上記に追加ですが、
ファイルは、10000行、35列で
相違部分が7020個の場合です。

投稿時間:2003/04/16(Wed) 02:55
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: RichTextBox使用のファイル比較
一度下記を試して見て下さい。

Option Explicit    
'参照設定でMicrosoft DAO 3.6 Object Library にチェックを
'入れておいて下さい。
Private Sub Command1_Click()
    Screen.MousePointer = vbHourglass
    DoEvents
    
    MSFlexGrid1.Visible = False
    MSFlexGrid1.Clear
    MSFlexGrid2.Visible = False
    MSFlexGrid2.Clear
    Dim DB          As Database
    Dim RS          As Recordset
    Dim TxtFileName As String
    Dim DataPath    As String
    Dim strConnect  As String
'============== 元ファイルの読込み表示 =======================
    'データの入っているパス
    DataPath = App.Path
    'テキストファイル名
    TxtFileName = "test.CSV"
    '接続文字列を設定
    strConnect = "Text;DATABASE=" & DataPath & ";HDR=NO"
    'ファイルをオープン
    Set DB = OpenDatabase(DataPath, False, False, strConnect)
    'テーブルの内容を格納
    Set RS = DB.OpenRecordset(TxtFileName, dbOpenTable)
    Set Data1.Recordset = RS
    Data1.Refresh
    
    RS.Close
    DB.Close
    Set RS = Nothing
    Set DB = Nothing
'============== 比較用ファイルの読込み表示 =======================
    'テキストファイル名
    TxtFileName = "test1.CSV"
    '接続文字列を設定
    strConnect = "Text;DATABASE=" & DataPath & ";HDR=NO"
    'ファイルをオープン
    Set DB = OpenDatabase(DataPath, False, False, strConnect)
    'テーブルの内容を格納
    Set RS = DB.OpenRecordset(TxtFileName, dbOpenTable)
    Set Data2.Recordset = RS
    Data2.Refresh

    RS.Close
    DB.Close
    Set RS = Nothing
    Set DB = Nothing
    MSFlexGrid1.Visible = True
    MSFlexGrid2.Visible = True
    Screen.MousePointer = vbDefault
End Sub

Private Sub Command2_Click()
'完全一致検索
    Screen.MousePointer = vbHourglass
    DoEvents
    Dim Ro     As Long
    Dim Co     As Long
    MSFlexGrid1.Visible = False
    MSFlexGrid2.Visible = False
    With MSFlexGrid1
        For Ro = .FixedRows To .Rows - 1
            For Co = .FixedCols To .Cols - 1
                If MSFlexGrid2.TextMatrix(Ro, Co) <> .TextMatrix(Ro, Co) Then
                    With MSFlexGrid2
                        .Col = Co
                        .Row = Ro
                        .CellBackColor = vbRed
                    End With
                End If
            Next Co
        Next Ro
    End With
    MSFlexGrid1.Visible = True
    MSFlexGrid2.Visible = True
    Screen.MousePointer = vbDefault
End Sub

Private Sub Command3_Click()
'表示色を解除
    With MSFlexGrid2
        .FillStyle = flexFillRepeat
        .Col = 0
        .Row = 0
        .RowSel = .Rows - 1
        .ColSel = .Cols - 1
        .CellBackColor = vbWhite
        DoEvents
        .FillStyle = flexFillSingle
        .Col = 1
    End With
End Sub

Private Sub Form_Load()
'下記はプロパティで設定して下さい。
    With MSFlexGrid1
        .FixedCols = 0
        .FixedRows = 0
    End With
    With MSFlexGrid2
        .FixedCols = 0
        .FixedRows = 0
    End With
    '別途プロパティで設定して下さい
    'MSFlexGrid1.DataSource = Data1
    'MSFlexGrid2.DataSource = Data2
    Data1.Visible = False
    Data2.Visible = False
End Sub

投稿時間:2003/04/16(Wed) 13:24
投稿者名:mitu
Eメール:
URL :
タイトル:
Re^6: RichTextBox使用のファイル比較
ありがとうございます。

花ちゃんさんのソースを試したところ、結構早くできました。
ただ、MsFlexGridとなると、セルの制限があり、
実際のファイルでは、10240行、35列ぐらいなので、
MsHFlexGridの方向で考えていました。

ソースのMsFlexGrid部分をMsHFlexGridに変更して、
Dataコントロール部分をAdodcコントロールに変えてみたのですが、
Set Adodc1.Recordset = RS
の部分で、「型が違います」とエラーになってしまいました。
データベースアクセス関連に関して知識不足です。

MsHFlexGridに変えて行う場合はどうすればよいでしょうか?

また、比較色付け部分に関して、MsHFlexGridで行ったところ
1分30秒程掛かりました。(両方色付け)
コントロールによって処理時間は変わるのでしょうか?

宜しくお願いします。

投稿時間:2003/04/16(Wed) 14:00
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^7: RichTextBox使用のファイル比較
> また、比較色付け部分に関して、MsHFlexGridで行ったところ
> 1分30秒程掛かりました。(両方色付け)
> コントロールによって処理時間は変わるのでしょうか?

多分変わらないと思うのですが?
MsHFlexGrid を非表示状態で実行されているでしょうか?

MsHFlexGrid はADO でないと接続できないようですね!
私もデータベース関連は殆どしりません。
スレッドが長くなったのでその辺は改めて別スレッドで質問して下さい。