• 締切済み

すっきりしたソースを書くには

エクセルVBA初心者です。 セルAの4行目から27行目までの範囲でセルDとFとGの値を消すというソースを作りたいのですが、以下のようなソースを何十個もつくるのは大変なので、もっとすっきりとした書き方はありますか? ご指導のほどお願いします。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Cells(4, 1).Value = "" And Cells(4, 4).Value <> "" Then Cells(4, 4).Value = "" End If If Cells(4, 1).Value = "" And Cells(4, 6).Value <> "" Then Cells(4, 6).Value = "" End If If Cells(4, 1).Value = "" And Cells(4, 7).Value <> "" Then Cells(4, 7).Value = "" End If End Sub

みんなの回答

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

(1)規則性を見つけて、繰り返し処理に持ち込む。 本質問はこのケースだろう。 繰り返しが不規則で、余り多数でなければ、テーブルにそのデータを持つ。 (2)IF文の繰り返しの羅列が多くなる場合は、何か別の良い方法は無いかと考え込む。本質問もそうなのだろう。 (3)問題を分割するなど、思考力を磨く 本質問でもCells(4, 1).Value とANDで聞いている条件は別々に 考えられるだろう まづCells(4, 1).Value  これが成り立たないと全体がダメだから。 その後Cells(4, X).Value を考えるなど。 (3)(繰り返し比較などの要素は考える上では潜在するが)それを消したメソッドやプロパティを日ごろから勉強する。 例えばFind(こういうのはAかAかと、IF思考の面は有るが表にはIFは出ない)、 Selection.SpecialCells(xlCellTypeBlanks).Select こういうのは日ごろから勉強してないと、絶対でてこない。 質問者はコードのテクニックだけに頭が行って、 エクセルの機能 VBAでもメソッド・プロパティ・ステートメント・関数の個々の機能 使い方 の重要性に頭が行って無いのでは。 1、2ヶ月ですっきりしたコードはかけません。 経験・習い(まね)を増やすのみ。 それに直ぐ、人に聞かない態度も大切と思う(自分で考えなくなる)。

ytsugie
質問者

お礼

ありがとうございます。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.1

第一になぜ  Worksheet_SelectionChange イベントなのでしょうか? 即時に反応するというのなら、  Worksheet_Change では? 一方で、たとえ誤入力でも、警告も無しにいきなり入力値が消えたりすると、ユーザー心理としては何が起きたのか分からず、もう一度同じ入力を繰り返すということをやりそうですし、あるいはムカつく人もいそうな気がしますが… それはまぁ置いておいて… Changeイベントで実行すると仮定して、それまでのシートの状態が管理された状態になっているとするなら、新しく入力されたものだけをチェックすればよいことになります。 入力された(変更された)セルは引数Targetで得られますので、その行だけをチェックすればよいことになります。 また、 Cells(4, 1).Value = "" And Cells(4, 4).Value <> "" は正確に条件を判定しようとしていますが、Cells(4, 4).Valueの値がどうであれ、Cells(4, 4)は空白にしてしまうので前半の条件だけで十分です。 (D4に値があれば空白に、D4に値がない(空白)の時も空白にしてしまう) ということで… Private Sub Worksheet_Change(ByVal Target As Range) Dim r As Long r = Target.Row If Cells(r, 1) = "" Then  Application.EnableEvents = False  Cells(r, 4) = ""  Cells(r, 6).Resize(, 2) = ""  Application.EnableEvents = True End If End Sub みたいにできます。 (ただし、上のままでは「セルAの4行目から27行目までの範囲で」という条件が反映されていません。) また、Changeイベントはシートのどこのセルの値が変わっても発生するので、そのたびにサブルーチン全体の処理していたのでは無駄なので、最初に処理する対象(範囲)であるかを早めに判断して、対象外の場合はExit Subなどで抜け出してしまうというのが一般的です。 というわけで、4~27行でD、EF列の範囲なのかどうかを判断する処理を加えておくのがよろしいでしょう。2行(または3行)ほど追加すれば可能になると思いますので、その辺の修正は御自分でなさってください。

