• ベストアンサー

【Excel VBA】コードの書き方『AまたはBだったら…』

Excel2003を使用しています。 マクロで、『A列-C列が0じゃなかったら、選択範囲をコピーする』という処理をしていますが、これを『A列-C列、または、Q列-S列が0じゃなかったら…』というふうにもうひとつ条件を加えたいのですが、どのように書いたらいいのでしょうか? コード(一部)は下記のようになっていますが、これでは間違っているようです。 マクロ勉強中ですので、ここはこういうふうに…と指摘していただけると助かります。お手数ですが、よろしくお願いします。    ・    ・    ・  i = Selection(1).Row  j = Selection(1).Column  k = Selection(Selection.Count).Row  l = Selection(Selection.Count).Column  With Sheets("○月")  For m = i To k  If (.Cells(m, "A") - .Cells(m, "C") <> 0 Or .Cells(m, "Q") - .Cells(m, "S") <> 0) Then  .Range(.Cells(m, j), .Cells(m, l)).Copy    ・    ・    ・

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.7

こんにちは。Wendy02です。 >教えていただいたコードで試してみましたが、やはり、結果が反映されませんでした。 If (.Cells(m, "A").Value - .Cells(m, "C").Value <> 0) Or _ (.Cells(m, "Q").Value - .Cells(m, "S").Value <> 0) Then それから後に、もう一度検証してみましたが、間違いはありません。 いくらミスの多い私でも、以下のように、変数を別途取って、これで間違えたら、どうしようもありません。 他の要因が混じっているのではありませんか? 一つは、他の場所を指しているとか? もしかしたら、最初から思っていることと違っているとか……(^^; 一旦、以下のようにして、変数で、ログを取ってみればよいと思います。 'Value プロパティは入れなくても、自動的に、Value 値になります。ただし、文字列も、数値として計算されます。 Dim a As Boolean '一応、宣言はしてください。 Dim b As Boolean Dim c As Boolean a = (.Cells(m, "A").Value - .Cells(m, "C").Value <> 0) b = (.Cells(m, "Q").Value - .Cells(m, "S").Value <> 0) c = a or b '結果:True で、「コピーする」ことになると思います。  True or False = True  False or True = True  True or True = True  False or False = False

rx-z5815
質問者

お礼

Wendy02 さん、こんばんは。 お手数かけて申し訳ありません。。。 今回は、コードの書き方には問題がなかったようなので、前にアドバイスをいただいたように、さらに細かく条件をつけることにしました。 何度も丁寧に回答してくださったおかげで、いろいろと勉強にもなりました。ありがとうございました! また、お世話になることもあるかと思いますが、よろしくお願いします。

その他の回答 (7)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.8

こんばんは。 新たな回答を、#2849639 側に書きました。 ロジックとしては、最終的にここの回答でよいと思いますが、もう少し、私は、考えればよかったです。ワークシートでは「マイナスは要注意」ですが、VBAでは、小数点すべてが要注意です。つまり、浮動小数点の問題を見逃していました。

rx-z5815
質問者

お礼

Wendy02 さん、こんにちは。 こちらにも書き込みしていただき、ありがとうございます。 今回の質問の場合は、整数のみしか扱わないのですが、ワークシートでは「マイナスは要注意」、VBAでは小数点すべてが要注意とは、恥ずかしながら知りませんでした(^^ゞ こちらの質問も、すぐに締め切らなくて良かったです。 ありがとうございました!

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんにちは。Wendy02です。 私の回答は、Not ステートメントで書いたけれども、"<>"でしたら、 間違えましたね。 以下は、特に、VBAの場合は、カッコをつけて変わることはありませんが、見易さのために、つけてみました。 If (.Cells(m, "A").Value - .Cells(m, "C").Value <> 0) Or _ (.Cells(m, "Q").Value - .Cells(m, "S").Value <> 0) Then

rx-z5815
質問者

お礼

Wendy02 さん、こんにちは。 再度の回答ありがとうございます。 教えていただいたコードで試してみましたが、やはり、結果が反映されませんでした。論理和・論理積って、よほど慣れていないと難しいのですね。 別件でのWendy02 さんのアドバイスにもありましたように、別の方法で処理することを検討してみようと思います。 ありがとうございました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

申し訳ないのですが、少し、割り込みさせていただきます。 通常、私は、Selection が、Rangeと確認できている場合は、それ自身が持っているプロパテイで、以下のようにして列と行のサイズを取得します。 With Selection  i = .Cells(1).Row  j = .Cells(1).Column  k = .Cells(.Count).Row  l = .Cells(.Count).Column End With 2次元配列でも良いのですが、配列は、縦横が逆になりますので、気をつけないと間違えてしまいます。 >Cells(m,"A") なお、ここの掲示板では、こういう書き方をされる方が多いようですね。可読性が高くなるからでしょうけれども、私は、VBAでは、ワークシートに対して、数式をR1C1方式にして読み出すことも多いし、Cellsに対しても、R1C1方式のほうが読みやすく感じます。(出力自体は、A1 にしてあれば、A1方式に変わります) 文字列を数値に置き換えるタイムラグなどは、微々たるものでしょうから、それ自体は問題にはならないはずですが、内部的には、おそらく読み替えているように思います。

rx-z5815
質問者

お礼

Wendy02 さん、おはようございます。 再度アドバイスをいただき、ありがとうございます。 以前、別のVBAに関する質問で、数式をR1C1方式で書いたコードを教えていただいたのを思い出し、もう一度見てみましたが、確かにR1C1方式のほうが読みやすく感じました。 ところで、この質問に対する回答(No.2)をいただいて、お礼を出した後に、わからないことが出てきてしまい、このアドバイス(No.5)をいただく前に、No.2の補足欄にその内容を書いて、再度質問させていただいたのですが、こちらの方は、どのようにしたらいいでしょうか?お手数ですが、よろしくお願いします<(_ _)>

  • Dxak
  • ベストアンサー率34% (510/1465)
回答No.4

UBound 関数は、配列の使用可能な最大値を調べる関数です UBound(Selection.Value,1) の様に、第一引数に配列変数、第二引数に次元数を指定します LBound 関数と、対になってて、こちらの場合は最小値を調べます Selectionの場合、1から始まるのでUBound 関数で最大値だけ調べてるわけですが・・・

rx-z5815
質問者

お礼

再度の回答ありがとうございます。 『UBound』は、配列の使用可能な最大値を調べる関数なんですね。 またひとつ勉強になりました。 >Selectionの場合、1から始まるのでUBound 関数で最大値だけ調べてるわけですが・・・ そうですね、最大値だけ調べれば事足りるってことですね。大変参考になりました。ありがとうございました。

  • Dxak
  • ベストアンサー率34% (510/1465)
回答No.3

条件ではなくて、 > k = Selection(Selection.Count).Row > l = Selection(Selection.Count).Column の部分では? 「Selection.Count」は、選択されたセルの個数 例えば「B3:C9」だと、14セル(7セル×2セル) k = i + UBound(Selection.Value,1) l = j + UBound(Selection.Value,2) で、大丈夫かな? 私も、「Cells(m, "A")」とか、気になるんだけど・・・Class Rangeだから、動くのかな?

rx-z5815
質問者

お礼

Dxak さん、こんにちは。 回答ありがとうございます。 No.2の Wendy02 さんの回答で、うまくいきました。 論理和・論理積の問題だったようで、[Or]を[And]に訂正することで、解決しました。 ちなみに、  If (.Cells(m, "A") - .Cells(m, "C") <> 0 And .Cells(m, "Q") - .Cells(m, "S") <> 0) Then という書き方でも、問題なく処理されました。 あと、教えていただいた >k = i + UBound(Selection.Value,1) >l = j + UBound(Selection.Value,2) で、『UBound』を初めて目にしたのですが、これはどういうことを表しているのでしょうか?よろしければ、教えていただけると、マクロ勉強中ですので、参考になります。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。Wendy02です。 >『A列-C列、または、Q列-S列が0じゃなかったら…』 たぶん、私の理解の範囲ですと、これは、「論理和・論理積」のことだと思います。 プログラムの基礎の基礎で出てきますが、恥ずかしいのですが、私も間違いそうになります。(^^;  「論理和」を、そのまま使っても反転しません。 If A Or B = True Then と論理和をそのまま、結果、True で、反転して、 If Not A Or Not B = True Then にした場合に、論理和のままですとうまくいきません。 これは、論理積にしなくてはなりません。 If Not A And Not B = True Then 一度、スモールサンプルで、その逆転を試してみると良く分かります。 '----------------------- Sub test() a = 0 b = 0 c = 1 d = 0 ' If (a - b <> 0) Or (c - d <> 0) Then  If (a - b <> 0) And (c - d <> 0) Then    MsgBox "True"  Else    MsgBox "False"  End If End Sub そういう私も、今は、別のプログラムの基礎の基礎から勉強中です。

rx-z5815
質問者

お礼

Wendy02 さん、こんにちは。 回答ありがとうございます。 ちょうど、No.1さんの回答を元にコードを変更して、マクロを実行してみたところ、結果が反映されていなかったので、また新たな疑問が出てきたところでしたが、Wendy02 さんの回答で、うまくいきました! Or より前の『A列-C列が0じゃなかったら』の部分の条件も無視(?)されて、単なる選択範囲のコピーになってしまい、困っていたところでしたので、本当に助かりました(*^^*)

rx-z5815
質問者

補足

何度もすみません。 お礼を出した後、わからないことが出てきたので、補足欄を使わせていただきます。 先程、 Or を And に訂正して、うまくいったと思っていたのですが、ちゃんと結果が反映されない場合が出てきてしまい…というか、 And に訂正したので当然のことなのかもしれませんが、単純に質問文に記載しているコードの Or を And 訂正するだけではダメだったのでしょうか? 結果が反映されなかったときの選択範囲を見てみると、A列とC列は含まず、Q列とS列を含む選択範囲なのですが、その範囲内のA列-C列が0の行がコピーされていませんでした。 また、 And を Or に戻してみたり、といろいろ試してみたのですが、どうしたらいいのかわかりません。何度も申し訳ありませんが、教えていただけないでしょうか?

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

If (.Cells(m, 1) - .Cells(m, 3) <> 0 Or .Cells(m, 17) - .Cells(m, 19) <> 0) Then × Cells(m,"A") ○ Cells(m,1)

rx-z5815
質問者

お礼

chie65536 さん、こんにちは。 回答ありがとうございます。 当初の『A列-C列が0じゃなかったら…』という条件のみのときは、  If .Cells(m, "A") - .Cells(m, "C") <> 0 Then という書き方でも、問題なかったようですが、これはどうしてなのでしょうか?もし、よろしければ、教えていただけると嬉しいです。

関連するQ&A

専門家に質問してみよう