指定行の文字列を取得 |
複数行テキストボックスの指定行の文字列を取得する。 (077) | |
以前 テキストボックスの総行数・現在行・現在桁の取得 を修正していて見つけたEM_GETLINE を見つけたので試して見ました。 フォームに テキストボックス 2個 ラベルコントロール 2個 コマンドボタン 3個 を貼り付けておいて下さい。 Option Explicit '指定のウィンドウにメッセージを送る(750) Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long 'メモリブロックをコピーする(1008) Private Declare Sub CopyMemory Lib "kernel32.dll" _ Alias "RtlMoveMemory" (Destination As Any, Source As Any, _ ByVal Length As Long) '複数行テキストボックスにおいてテキストの行数を取得する(799) Private Const EM_GETLINECOUNT = &HBA ' 〃 指定行の先頭の文字インデックスを取得する(803) Private Const EM_LINEINDEX = &HBB '指定の行を取得する Private Const EM_GETLINE = &HC4 ' 〃 指定の文字インデックスを含む行インデックスを取得(802) Private Const EM_LINEFROMCHAR = &HC9 ' 〃 指定した行インデックスの一つ前の行までのバイト数を取得(803) Private Const EM_LINELENGTH = &HC1 '総行数を格納する変数 Dim lngMaxRow As Long '指定行を格納する変数 Dim LineNo As Long '指定行の文字列を取得するプロシージャ Private Sub AppointRowStr() ' Dim strBuffer As String, BufSize As Integer, lngLen As Long ' BufSize = 256 ' 'バッファーの最初の2バイトに最大バイト数を設定する ' '第1バイトに最大バイト数の下位バイト、第2バイトに上位バイトを指定する ' strBuffer = Chr(BufSize And &HFF) & Chr(BufSize / &H100) & _ ' String(BufSize - 2, vbNullChar) ' '半角1バイト・全角2バイト換算での取得バイト数と文字列を取得 ' lngLen = SendMessage(Text1.hwnd, EM_GETLINE, LineNo, ByVal strBuffer) ' 'バッファー内の取得した文字列を取り出す ' Label1.Caption = Left$(strBuffer, InStr(strBuffer, vbNullChar) - 1) '上記でも特に問題ないとは思うのだが、魔界の仮面弁士さんの忠告もあって 'http://hanatyan.sakura.ne.jp/vb60bbs/wforum.cgi?mode=allread&no=10299&page=0 '下記に変更しておきます。 '--------------------------------------------------------------------- Dim Buffer() As Byte '取得する文字列のバッファー Dim LineLength As Long '1行当たりのバイト数 Dim LineIndex As Long '指定行の先頭の文字インデックス ' 同じバイト数を2度も取得するのは無駄な気もするので、下記のように予め ' 大き目のバッファーを用意して取得してもいいかとは思うのですが ' ReDim Buffer(1024) 'バッファーのサイズ用に1行当たりのバイト数を事前に取得 '指定行の先頭の文字インデックスを取得 LineIndex = SendMessage(Text1.hwnd, EM_LINEINDEX, LineNo, ByVal 0&) '指定行のバイト数を求める LineLength = SendMessage(Text1.hwnd, EM_LINELENGTH, LineIndex, ByVal 0&) If LineLength < 1 Then Label1.Caption = "" Exit Sub '改行のみ場合等は、処理を抜ける End If ReDim Buffer(LineLength - 1) 'バッファーの最初の2バイトに最大バイト数を設定する CopyMemory Buffer(0), LineLength, 2 '半角1バイト・全角2バイト換算での取得バイト数と文字列を取得 '(ここで取得するバイト数は、上記で取得するバイト数と同じになります。) LineLength = SendMessage(Text1.hwnd, EM_GETLINE, LineNo, Buffer(0)) 'バッファーより指定バイト数分の文字を取り出し Unicode に変換 Label1.Caption = StrConv(LeftB$(Buffer, LineLength), vbUnicode) End Sub '複数行表示するテキストボックス Private Sub Text1_Change() 'テキストボックスの内容が変更されたら総行数を再取得 lngMaxRow = SendMessage(Text1.hwnd, EM_GETLINECOUNT, 0&, 0&) End Sub Private Sub Text1_Click() '現在行を取得してその内容を表示 LineNo = SendMessage(Text1.hwnd, EM_LINEFROMCHAR, -1&, 0&) If LineNo >= 0 And LineNo <= lngMaxRow Then '指定行の文字列取得へ Call AppointRowStr End If End Sub Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer) '現在行を取得してその行の内容を表示 LineNo = SendMessage(Text1.hwnd, EM_LINEFROMCHAR, -1&, 0&) If LineNo >= 0 And LineNo <= lngMaxRow Then '指定行の文字列取得へ Call AppointRowStr End If End Sub '指定行を入力するテキストボックス Private Sub Text2_GotFocus() Label2.Caption = "指定行を1〜" & lngMaxRow & "の範囲で指定して下さい" End Sub '指定行を入力するテキストボックス Private Sub Text2_KeyPress(KeyAscii As Integer) On Error GoTo ErrorHandler If KeyAscii = vbKeyReturn Then KeyAscii = 0 '指定行から1行分引く LineNo = CLng(Text2.Text) - 1 If LineNo >= 0 And LineNo <= lngMaxRow Then '指定行の文字列取得へ Call AppointRowStr Else Beep Text2.Text = "" End If End If Exit Sub ErrorHandler: Beep Text2.Text = "" End Sub ついでにファイルの入出力関係を (077) '丸ごと保存のコマンドボタンに記入 Private Sub Command1_Click() If Len(Text1.Text) < 1 Then MsgBox "保存するテキストがありません。" Exit Sub End If Dim Ret As Long Ret = InStr(Text1.Text, Chr$(34)) If Ret = 0 Then Ret = InStr(Text1.Text, Chr$(-32408)) End If If Ret Then Text1.SelStart = Ret - 1 Text1.SelLength = 1 Text1.SetFocus End If If Ret > 0 Then Dim strMsg As String strMsg = "文中に " & Chr$(34) & " が含まれています 保存しますか" Ret = 0 Ret = MsgBox(strMsg, vbYesNo) If Ret = vbNo Then Exit Sub End If End If 'テキストボックスの内容を丸ごと保存 ' ”区切りで保存されるので文書中には ”は使用不可。 Dim lngFileNo As Long lngFileNo = FreeFile Open "..\test.txt" For Output As #lngFileNo Write #lngFileNo, Text1.Text Close #lngFileNo End Sub '行ごと読み込みのコマンドボタンに記入 Private Sub Command2_Click() 'Line Input で行ごとの読み込み Dim Mystring As String Dim lngFileNo As Long lngFileNo = FreeFile Text1.Text = "" DoEvents Open "..\test.txt" For Input As #lngFileNo Do Until EOF(lngFileNo) Line Input #lngFileNo, Mystring Text1.Text = Text1.Text & Mystring & vbCrLf Loop Close #lngFileNo Text2.SetFocus End Sub '丸ごと読み込みのコマンドボタンに記入 Private Sub Command3_Click() 'ファイル丸ごと読み込み(高速) Dim Mystring As String Text1.Text = "" DoEvents Dim lngFileNo As Long lngFileNo = FreeFile Open "..\test.txt" For Input As #lngFileNo Input #lngFileNo, Mystring Text1.Text = Mystring Close #lngFileNo Text2.SetFocus End Sub |
|
テキストボックスの総行数・現在行・現在桁の取得 も参考にして下さい。 複数行テキストボックスの総行数・指定行の文字列等が取得でき、テキストファイルを扱う場合便利かと思います。行ごとの文字列が簡単に扱えるので読み込み時変数等に保管する必要もなく、ファイルの保存もテキストファイルを丸ごと保存でき処理が簡単にすみます。 読み込みも丸ごと読み込みが出来32KB位のファイルで0.2秒位で読み込み表示ができます。 行ごとに読み込みますと 14秒位かかります。但し、丸ごと読み込むため ” は文書中には使えません。( ” 区切りで保存のため) 尚、最初にテキストファイルを読み込むには行ごと読み込みを使って下さい。 文書中に ” があれば表示したテキストボックス中で削除し、丸ごと保存で保存して下さい。 丸ごと保存で保存したファイルだけが、丸ごと読み込みで読み込めます。 テキストファイルは適当な Readme.txt 等をコピーして使って下さい。 |