2007年9月19日水曜日

第43回目 ちょっと寄道の2

○第43回目 ちょっと寄道の2

 前回説明したように、エクセルマクロから命令等不要な部分を削除します。
 そこから、変数を抜き出すというマクロです。
 変数は、
 半角スペース+変数名+半角スペース+変数名+半角スペース…、となっていて変数名の数はわかりませんが、最後は半角スペースで終わっています。
 一部を取り出すと次のようになっています(末尾の半角スペースが削除されています。自動設定をしているために、保存すると末尾スペースが削除されてしまうからです)。

AAA
p1 (AAA )
AAA1 (AAA p1 1)
retu1 (AAA1)
gyo1 (AAA1)
AAA9 (AAA p1 1)
retu9 (AAA9)
gyo9 (AAA9)
gyo_cnt gyo9 gyo1 1
retu_cnt retu9 retu1 1
k 0 1
i 0 gyo_cnt 1
dd1(i) (gyo1 i retu1 k)
dd2(i) i
i
i 0 gyo_cnt 2
j i 1 gyo_cnt 1
dd1(j) dd1(i)
AA dd1(j)
dd1(j) dd1(i)
dd1(i) AA
bb dd2(j)
dd2(j) dd2(i)
dd2(i) bb
  :

 これから、
Dim AA,AAA,AAA1,AAA9,bb
Dim dd1(100),dd2(100),dd3(100),gyo1,gyo9
Dim gyo_cnt,i,j,k,n_gen(100)
Dim n_new(100),n_old(100),p1,retu1,retu9
Dim retu_cnt,
 というものを抜き出すのです。配列定義の(100)は、一意的に(100)にしているものです。
 ソートをかけていますので、配列変数と通常の変数が混在しています。

 マクロを見て行きます。
 全文対象なので、一行目から最後まで同じことを繰り返します。
 最初の段階では重複は削除しません。
 変数名はスペースに区切られていますので、半角スペースを探していきます。二回探して始まりと終わりの位置をとります。
 変数名を取り終わったら、配列変数に格納して、格納した変数までを削除したもの(スペースは残す)で同じように探していきます。スペースが二つなければその行は終了です。
 これを最終行まで繰り返しますが、問題は変数名ではないものまでが入っているということです。一例を挙げれば、数値です。あとは、変数ではあるが、外の場所に記述されているもの、カッコ内のものの一部です。
  i 0 gyo_cnt 2  ←"0","2"は数値
 p1 (AAA)    ←"(AAA)"はほかの場所で必ず出てくるもの
 AAA1 (AAA p1 1) ←"(AAA"、"1)"はカッコ内の一部。
          ← "p1"はカッコ内の一部ですが、その判断ができないので、生かされます。
  dd2(i) i    ← "dd2(i)"は配列変数なので、カッコ内を100にします。

 取得した変数名をソートし、重複部分を除きます。
 そして、五こずつ、Dimに続けて表示します。
 流れはこんなものです。

 具体的に見てみましょう。(これはQXマクロです)

'初めのおまじない
   if @hwnd = 0 then exit proc

  '選択範囲を記憶
  y_begin = @SelectStartLine  'これは物理的行数
  y_end  = @ScrLineToCrLine(@SelectEndLine)  'これは論理的行数
  @BlockSelectEnd
  if y_begin = 0 then
    y_begin = 1        'これは物理的行数
    y_end = @ScrLineToCrLine(@LastLine) 'これは論理的行数
  end if

'メイン処理
'指定された範囲の中における、変数を持つ文字列を抜き出す。
'形式は、半角スペース+変数十半角スペースとなっている
  @Line = y_begin

   i= 0
   do   =⇒このdoは指定範囲内で繰り返すという意味のもの
   a$ = @textCr$(@Line)   =⇒一行の内容を変数に入れる
   b$ = a$

  do while 1  =⇒一行の中から変数名を抜き出す。変数名の数がわからないので、無限ループになっている。
    rr$ = " "
    p1 = instr(b$,rr$)   =⇒rr$は半角スペースのこと。一つ目のスペースの位置取得
    p2 = instr(mid$(b$,p1+1),rr$) =⇒二つ目のスペースの一取得。p2は最初のスペースは除いた位置である。変数名の長さ+1となる
    if p2 = 0 then exit do  '抜け出る
      c$= left$(mid$(b$,p1+1,p2-1),1) =⇒抜き出した変数名候補の先頭の文字を取得
      d$= right$(mid$(b$,p1+1,p2-1),1) =⇒抜き出した変数名候補の最後の文字を取得
      if c$ < "0" or c$ > "9" then  ' 0<= c$ <=9 は除外 =⇒数値は除く
        if c$ <> "(" then      'c$ = ( は除外 =⇒"("で始まっているものは除く
          p3 = instr(mid$(b$,p1+1,p2-1),"(")
          if p3 = 0 or d$ = ")" then   '途中に( があり、かつ、末尾が ) でない は除外
            if p3 <> 0 or d$ <> ")" then  '途中に( がなく、かつ、末尾が ) である は除外
              if p3 <> 0 and d$ = ")" then '途中に( がある、かつ、末尾が ) である
                mm1$[i] = left$(mid$(b$,p1+1,p2-1),p3) & "100)"  =⇒配列変数なので、配列数を一意的に100とする。
                i = i + 1
              else              '途中に( がなく、または、末尾が ) でない
                mm1$[i] = mid$(b$,p1+1,p2-1)
                i = i + 1
              end if
            end if
          end if
        end if
      end if
      b$ = mid$(b$,p2)

  loop

  @MoveNextLineCr  '改行し次の行へ

  loop while @ScrLineToCrLine(@Line) < y_end

  m_end = i-1  '定数の個数(0を含める)

  if m_end = 0 then exit proc

'ソート
  for i = 0 to m_end-1  'ソート
    min$=mm1$[i]
    for j = i+1 to m_end
      if min$ > mm1$[j] then
        min$ = mm1$[j]
        mm1$[j] = mm1$[i]
        mm1$[i] = min$
      end if
    next
  next

'重複した場合クリアする
  for i = 0 to m_end-1
    for j = i+1 to m_end
      if mm1$[i] <> mm1$[j] then exit for
        mm1$[j] = ""
    next
  next

'重複の削除。つめる。
  j = 0
  for i = 0 to m_end
    if mm1$[i] <> "" then
      mm1$[i-j] = mm1$[i]
    else
      j=j+1
    end if
  next
  m_end2 = m_end - j '最終的な定数の数

'末尾に追加。五単位で改行。間はカンマで区切る
  @InsertF "\n"  =⇒改行命令
  @InsertF "\n"

  i=0
  @Insert "Dim "
  for m= 0 to m_end2
    i=i+1
    if i= ll005 then
      @Insert mm1$[m]
      @InsertF "\n"
      @Insert "Dim "
      i=0
    else
      @Insert mm1$[m]
      @Insert ","
    end if
   next
  @InsertF "\n"
  @InsertF "\n"
 ※これはQXマクロである。

 ※今後の改修点
  ・QXマクロプログラムでも変数を抜き出せるようにする。(削除表(変換表)の作りで終了)
  ・変数の種類別に、変数名を分類し、その順番に出力する。配列変数、文字用変数、その他の分類
  ・その他の更なる分類。一文字のもの、二文字のもの、間に"_"があるもの、その他

 こんなところを改善点として考えています。
 次回から本道に戻ります。

0 件のコメント: