2008年4月27日日曜日

第91回目 QXマクロの紹介(その2)

○第91回目 QXマクロの紹介(その2)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 まず、
 3.前の行のあの部分をコピーしたい
 5.あの行(複数の行も可能とする)をコピーしたい(それをもとに修正すれば早い)
 を取り上げてみます。

 簡単なほうから
 5.あの行(全体)をコピーしたい(それをもとに修正すれば早い)

 この機能の意味はお分かりでしょうか。
 カーソルのある行を0とみたてて、前の行は、1、2、3…、後ろの行は-1、-2、-3…と数えることにします。
 0-3とした場合=⇒現在行を含めて前の4行を現在行の前の行にコピーします。
 2-3とした場合=⇒2行前と3行前の行を現在行の前の行にコピーします。
 3とした場合=⇒3行前の行を現在行の前の行にコピーします。
 後ろの場合はマイナスをつけるだけで指示は同様です。-0-3、-2-3、-3.
 後ろの行をコピーする場合も、コピー文はカーソルのある行の前にコピーします。
 では、0と指定した場合はどういう意味になるでしょうか。カーソルの行をカーソルの行の前にコピーすることにします。-3-(+2)というような意味合いの指定は出来ないこととします。
 禁止事項はこれ以外にも、3-2、-3-2もダメとします。
 (QXマクロの一般的なお約束事は第33回及び34回参照)

 流れのポイントを見て行きます
 1.カーソルのある行の行番号を取得する
 2.コピーする箇所の入力。2-3など。
 3.入力値の分解
 4.コピーすべき行を配列変数に入れる(MAX100行としました)
 5.カーソルを、最初の行の前に置く
 6.コピーした文を貼付ける、改行を貼付ける。これを指定した回数繰りかえす。
 7.貼付けた一群の行の先頭行の行頭にカーソルを置く

 1.カーソルのある行の行数を取得する
  y_begin = @ScrLineToCrLine(@Line) '物理行から論理行への変換
  ※@Lineそのものは物理的な行数(表示単位の行数)となっています。
 2.コピーする箇所の入力
msg$ = "コピーしたい範囲の行数を入力してください。後ろの文章の場合はマイナス付き。例;3-5、-2-4、3、-3"
in1$ = inputbox$(msg$,,"0-2")
if in1$ = "99" then exit proc
 99が入ってきた場合は終了としました。
 3.入力値の分解。開始行、終了行の把握
 入力値の中の"-"の位置を調べます。
 ない場合…前の単一行の指定=⇒そのものが開始行であり終了行
 ある場合でその場所が1ではない…前の複数行の指定=⇒"-"の前が終了行、後が開始行
 ある場合でその場所が1でありほかに"-"がない…後ろの単一行の指定=⇒そのものが開始行であり終了行
 ある場合でその場所が1でありほかに"-"がある…後ろの複数行の指定=⇒"-"の前が開始行、後が終了行
 "-"の場所は、 p1=instr(in1$,"-")でもとめます。
 二つ目の"-"の場所は、 p2=instr(mid$(in1$,p1+1),"-")でもとめます。
 ここで使う変数は文字型なので、分解したあとvalで数字型にしておきます。
 前の複数行指定の場合で、一つ目の"-"の前と後ろは、
in19 = val(left$(in1$,p1-1))*(-1)
in11 = val(mid$(in1$,p1+1))*(-1)
で取り出します。開始・終了行が逆のように見えるのに注意してください
 後の複数行指定の場合では、一つ目の"-"が一つ余計についているので、
in11 = val(mid$(in1$,p1+1,p2-1))
in19 = val(mid$(in1$,p1+p2+1))
で取り出します。

 4.該当する行を配列変数に入れる(MAX100行としました)
 最初にカーソルがあった行からの相対的な位置は、in11とin19に入っています。
 この場合は、前はマイナス、後はプラスの数値となっています。
 コピーすべき行の相対的位置は、in11からin19になります。
 それを配列変数に格納しておきます。
'コピーもとの行に移動
@Line = @CrLineToScrLine(y_begin+in11)
 ( )の中は論理行となっています。それを表示上の行にしています。
gyo_cnt = in19-in11+1
'格納処理。
for i = 1 to gyo_cnt
mm$[i] = @TextCr$(@Line) 論理的な一行分の取得はこうします。改行は含まれません
@MoveNextLineCr '次の行(論理行)へ
next

 5.カーソルを、最初の行の行頭に置く
 ここまでは、行を追加していませんので行の関係は最初のままです。
 最初の行に制御を移します。
@Line = @CrLineToScrLine(y_begin)

 6.コピーした文を貼付ける、改行を貼付ける。これを指定した回数繰りかえす。
@MoveBeginningLine
for i = 1 to gyo_cnt
@Insert mm$[i]
@InsertF "\n"
next
これは説明が不要だと思います。

 7.カーソルを貼付けた一群の行の先頭行の行頭に置く
 前の場合、後の場合とも、最初の行となります。。
 したがって、
  @Line = @CrLineToScrLine(y_begin)
 となります。

 結構かかりました。今回はここまでとします。

2008年4月20日日曜日