関連するQ&A

  • セル値

    すみません エクセルVBA勉強中のものですが、セルA1とA2がブランクだったら、セルB1に”あ”を表示するという式を作ったのですがうまく動いてくれません ご指導のほどお願いします。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Cells(1, 1).Value <> "" & Cells(2, 1).Value <> "" Then Cells(1, 2).Value = "あ" End If End Sub

  • マクロの疑問

    Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Address <> "A2" Then Range("A2").Select End If End Sub とすると、どのセルを選んでもA2に飛ぶのに、 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Address = "A3" Then Range("A2").Select End If End Sub とすると、A3を選んでも全く移動しないのはなぜでしょうか。 なにか落とし穴がありそうで。。。 よろしくお願いします。

  • SelectionChangeイベント 文字列エラ

    エクセルvbaなのですが セルをクリックしたときに、該当する値ならメッセージを表示させる際に Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Value = 1Then MsgBox "" End If End Sub ならエラーにならずに動くのに Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Value = "運賃" Then MsgBox "" End If End Sub のように文字列にすると、型が一致しません。 と言うエラーになります。 If Target.Value = "運賃" Then の時でも、空白セルや数値が入ったセルをクリックした際はエラーになりません。 どのような型にすればいいのでしょうか? 実際、「運賃」と言う値が入ってるセルをクリックしても同じエラーが発生します。

  • VBAでエラートラップがうまくいきません。

    VBAで次のようなプロシージャを実行してみました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)   If Target.Value = " " Then          ~コード~   END IF END SUB すると複数のセルが選択されるとエラーがでます。そこで次のようにしてみました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)   On Error GoTo エラー処理   If Target.Value = " " Then     On Error GoTo 0           ~コード~   END IF   EXIT SUB エラー処理:   EXIT SUB END SUB ところがこれでもやっぱりIF文のところでエラーがでます。 当方初心者でなぜエラーがでるのかわかりません。 わかりやすくご教授ください。 よろしくお願いします。

  • 複数のセルを選択しているかを取得するプロパティは?

    SelectionChangeイベントで 複数のセルを選択しているかを取得するプロパティってないのでしょうか? 今は、 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Len(Target.Address) > 5 Then MsgBox "複数のセルが選択されています" End If End Sub こうしていますが、行数が多くなると文字も多くなってしまうので、このコードでは対応できません。 Rangeオブジェクトに何個セルが入ってるかを知る方法はありますか? ウォッチのTargetのcellsを見ても、どう見ればいいのかわかりません

  • シートのイベント VBA

    シートをクリックしたらシートをクリアしたいのですが クリックするセルがA1の場合は、マクロを実行させたくないのですが 下記のコードだとエラーになってしまいます。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Not Target.Range = Range("a1") Then Cells.Clear End If End Sub ”Range("a1")でなければ、Cells.Clearする” にはどうすればいいですか?

  • こんばんは、watabe007さん。

    961awaawaです。 >シートモジュールに貼り付けてお試しください。 Private Sub Worksheet_Change(ByVal Target As Range) With Target If Intersect(.Cells, Range("L:M")) Is Nothing Then Exit Sub If .Row < 3 Or .Value = "" Then Exit Sub If Not IsNumeric(.Value) Then Exit Sub .Offset(, 3).Value = Cells(.Row, .Value).Value End With End Sub というソースを作って頂いたのですが、既に各sheetにprivate sub からなるソースが入ってましてコンパイルエラー(名前が適切ではありません Worksheet_Change)となります。他に方法等頂けましたらありがたいです。

  • エクセル マクロを利用して繰り返して入力する方法

    マクロでA1B1C1D1E1F1セルに入力しF1入力後A2B2C2D2E2F2と 下方向へ繰り返し800行くらいまで入力し、それとB列はスキップしたいのですが下記の方法で別々のシートでは うまくいくのですが同じシ-ト内ではエラ-になってしまいます 次の行への移動 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Column = 7 Then Cells(Target.Row + 1, 1).Select End If End Sub B列のスキップ Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Range("G1") <> "" Then If Target.Column = 2 Then Target.Offset(0, 1).Select End If End If End Sub どなたかご存じの方教えて下さい

  • エラーが出てしまいます。

    特定の列(C列)に日付が入力されると同じ行の違う列に月名が入力されるマクロをt食ってみました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Column = 3 Then Cells(Target.Row, 10) = Month(Target.Value) End If End Sub しかしC列の一つのセルに入力したときはきちんと作動したのですが、C列の複数セルを選択したときにエラーが出てしまいました。 このエラーを回避する方法はあるのでしょうか。

  • Excel VBA 他のシートに演算結果を入れたい

    例えば、A~Dというシートのいずれかのo1セルに数値を入力すると、演算結果がp1に入る場合。 A~Dのどのシートでもo1に入力したら、Z!p1にp1の値を放り込みたいのです。 で、以下のようなコードを書いたのですが、上手くいきません。 因みに、セルの移動方向はオプションで「右方向」に設定してあります。 ※結果としてセルの移動を認識していないのか、まったく無反応です。 ※Range("Z!$P$1") =… の行にブレークポイントを設定しても、引っかかりません。 何が悪いのかお教え頂ければ幸甚です。 >違うシートには代入できない… ってことでしょうか? Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Address = "$P$1" Then Range("Z!$P$1") = Range("$P$1") End If End Sub ※なお、出典元のSubは以下の様なもので、正常に動作していました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) If Target.Address = "$A$1" Then Range("B1") = Range("B1")+1 End If End Sub