- ベストアンサー
【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 ・ ・ ・
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。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
その他の回答 (7)
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。 新たな回答を、#2849639 側に書きました。 ロジックとしては、最終的にここの回答でよいと思いますが、もう少し、私は、考えればよかったです。ワークシートでは「マイナスは要注意」ですが、VBAでは、小数点すべてが要注意です。つまり、浮動小数点の問題を見逃していました。
お礼
Wendy02 さん、こんにちは。 こちらにも書き込みしていただき、ありがとうございます。 今回の質問の場合は、整数のみしか扱わないのですが、ワークシートでは「マイナスは要注意」、VBAでは小数点すべてが要注意とは、恥ずかしながら知りませんでした(^^ゞ こちらの質問も、すぐに締め切らなくて良かったです。 ありがとうございました!
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。Wendy02です。 私の回答は、Not ステートメントで書いたけれども、"<>"でしたら、 間違えましたね。 以下は、特に、VBAの場合は、カッコをつけて変わることはありませんが、見易さのために、つけてみました。 If (.Cells(m, "A").Value - .Cells(m, "C").Value <> 0) Or _ (.Cells(m, "Q").Value - .Cells(m, "S").Value <> 0) Then
お礼
Wendy02 さん、こんにちは。 再度の回答ありがとうございます。 教えていただいたコードで試してみましたが、やはり、結果が反映されませんでした。論理和・論理積って、よほど慣れていないと難しいのですね。 別件でのWendy02 さんのアドバイスにもありましたように、別の方法で処理することを検討してみようと思います。 ありがとうございました。
- Wendy02
- ベストアンサー率57% (3570/6232)
申し訳ないのですが、少し、割り込みさせていただきます。 通常、私は、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方式に変わります) 文字列を数値に置き換えるタイムラグなどは、微々たるものでしょうから、それ自体は問題にはならないはずですが、内部的には、おそらく読み替えているように思います。
お礼
Wendy02 さん、おはようございます。 再度アドバイスをいただき、ありがとうございます。 以前、別のVBAに関する質問で、数式をR1C1方式で書いたコードを教えていただいたのを思い出し、もう一度見てみましたが、確かにR1C1方式のほうが読みやすく感じました。 ところで、この質問に対する回答(No.2)をいただいて、お礼を出した後に、わからないことが出てきてしまい、このアドバイス(No.5)をいただく前に、No.2の補足欄にその内容を書いて、再度質問させていただいたのですが、こちらの方は、どのようにしたらいいでしょうか?お手数ですが、よろしくお願いします<(_ _)>
- Dxak
- ベストアンサー率34% (510/1465)
UBound 関数は、配列の使用可能な最大値を調べる関数です UBound(Selection.Value,1) の様に、第一引数に配列変数、第二引数に次元数を指定します LBound 関数と、対になってて、こちらの場合は最小値を調べます Selectionの場合、1から始まるのでUBound 関数で最大値だけ調べてるわけですが・・・
お礼
再度の回答ありがとうございます。 『UBound』は、配列の使用可能な最大値を調べる関数なんですね。 またひとつ勉強になりました。 >Selectionの場合、1から始まるのでUBound 関数で最大値だけ調べてるわけですが・・・ そうですね、最大値だけ調べれば事足りるってことですね。大変参考になりました。ありがとうございました。
- Dxak
- ベストアンサー率34% (510/1465)
条件ではなくて、 > 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だから、動くのかな?
お礼
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)
こんにちは。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 そういう私も、今は、別のプログラムの基礎の基礎から勉強中です。
お礼
Wendy02 さん、こんにちは。 回答ありがとうございます。 ちょうど、No.1さんの回答を元にコードを変更して、マクロを実行してみたところ、結果が反映されていなかったので、また新たな疑問が出てきたところでしたが、Wendy02 さんの回答で、うまくいきました! Or より前の『A列-C列が0じゃなかったら』の部分の条件も無視(?)されて、単なる選択範囲のコピーになってしまい、困っていたところでしたので、本当に助かりました(*^^*)
補足
何度もすみません。 お礼を出した後、わからないことが出てきたので、補足欄を使わせていただきます。 先程、 Or を And に訂正して、うまくいったと思っていたのですが、ちゃんと結果が反映されない場合が出てきてしまい…というか、 And に訂正したので当然のことなのかもしれませんが、単純に質問文に記載しているコードの Or を And 訂正するだけではダメだったのでしょうか? 結果が反映されなかったときの選択範囲を見てみると、A列とC列は含まず、Q列とS列を含む選択範囲なのですが、その範囲内のA列-C列が0の行がコピーされていませんでした。 また、 And を Or に戻してみたり、といろいろ試してみたのですが、どうしたらいいのかわかりません。何度も申し訳ありませんが、教えていただけないでしょうか?
- chie65536
- ベストアンサー率41% (2512/6032)
If (.Cells(m, 1) - .Cells(m, 3) <> 0 Or .Cells(m, 17) - .Cells(m, 19) <> 0) Then × Cells(m,"A") ○ Cells(m,1)
お礼
chie65536 さん、こんにちは。 回答ありがとうございます。 当初の『A列-C列が0じゃなかったら…』という条件のみのときは、 If .Cells(m, "A") - .Cells(m, "C") <> 0 Then という書き方でも、問題なかったようですが、これはどうしてなのでしょうか?もし、よろしければ、教えていただけると嬉しいです。
お礼
Wendy02 さん、こんばんは。 お手数かけて申し訳ありません。。。 今回は、コードの書き方には問題がなかったようなので、前にアドバイスをいただいたように、さらに細かく条件をつけることにしました。 何度も丁寧に回答してくださったおかげで、いろいろと勉強にもなりました。ありがとうございました! また、お世話になることもあるかと思いますが、よろしくお願いします。