第90回目 QXマクロの紹介

○第90回目 QXマクロの紹介
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 文章作成の効率を若干上げるマクロです。
 マクロを含めて文章を作成する際に一番よく使うのは何でしょうか。当然文字の入力かかる入力は除きます。
 人によって異なるものだと思いますが、コピー、移動、削除が多いのではないでしょうか。
 ということでこれらを中心にマクロの紹介です。
 ニーズ
【コピー】
 ・この行の前の部分をコピーしたい
 ・この行全体をコピーしたい
 ・前の行のあの部分をコピーしたい
 ・後ろの行のあの部分をコピーしたい
 ・あの行をコピーしたい(それをもとに修正すれば早い)
【挿入】
 ・この部分をカッコでくくりたい。いろいろなカッコを選びたい
 ・複数の行に連番を振りたい
 ・複数の行のある位置に同じ文字列を挿入したい
【特殊コピー】
 ・この文書の全文を別の文書のある部分にコピーしたい
 ・文末までをクリップボードにコピーしたい
 ・ブロックコピーをしたい
【逆転】
 ・あの行をコピーして、中を逆転させればいいのではないか(特にマクロでは、"="の前後を変えたいということがよく起こります)
 ・前後の行を逆転させたい
【削除】
 ・一時一字削除していくのではなく、何文字か一気に削除できないか
 ・文末まで削除したい
 ・一行を簡単に削除したい
 ・何行かをいっぺんに削除したい

 例えば、上のような"まとめの文章"があったとします。これ("・"の行のみ)に連番を振りたいのですが、どうしますか。連番は、"1."、"2."、"3."というものとします。
 今把握している連番マクロでは、指定されたすべての行となっていますので、【 】の行にも連番が振られてしまい、一気には出来ません。何段階に分けて実行するしかありません(【 】を除いて作った段階で、連番を振るというのであれば可能です)。
 この例のように文書を作成する場合においても、結構マクロが便利なのです。

 連番マクロで番号を振ってみました。
 既存のマクロ等の場合はコメントを付しています。
【コピー】
 1.この行の前の部分をコピーしたい
 2.この行全体をコピーしたい=⇒QXエディタの基本機能
 3.前の行のあの部分をコピーしたい
 4.後ろの行のあの部分をコピーしたい
 5.あの行(複数行も可能とする)をコピーしたい(それをもとに修正すれば早い)
【挿入】
 6.この部分をカッコでくくりたい。いろいろなカッコを選びたい=⇒括弧入力マクロ
 7.複数の行に連番を振りたい=⇒連番自動入力マクロ
 8.複数の行のある位置に同じ文字列を挿入したい
【特殊コピー】
 9.この文書の全文を別の文書のある部分にコピーしたい
 10.この文書のこの部分を別の文書のある部分にコピーしたい
 11.文末までをクリップボードにコピーしたい
 12.ブロックコピーをしたい=⇒「箱形でペタペタ」マクロ
【逆転】
 13.あの行をコピーして、中を逆転させればいいのではないか(特にマクロでは、"="の前後を変えたいということがよく起こります)
 14.前後の行を逆転させたい。一行の移動も一種の逆転でしょうか。含めましょう。
【削除】
 15.一字一字削除していくのではなく、何文字か一気に削除できないか
 16.文末まで削除したい=⇒QXエディタの基本機能
 17.一行を簡単に削除したい=⇒QXエディタの基本機能
 18.何行かを一気に削除したい

※ここに掲げた"括弧入力マクロ"等の記載のある部分は、すでにフリーのマクロとしてあるものです。

 ここに掲げた機能の全部が必要なものとはいえないと思います。筆者も、ほとんど使わないのは、11と15と18です。
 18なんかは、削除したい行数を数えるという頭の動きに慣れていないと、めんどくさくなり、既存の操作になる傾向があります。使いこなすには、視覚的に全体をみて瞬時に判断するとかの頭の訓練する必要があります。

2008年4月12日土曜日

第89回目 ブック(ファイル)を超えての処理の仕方(本題)

○第89回目 ブック(ファイル)を超えての処理の仕方(本題)
 ※エクセル2007で行なったものです

 今回はファイルを越えてです。
 ファイルの中に入れば、前回の処理で全シートの中身を置き換えていくという処理になります。
 ですから、前回の処理(置換語等の情報を取得したあと)に初めとおわりを付け加えればよいことになります。
 流れを頭の中に入れておきましょう。
 1.置換語等の取得
 2.パス名等の取得
 3.ファイルを閉じる
 4.フォルダ内のエクセルファイルを開く
 5.全シートに対して置換え処理をする
 6.当該ファイルを閉じる
 7.次のファイルを開き、処理を繰り返す。ファイルがない場合は終了。

 2.パス名等の取得
myPath = ActiveWorkbook.Path
 =⇒パス名は、フォルダの名前までが取得されます。
ChDir myPath
=⇒フォルダを指定します。
 ファイルを開く時には、フルパス名で開くことにします。

 3.ファイルを閉じる
