例)文字列:あいうえお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です。)
一部分だけでなくて、関係するところをまとめて質問すると良いです。
投稿された処理内容は、多分ループ内での処理だと思います。
全体のうちの部分部分の文字列をその少ない文字列ごとにstrConvで変換しているので、処理が無駄です。全体を一括で変換するようにして、処理の回数を減らしましょう。
また、文字数が多い場合、前もってバッファを用意し、MidBステートメント(※注 関数じゃないですよ)で変換するのが処理を早くする方法です。
しかし、もともとがテキストファイルであるなら、Binaryで開いて、指定バイト数分読み込み、区切り文字(改行コードとか)を追加して別ファイルに出力していく、
最後までデータを別ファイルに出力し終わったら、元のファイルを削除して、作っておいた別ファイルの名前を元のファイル名に変更する。というロジックのほうが圧倒的に速いでしょう。
urlはダミーです。
前回の回答に近いのですが、読み取り時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バイトの切れ目にならいとしています。
ダミー
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
コメント(0件)