○第92回目 QXマクロの紹介(その3)
※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。
文章作成の効率を若干上げるマクロです。
今回は、
3.前の行のあの部分をコピーしたい
を取り上げます。
文字列の場所の指定としては、2-10(この10は文字数)、-10、15-、ここまでは普通でしょう。
更に、0、0-12、0--10、99-10という指定もできるようにしています。
0って?=⇒現在のカーソルの位置を基準として末尾までという指定です
0-12って?=⇒現在のカーソルの位置を基準として後ろに12文字という指定です
0--10って?=⇒同じく、現在のカーソルの位置を基準として前に10文字という指定です
99-10って?=⇒文末から前に10文字という指定です
(前の行が現在のカーソル位置よりも短い場合は、更に行を前にさかのぼっていって、その位置に文字がある行からコピーするようにしていますが、この講では、出来るだけ単純にするために、該当する文字列がなしとして、何もコピーしないことにします。)
このマクロで問題になったのは、現在のカーソルの位置が、前の行の文字の位置とぴったり重なっていない可能性があるということです。半角全角が混じっていると、うまくぴったりあわないことがあります。
それ以外の場合は、文字列の切り出し関数、mid$で開始文字数とコピーする文字数を指定すれば、簡単にコピーもとの文字列は取得できます。挿入する場所はカーソルのある場所の前になっているので、そのままま挿入すればいいことになります。
これも、前回同様に処理の流れを見てみましょう。
1.コピーしたい文字列の場所を入力する
2.前の行を変数に取得する
3.入力値を分解する
4.位置の指定、カーソル位置からの指定、末尾からの指定ごとに処理を行なう。
=前の行から文字列を切り出し、コピーする。
1.コピーしたい場所を入力する
msg$ = "コピーしたい文字列の範囲を入力してください。5-20、8-、-25、0、0-8、0--8、99-8"
in_pos$ = inputbox$(msg$,"QX32 文字列のコピー","0")
p2 = instr(in_pos$,"-")
if p2 = 0 and in_pos$ <> "0" then exit proc
-が含まれてなく、0でない場合は、終了とします(5と入力した場合、入力値は有効と思われますが、めんどくさかったので無効としました。1文字の場合は無理にでも、5-1のように指定をしてください)。
2.前の行を変数に取得する
これを行なうために、最初の行及びカーソルの位置を取得しておいてください。最初の行は論理行に変換します。
y_begin = @ScrLineToCrLine(@Line) '物理行から論理行への変換
p1=@BytePosCr
前の行の全文字列取得は、
@Line = @CrLineToScrLine(y_begin-1) '論理行から物理行への変換
b$ = @TextCr$(@Line)
となります。(この段階で、制御は前の行にいっていますので、貼り付ける時、もとに戻しておく必要があります)
3.入力値を分解する
-の位置が問題になります。これはp2に入っていますので、基本的にはその前後に分解します。前をm1、後ろをm9とします。分解した後は数字に直すことを忘れないようにしてください。m9は文字数という位置づけにします。まずは単純に分解してください。
ただし、p2=0の場合("0"という入力の場合)は、m1は1、m9は999としておきます。
ただし、p2=1の場合("-9"という形式)は、m1は1とします。
ただし、p2=末尾の場合("8-"という形式)は、m9は999とします。
(99-8の場合は、単純にm1は99、m9は8とします)
3-2.指定値の修正
前の行の文字数で修正します。最終的にはm1もm9も文字の位置にします。
原則としてm9には文字数が入っていますので、m9=m1+m9-1とし、文字の位置にします。
m1=99の場合は、m1="前の行の文字数"-m9+1とし、m9は"前の行の文字数(=位置)"とします。
m9=999の場合は、m9="前の行の文字数(=位置)"とします。
すると、もれるのは、カーソル位置から求める場合だけとなります。これはあとで記述。
ただし、この結果、m1とm9が逆転していた場合は、m1とm9を入れ替えます。
また、文字の長さをオーバーしていたとか、マイナスだったとか、文字の長さに制限する、1とするまたは処理終了(exit proc)する、とかしてください。
4-1.位置の指定、末尾からの指定の場合
カーソルを元の位置に戻します。
@Line = @CrLineToScrLine(y_begin)
@BytePosCr=p1
コピーする文字は、
c$=mid$(b$,m1,m9-m1+1)
貼り付けは
@Insert c$
@BytePosCr=p1 'カーソルを元の場所に戻します。これはなくてもいいです。
4-2.カーソル位置からの指定の場合
最初のカーソルの位置を、p1=@BytePosCrで取得しています。
前の行の文字のバイト長(lenb(b$))より、p1が大きかった場合は、処理を終了させます(exit proc)。
p1は、カーソルのある文字が始まるバイト数となっています。頭から全角の文字列で4文字目にカーソルをおいた場合、カーソルの位置は7となります。前の行の7バイト目から始まる文字があるといいのですが、ない場合があります。最大が全角ですので、可能性は6バイト目から始まる全角文字です。(このような場合は、その文字から貼り付け対象とすることとします)
さてさて、バイト位置と文字の位置をどうやって対応付けますか。
1文字ずつ、そのバイト長を求めていきます。それを末尾まで行い、バイト数を累積したものを配列変数に入れます。
これは、その文字の終わるバイト位置になっています。
for i = 1 to len(b$)
nn(i) = lenb(mid$(b$,i,1))+ nn(i-1)
next
さて、これらのバイト位置とp1を比較します。それぞれの意味合いが違うので注意を要します。
前の例(7バイト目から始まっている)で考えて見ますと、6バイト目で終わっている文字があると、これは対象外です。次の文字はp1から始まっているということになりますから。
順番に見て、7バイト目で終わっていた場合は、最初の文字としていいでしょう。
順番に見て、7バイト目で終わっているものがなく、8バイト目で終わっていた場合は、7バイト目から始まっている全角の文字と判断できますので、最初の文字となります。
順番に見て、9バイト目で終わっているものは、最大でも8バイト目から始まっているので、最初の文字とはいえません。
したがって、初めて7バイトまたは8バイトの切れ目を持っている文字が、最初の文字となります。
for i = 1 to len(b$)
if p1 <= nn(i) then
m1=i
exit for
end if
next
次に、終わりの文字の処理です。
0-5とは、カーソルの位置以降の5文字という意味なので、
m9=m1+m9(5のこと)-1となります。(入力値を分解したものをまずm9に入れている)
0--5とは、カーソルの位置以前の5文字という意味なので、
m9=m1+m9(-5のこと)+1となります。(これは入力値がマイナスかどうかで判断できます。この結果、m1とm9が逆転しますので、入れ替えておいてください)
m9が文字の長さをオーバーしてる場合は文字の長さにとどめておいてください。
カーソルを戻し、文字を切り出し貼り付けるのは、4-1と同じですので省略します。
※機能の拡張
前の文が短すぎて、入力で指定した位置に文字がない(本来は入力誤り)、カーソルの位置に文字がない(本来は指定誤り)の場合の処理が一つ考えられます。
次に、コピーもとの文字列を、直前の行だけでなく、当該行、直後の行も指定できる。更に、直前直後の行ではなく離れた行も指定できる、ということも考えられます。
ニーズいかんですが、必要性は結構あります(よ)。
今回はここまで。

0 件のコメント:
コメントを投稿