ActiveWorkbook.Close SaveChanges:=True
 最初のファイルは閉じておきます、これをしないと二重に開くということが起きるので、その回避が面倒くさいので、閉じることにします。

 4.フォルダ内のエクセルファイルを開く
  フォルダに入っているエクセルのファイル名が必要です
   myFName = Dir(myPath & "\*.xls")
  =⇒これで取得します。myFName にはファイル名が入ります。パス名ではありません。
  (myFName = Dir("*.xls") でいいはずなのですが、フォルダの指定が出来ていないため、デフォルト値のフォルダをさがしにいってしまう)
  まず一つ取得しておいて、あとはdo loopで繰り返します。

Do Until myFName = ""
=⇒フォルダに次のファイルがなくなると、ファイル名はヌルが取得される
myFName = myPath & "\" & myFName
=⇒'フォルダ間でのパス名とファイル名をつけて完全パス名にしています。
Workbooks.Open Filename:=myFName
  =⇒ファイルを開く命令
sh_no = ActiveSheet.Index
=⇒処理が終わったときに開いた時点のシート再現するために取得する。

 5.全シートに対して置換え処理をする=⇒前回参照

 6.当該ファイルを閉じる
Worksheets(sh_no).Select
=⇒開いた時のシートに戻す
ActiveWorkbook.Close SaveChanges:=True
=⇒ファイルを保存する。確認のメッセージは出ません。

 7.次のファイル名を取得し、処理を繰り返す。ファイルがない場合は終了。
myFName = Dir()
  =⇒次のファイル名を取得
     myFName = Dir("")とすると最初からになるので、ぐるぐるまわる。
Loop

 これで終了ですが、終了する前に最初に開いてたファイルを開いて最初の状態を再現するには、最初のファイルのパス名とシート番号を別にもっておいて開きなおしてください。
 完全パス名 ThisWorkbook.FullName

※今回は置換えだったので、シート内の表の形式はまったく関係ありませんでした。
 しかし、ファイル内のシートがまったく同じ形式、かつ、フォルダ内のすべてのファイルも同じということもあります。すると、今回の置換えではないロジックを含んだ複雑な処理が出来ます。そのようなケースで大量処理の場合、夜始動させておいて、朝に出来上がっているという、芸当ができ、時間の節約が可能となります。
 また、マクロ中にフォルダのパス名を記述する方法もあります。すると複数のフォルダの処理が可能となります。
 応用できる事例があると腕のふるいがいがありますね。いちやく一目置かれるかも(保証なし)。

2008年4月6日日曜日

第88回目 ブックを超えての処理の仕方(背景など)

第88回目 ブックを超えての処理の仕方(背景など)

 必要は成功の母です。
 エクセルのファイルの入っているフォルダをコピーします。
 すると、一つのエクセル
のファイルから見て、リンク関係は、
 1.同じフォルダにあるエクセルのファイルからのリンクは正しくコピーされます。
 2.違うフォルダに入っているエクセルファイルからのリンクは正しく引き継がれません。ここで正しく引き継がれないとは、前の一群のフォルダにリンクが張られたままだということです。違う見方でいうと、リンク元のフォルダまでコピーしたのにフォルダ外からのリンクは、もとのフォルダのままだということです。これをフォルダガイストというといった笑われましたが…。
 これを直すには、リンク先を新しくコピーしたフォルダのパスに置き換える必要がです。
 【概 略 図】










 簡単です。一つ一つのエクセルファイルを開いて、一つのシートごとに置換えをしていき続ければいいのです。
 簡単ですが、面倒です。
 今まで紹介した機能では、複数語の置換えというのがありました(第20回)。
 これは複数の文字列の置換えを作成しておき、そのセルを指定し、さらに置き換え範囲を指定して(同一シート)、置換えを行うものです。
 この機能を拡大し、
 1.ファイル内のすべてのシートに対して置換えを行う。
 2.フォルダ内のすべてのエクセルファイルのすべてのシートに対して置換えを行う。
 とするものです。
 手順としても機能としても、原型を含めて三つのものを作成しておくのがいいでしょう。
 すなわち、
 1.シート内の指定した範囲内に対して置換えを行う。
 2.ファイル内のすべてのシートに対して置換えを行う。
 3.フォルダ内のすべてのエクセルファイルのすべてのシートに対して置換えを行う。
 という機能となります。

 2は簡単です。1の機能をシートごとに処理することにすればいいのです。for to文でシートの数だけ繰り返せばいいのです。
 問題(気をつけるべき点は)は、二つあります。
 1.ワークシートだけにするのかグラフのシートを対象にするのか
 =⇒グラフシートでは置換えは効かないと思われるのでワークシートだけに限定する
 2.処理が終了したとき、複数置換え語が書かれているシート(実行時のシートのこと)に処理を移すにはどうするか
 基本事項を次に書いておきます。
 ワークシートだけを処理する
  For j = 1 To Worksheets.Count 'グラフを入れる場合は To Sheets.Count
 Worksheets(j).Select
ワークシートの全部のセルを指定
  Cells.Select
 シート番号を取得しそのシートを指定する
 ii0 = Sheets.Index
  Sheets(ii0).Select

 後の機能は第20回を参照してください。
 フォルダ内のエクセルファイルへの対応は次回にします。