2009年9月22日火曜日

第129回目 計算式の分析での追加テクニック

○第129回目 計算式の分析での追加テクニック

 いろいろと作業を行っていますと、当然想定外のことが起こって、マクロの修正を余儀なくされます。その中で、紹介しておくべきことがありました。
 それは、セル群に名前をつけていて、その名前を使って計算式を記述しているという場合の処理です。
 あるシートのある列(T列とします)全体を、qqqという名前で定義しています。
 そして計算式は、
 =qqq*12 と記述しています。
 あれおかしいですね。計算式は一つのセルなのに、qqqはセル群ですね。どこをもってくるのでしょうか?
 この場合は、計算式が入るセルの行数と同じ行のものが持ってこられます。
 計算式のセルがB20であれば、T20*12という計算結果となります。lookup関数のような結果となります。すると、このような計算式の記述のほうが、簡潔でかつ、わかりやすくなりますね。

 ※名前をつけたセルを使うという例は、自分としてはあまりないので、多くのケースを網羅しているとはいえませんということを最初に断っておきます。

 続けますと、そのように計算式を入れたところ、後で計算式を見てみると、なんと前にブック名がくっついているのです。
 =book12!qqq*12

 さて、テーマは、book12!qqqという場所にどう飛んでいったらいいのかということです。
  答えは単純で、
  Range("qqq").select です。
  これで、該当するシートのT列が選択されます。
  まずは、簡単ですね…、と思いきやこの処理が出来ずにエラーになる場合があるのです。100%正しい理由はわかりません。
 ・シートが違っている時に起きる。
 ・名前がつけられたすべてのセル群についてエラーになるのではない。
 解明できなかったので、同じシートであれば、飛んでいける点を採用しました。その名前があるシートを見つけ、そこで飛べばいいのではないかということです。
 エラーレジーム機能(エラーが生じた場合、次の行に飛びそこから実行)を使って、一番目のシートから試してみるのです、エラーであれば次のシートで試す。エラーでなければそこが正解。

 コーディングでのポイントは次のとおりです。
  On Error GoTo ErrorTrap

For k = 1 To ii_max9 '名前付きセルのあるシートを探す
Sheets(k).Select
errflag = 10
Range(p_xy_A1(i)).Select
If errflag <> 109 Then Exit For
Next
aaa4 = Selection.Address
gyo22 = Selection.Row
retu22 = Selection.Column

  ErrorTrap:
  errflag = errflag * 10 + 9
  Resume Next

 次は行数の把握です。
 これは、前にもいったとおり、計算式のあるセルの行にします。
 問題は、一つのセルに名前がついていた場合です。この場合は、行を求めるということは不要となりますね。
 複数セルに名前がついている場合は、
 Cells(計算式のあるセルの行,retu22)を使ってコーディングをします。

 以上のことを盛り込むことで、名前がつけれたセル群に対する処理は可能となります。

 ※名前がついた場所へのジャンプ処理でのマクロ。参考まで。
Application.Goto Reference:="qqq"


 ※内容整理のためにしばらく休みます(2ヶ月ほど)。

2009年9月6日日曜日

第128回目 計算式の分析;if文(その2)

○第128回目 計算式の分析;if文(その2)

 どこのカンマを本当のものと見極めるか。
 夢を見ました。大きな長細い皿の上に大小の皿が乗っかっています。皿の上に、また皿が乗っかっているものがあります。皿の中には豆粒の大きさのものがあります。二つほど入っています。よく見ると、一番下の皿に直接乗っかっている豆粒状のものは2つあります。他のものは上の皿に乗っていました。
 これです。皿はカッコと思えば、一番下の皿に直接乗っかっているものが求めるものになるのではないか、と思われます。
 これをマクロで書けばいいのです。
 ユーリイカ!
 というわけで、他の皿(カッコ)に乗っかっていないものを探します。
 カッコの始まりの位置と終わりの位置がわかりますので、その中に含まれているカンマかどうかがわかります。
 これで解決しました。
 あとはできるはずです。

=IF(lookup(xxx,xxx:xxx,xxx:xxx)>0.1,If(xxx>0.1,round(B23*1.234,2),lookup(xxx,xxx:xxx,xxx:xxx)),sumproduct(xxx:xxx,xxx:xxx))
 
 IF(の終わりの位置…4
 IF(文の後の)の位置…123
 IF(文の中の()1の位置…11と31
 IF(文の中の()2の位置…39と94
 IF(文の中の()3の位置…53と65
 IF(文の中の()4の位置…73と93
 IF(文の中の()5の位置…106と122
 カンマの位置…15,23,36,47,63,77,85,95,114
 これらの情報から、該当するカンマは36と95となります。
 この位置で切り分ければいいことになります。

 ということでこの問題は解決しました。

 なに、カッコのランク付けのやりかたがわからない?
 ○第126回目 計算式の分析;if関数(その前に)の後半をみてください。
 考え方は次のとおりです。
 1.最初の(を見つける。
 2.次の(を見つける。
 3.1以降の最初の)を見つける。
 4.1と2の間に3があるか。ある場合は、1と3が対応します。
 4-2.対応したら、3の位置の後から、1以下を繰り返えす。
 5.ない場合は、2のカッコを1とおき、2-4の操作をカッコがなくなるまで繰り返します。
 これによりランク1のカッコが見つかりますので、該当したカッコを別の記号に置き換えて、1に戻って1以下の処理をカッコがなくなるまで繰り返します。それぞれ5が終わった段階で、ひとつのレベルのもののカッコが決まっていきます。
 カッコの位置を探していくときに、前の部分を切り落として探していきますが、最終的には全体でみなければいけないので、全体の位置をも把握しながらということが、注意点でしょうか。