ExcelVBAでの全角と半角が混在するテキストファイル(改行無しで10MBと大容量)を読み込み、指定バイト数で区切りを入れるという文字列を処理します。

例)文字列:あいうえおabcdかきくけこ012345、指定バイト数:10
あいうえお
abcdかきく
けこ012345
LenBやMidBの動きがVBAとワークシート関数で異なるため、下記処理が必要となり、これを通した場合、処理がものすごく遅くなります。
LenB(StrConv(str, vbFromUnicode))
StrConv(MidB(StrConv(str, vbFromUnicode), start, length), vbUnicode)
参考:http://makotowatana.ld.infoseek.co.jp/vba_character.html#bite
この処理遅延は何とか回避できないのでしょうか?全角半角が混在しているテキストをVBAで処理する場合の、速度面を重視した文字列処理記述方法をご提示下さい。
http://q.hatena.ne.jp/1240918358
と同じ処理を、全角半角でも速くやるには、という質問です。
(VBAでのテクニックが知りたいので、同じ処理を別の言語でする、という回避方法はなしでお願いします。Excelのバージョンは2000-2007です。)

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2009/05/08 13:12:28
  • 終了:2009/05/15 13:15:02

回答(4件)

id:frkw2004 No.1

ふるるP回答回数192ベストアンサー獲得回数212009/05/08 13:40:07

ポイント23pt

一部分だけでなくて、関係するところをまとめて質問すると良いです。

投稿された処理内容は、多分ループ内での処理だと思います。

全体のうちの部分部分の文字列をその少ない文字列ごとにstrConvで変換しているので、処理が無駄です。全体を一括で変換するようにして、処理の回数を減らしましょう。

また、文字数が多い場合、前もってバッファを用意し、MidBステートメント(※注 関数じゃないですよ)で変換するのが処理を早くする方法です。

しかし、もともとがテキストファイルであるなら、Binaryで開いて、指定バイト数分読み込み、区切り文字(改行コードとか)を追加して別ファイルに出力していく、

最後までデータを別ファイルに出力し終わったら、元のファイルを削除して、作っておいた別ファイルの名前を元のファイル名に変更する。というロジックのほうが圧倒的に速いでしょう。

urlはダミーです。

http://www

id:jccrh1 No.2

jccrh1回答回数111ベストアンサー獲得回数192009/05/08 14:38:39

ポイント23pt

前回の回答に近いのですが、読み取り時ANSIIで取得し、StrConvでUNICODEに変換しています。

処理時間は7MBで約6秒でした。

Option Explicit
Sub 入力処理()
  Const レコード長 = 500
  Dim レコード数                As Long
  Dim レコード(レコード長 - 1) As Byte
  Dim I                     As Long
  Dim 進捗率                   As Integer
  
  Application.ScreenUpdating = False
  Open ThisWorkbook.Path & "\TEST.TXT" For Binary As #1
  レコード数 = (LOF(1) / レコード長)
  
  For I = 1 To レコード数
   進捗率 = I * 10 / レコード数
   Application.StatusBar = String(進捗率, "■") & String(10 - 進捗率, "□")
   Get #1, , レコード
   Range("A1").Offset(I - 1).NumberFormatLocal = "@"
   Range("A1").Offset(I - 1).Value = StrConv(レコード, vbUnicode)
  Next I
  Close
  Application.StatusBar = False
  Application.ScreenUpdating = True
End Sub

注)全角が500バイトの切れ目にならいとしています。

 

ダミー

http://q.hatena.ne.jp/1241755947

id:AZUY No.3

AZUY回答回数343ベストアンサー獲得回数122009/05/08 17:25:40

ポイント22pt

テキストファイルの中がSJISだと仮定してですが

Byte配列をつかって処理すると速いです。

http://q.hatena.ne.jp/answer

id:mj99 No.4

mj99回答回数138ベストアンサー獲得回数382009/05/08 19:53:05

ポイント22pt

2バイト文字が割れないよう考慮してみました。

Excel2003で1秒切れます(PCの性能によりますが)

Public Sub test1()
    
    Const fileName As String = "D:\a.txt"
    Const readCount As Long = 500
    Const bufEnd As Long = readCount - 1
    Const rowMax As Long = 65536
    
    Dim i As Long
    Dim rg As Range
    Dim bf() As Byte
    Dim cx As Variant
    
    Debug.Print Now()
    
    Application.ScreenUpdating = False
    
    'データを貼り付ける範囲
    Set rg = Worksheets(1).Range("A1:A" & rowMax)
    rg.Clear
    rg.NumberFormatLocal = "@"
    
    '2次元配列を作る
    cx = rg
    
    'ファイル読み込み
    With CreateObject("ADODB.Stream")
        .Type = 1 'adTypeBinary
        .Open
        .LoadFromFile fileName
        
        i = 1
        Do Until .EOS Or i > rowMax
            
            bf = .Read(readCount)
            
            '2バイト文字の割れ目調整(ファイルがShift_JISであると決め付け)
            If UBound(bf) = bufEnd Then
                If (bf(bufEnd) >= &H81 And bf(bufEnd) <= &H9F) Or (bf(bufEnd) >= &HE0 And bf(bufEnd) <= &HFF) Then
                    ReDim Preserve bf(bufEnd - 1) As Byte   '読み込んだバイト列の末尾を潰す
                    .Position = .Position - 1               'ファイルポインタを1バイト前へ
                End If
            End If
            
            cx(i, 1) = StrConv(bf, vbUnicode)
            i = i + 1
        Loop
        .Close
    End With
    
    '配列をセルに移す
    rg = cx
    
    Debug.Print Now()

End Sub


----

おまけ。個別に時間計測。

・セルに値を入れる時間

・StrConvの処理時間

Public Sub test2()
    
    '500バイトの文字列を65536個のセルに入れる処理
    Const dataCount As Long = 500
    Const rowMax As Long = 65536
    
    Dim i As Long
    Dim rg As Range
    Dim bf As String
    Dim cx As Variant
    
    Debug.Print Now()
    
    Application.ScreenUpdating = False
    
    Set rg = Worksheets(1).Range("A1:A" & rowMax)
    rg.Clear
    rg.NumberFormatLocal = "@"
    
    cx = rg
    
    bf = String(dataCount, "a")
    For i = 1 To rowMax
        cx(i, 1) = bf
    Next
    
    rg = cx
    
    Debug.Print Now()

End Sub

Public Sub test3()
    
    '500バイトを65536回StrConvで変換する処理
    Const dataCount As Long = 500
    Const rowMax As Long = 65536
    
    Dim i As Long
    Dim bf() As Byte
    Dim bf2 As String
    
    Debug.Print Now()
    
    bf = StrConv(String(dataCount, "a"), vbFromUnicode)
    For i = 1 To rowMax
        bf2 = StrConv(bf, vbUnicode)
    Next
    
    Debug.Print Now()

End Sub

http://q.hatena.ne.jp/1241755947

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません