計算式を駆使しよう。

マクロを組むとき、式を組み合わせて計算をすると、いろいろなことができるようになります。
今までは、IF文で分岐させていたことも、計算式を使うと端的に汎用性があるものにすることができます。

1.「¥」や「Mod」を使う。

今まで学校で習ってきた計算には、たし算・ひき算・かけ算・わり算があります。
しかしマクロを組む上で、さらに重要になってくるのが、 や Mod です。
普通のわり算は答えを小数点で出しますが、マクロを組む上では小数点以下まで計算することはあまり意味がありません。
そこで、普通のわり算の代わりに、商と余りを求める ¥ と Mod を使います。

 記号 計算の意味   計算 答え 
¥   わり算をした商を求める  11 ¥ 3  3
 Mod  わり算をした余りを求める  11 Mod 3  2

これを使うと、次のようなことができます。

 「¥」を使う
Sub a()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = R \ 3 ←@
  Next R

End Sub
 
「¥」を使って、同じ数字を連続して書き込む処理をしています。


@ Rを3で割った商を、セルに書き込みます。
 
Sub b()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = (R - 1) \ 3 ←@
  Next R

End Sub
@ 上のマクロは、セルに書き出した数字の並びがそろってないので、見栄え良くなるよう、計算式を改良しました。
Sub c()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = (R - 1) \ 3 + 1 ←@
  Next R

End Sub
@ セルの行列の番号が1〜なので、それに合わせて、1以上の数字が連続するよう、計算式を改良しました。
 「Mod」を使う  
Sub d()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = R Mod 3 ←@
  Next R

End Sub
 
同様に、「Mod」を使って、同じ数字を繰り返して書き込んでいます。


@ Rを3で割った余りを、セルに書き込みます。
Sub e()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = (R - 1) Mod 3 ←@
  Next R

End Sub
 
@ 上のマクロは、1・2・0という順番で循環しているので、これも見栄えが良くなるよう、計算式を改良しました。
Sub f()

  Dim R As Integer

  For R = 1 To 9
    Cells(R, 1) = (R - 1) Mod 3 + 1
  Next R

End Sub
 
@ さらにセルの行列の番号と合うように、1〜で始まるように、計算式を改良しました。 

2.三マス方眼を作ってみる。

「¥」や「Mod」を組み合わせると、数字を方眼の中に順番に入れていくこともできます。

【数字をもとにして】  数字(n)の行と列の位置を計算して、その場所に書き込む方法  
  Sub 三マス方眼A()

  Dim R As Integer ←@
  Dim C As Integer ←A
  Dim n As Integer ←B

  For n = 1 To 9 ←C
    R = (n - 1) \ 3 + 1 ←D
    C = (n - 1) Mod 3 + 1 ←E
    Cells(R, C) = n ←F
  Next n

End Sub
 
@ セルの行番号を入れる変数

A セルの列番号を入れる変数

B 数字を入れる変数

C 1〜9まで行う。

D 数字から、行番号を計算する。

E 数字から、列番号を計算する。

F 計算した場所に、数字を書き込む。 
【行と列の位置をもとにして】  行(R)と列(C)を決めて、その場所に入る数字を計算して出して書き込む方法
Sub 三マス方眼B()

  Dim R As Integer ←@
  Dim C As Integer ←A

  For R = 1 To 3 ←B
    For C = 1 To 3 ←C
      Cells(R, C) = (R - 1) * 3 + C ←D
    Next C
  Next R

End Sub
 
@ セルの行番号を入れる変数

A セルの列番号を入れる変数

BC 縦横が三マスずつなので

D 数字を計算して出して、それを書き込む。 
 【変数を使って】  変数(n)を使ってカウントし、その結果を書き込む方法 
Sub 三マス方眼C()

  Dim R As Integer ←@
  Dim C As Integer ←A
  Dim n As Integer ←B

  For R = 1 To 3 ←C
    For C = 1 To 3 ←D
      n = n + 1 ←E
      Cells(R, C) = n ←F
    Next C
  Next R

End Sub
 
@ セルの行番号を入れる変数

A セルの列番号を入れる変数

B カウンタ

CD 縦横が三マスずつなので

E 1つずつカウントしていく。

F カウントした数字を書き込む。 
どちらでも、三マス方眼を作ることはできますが、現実的によく使われるやり方は、数字から位置を割り出す方です。  

3.表の起点の位置を求める。

上の場合は、数字同士がきちんと1対1で対応しているので比較的計算しやすいのですが、時としてそうでない場合もマクロを組んでいくと出てきます。
次の表は、数独の表ですが、マクロで処理をさせようと思うと、大マスの起点の位置を知りたいことがよく出てきます。
それを求めるには、どうしたらいいのか、考えていきます。
 ※ 大マスとは、縦横3マス合計9マスの太線の枠のこと

Sub t1()

  Dim R As Integer
  Dim C As Integer

  R = ActiveCell.Row ←@
  C = ActiveCell.Column ←A

  MsgBox R & ":" & C

End Sub
この場合は、
@とAでアクティブなっているセルの
行番号と列番号を求めています。

しかし、大マスの起点である 
(7:1)の位置を求めたいときに、
どうしたらいいのでしょう?
Sub t2()

  Dim R As Integer
  Dim C As Integer
  Dim rr As Integer
  Dim cc As Integer

  R = ActiveCell.Row
  C = ActiveCell.Column

  Select Case R ←@
    Case Is <= 3
      rr = 1
    Case Is <= 6
      rr = 4
    Case Else
      rr = 7
  End Select

  Select Case C ←A
    Case Is <= 3
      cc = 1
    Case Is <= 6
      cc = 4
    Case Else
      cc = 7
  End Select

  MsgBox rr & ":" & cc

End Sub
 
このマクロでは、@とAで条件分岐を
使ってみました。

これでも目的は達成できていますが、
ずいぶんと行数を使ってしまいました。
  Sub t3()

  Dim R As Integer
  Dim C As Integer
  Dim rr As Integer
  Dim cc As Integer

  R = ActiveCell.Row
  C = ActiveCell.Column

  rr = ((R - 1) \ 3) * 3 + 1 ←@
  cc = ((C - 1) \ 3) * 3 + 1 ←A

  MsgBox rr & ":" & cc

End Sub
 
今度は、計算式を使ってみました。

@ ここで、大マスの起点になる
  行位置を計算します。

A ここで、大マスの起点になる
  列位置を計算します。


ポイントは、「¥」を使うことで、
7・8・9を同じグループと見なしたことです。

4.表の排他的な位置を求める。

先ほどの例では、大マスの起点の位置を計算で求めてきました。
それでは、排他的な位置を求めるには、どうしたらいいのでしょうか?
つまり、8行めを選択しているときには7行目と9行目を求める、9行目を選択しているときには7行目と8行目を求めるような時。

Sub t1()

  Dim R As Integer
  Dim C As Integer

  R = ActiveCell.Row ←@
  C = ActiveCell.Column ←A

  MsgBox R & ":" & C

End Sub
この場合は、
@とAでアクティブなっているセルの
行番号と列番号を求めています。

しかし、大マスの中の他の行である 
7行目や9行目を求めたいときに、
どうしたらいいのでしょう? 
Sub t4()

  Dim R As Integer
  Dim R2 As Integer
  Dim R3 As Integer

  R = ActiveCell.Row ←@

  Select Case R ←A
    Case Is = 1
      R2 = 2
      R3 = 3
    Case Is = 2
      R2 = 3
      R3 = 1
    Case Is = 3
      R2 = 1
      R3 = 2
    Case Is = 4
      R2 = 5
      R3 = 6
    Case Is = 5
      R2 = 6
      R3 = 4
    Case Is = 6
      R2 = 4
      R3 = 5
    Case Is = 7
      R2 = 8
      R3 = 9
    Case Is = 8
      R2 = 9
      R3 = 7
    Case Is = 9
      R2 = 7
      R3 = 8
  End Select

  MsgBox R & ">" & R2 & ":" & R3

End Sub
@ 行だけで考えてみます。

@ Select Case文を使って、分岐処理をしました。



8を選ぶと、9と7が返ってきます。

これでも目的は達成できていますが、
実際に使えるようにするには、
列でも同じことをやらなければなりません。
 
となると、ちょっと長すぎます。
  Sub t5()

  Dim R As Integer
  Dim R2 As Integer
  Dim R3 As Integer
  Dim rr As Integer

  R = ActiveCell.Row

  rr = ((R - 1) \ 3) * 3 + 1 ←@

  R2 = R + 1 ←A
  R3 = R + 2 ←B

  R2 = (R2 - 1) Mod 3 + rr ←C
  R3 = (R3 - 1) Mod 3 + rr ←D

  MsgBox R & ">" & R2 & ":" & R3

End Sub
 
@ 大マスの起点の位置を計算します。

A 暫定的に、次の数字を求めます。

B 暫定的に、次の次の数字を求めます。

C 大マスの中だけの位置を計算してから、起点の位置を加えて、正しい位置を出します。

ちなみに、大マス中だけの位置は、上から0・1・2です。

D ここも同じように計算します。