• 締切済み

VBA 範囲選択時エラー

Private Sub Worksheet_SelectionChangeのVBAでA列B列C列でワンクリックで文字が入力できるように設定致しました。 その後、A列からC列を範囲選択してDeleteするとデバック 「実行時エラー  型が一致しません」と出てしまいます。業務上、そのセルのデータは一気に消したいので困っております。どなたか分かる方よろしくお願い致します。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim rng As Range, rng_1 As Range, rng_2 As Range Application.EnableEvents = False Set rng_1 = Range("H17:H100") Set rng_2 = Range("I17:I100") Set rng_3 = Range("J17:J100") Set rng_4 = Range("K17:K100") Application.EnableEvents = True Set rng = Intersect(Target, rng_1) If Not rng Is Nothing Then Cancel = True If Target.Value = "" Then Target.Value = "(1)" Else Target.Value = "(1)" End If Else Set rng = Intersect(Target, rng_2) If Not rng Is Nothing Then Cancel = True If Target.Value = "(2)" Then Target.Value = Empty Else Target.Value = "(2)" End If Else Set rng = Intersect(Target, rng_3) If Not rng Is Nothing Then Cancel = True If Target.Value = "(3)" Then Target.Value = Empty Else Target.Value = "(3)" End If Else Set rng = Intersect(Target, rng_4) If Not rng Is Nothing Then Cancel = True If Target.Value = "(4)" Then Target.Value = Empty Else Target.Value = "(4)" End If End If End If End If End If End Sub

みんなの回答

回答No.3

(前の回答からのつづき) 6■代替え案 について 上記1■~5■への対策としてですが、  →1■   Targetが複数セルである場合にも(単一にも)備えて   Target内のセルをループする書き方をします。  →2■3■   _BeforeRightClick イベントを使ったものを提案します。   【選択セル範囲の変更時】ではなく   【選択セル範囲を右クリックした時】に替えます。   単一セルについては、左クリックでの選択を省略して   直接右クリックで作動します。   複数セルについては、一旦選択してから右クリックです。 なんで右クリック?という疑問があるかも知れませんが、 _SelectionChange イベントはクリックとは関係ない旨、2■で 説明しました。また、【選択セル範囲の変更】は様々な契機で 起こるので、処理を開始するきっかけとして、意図した通りの タイミングを捉えるのも難しい、ということも。 そこで、趣旨にもっとも近い操作性を実現できるであろうと 思われるのが、_BeforeRightClick イベント、ということです。  →4■   "(1)"でも、-1でも、どちらでもいいように、   セル値の取得については、.Valueプロパティの代りに   .Textプロパティを用いて、表示値をみるようにします。   誤作動を防ぐ為の仕組みを用意しましたが、   数値なのか文字列なのかは、そちらでご判断の上、   シート上での統一を、別途実践なさってください。  →5■   たぶん、大体は当たっているような気はしますが、   細かい仕様までは、実際に動かしてみないと   当のご本人も見当つかない面もあるでしょうから、   こちらからも敢えて明示しません。   やってみる内に、ここはこうしたいとか、   新たなニーズも出てくるでしょうから、   模索、検討してみてください。 一応、複数セルに対する処理については、 先頭(左上)セルのみで判別する少し変わったことをしています。 でもこれは、一度間違っても、 再度右クリックすれば、目的値に辿りつくように、という意図です。 以下、試す時は、 既存シートの_SelectionChange をコメントブロック等で一旦無効にするか 新規シートのシートモジュールに貼り付けるか 処理の重複が無い状態を担保するようにしてください。   処理対象として扱うセル範囲の限定の仕方   【Cancel引数】の扱い方   Application.EnableEvents プロパティの扱い方   セルを総当たりする For Each ループの扱い方 などは、努めて教科書的に書いていますので、 ご参考になることあれば、、、。 ' ' // Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) Dim myTarget As Range, c As Range Dim vTarget, flg As Boolean   Set myTarget = Intersect(Range("H17:K100"), Target)   If myTarget Is Nothing Then Exit Sub ' 処理対象のセル範囲外なので、処理を止めて、抜ける   Cancel = True   vTarget = "(" & myTarget(1).Column - 7 & ")" ' [H]:"(1)",[I]:"(2)",[J]:"(3)",[K]:"(4)"   flg = myTarget(1).Text = vTarget ' "消す"のか"値を設定する"のか判別したフラグ   Application.EnableEvents = False ' Worksheet_Change イベントの発行抑止   For Each c In myTarget     vTarget = "(" & c.Column - 7 & ")" ' [H]:"(1)",[I]:"(2)",[J]:"(3)",[K]:"(4)"     If flg Then       c.Value = Empty     Else       c.Value = vTarget     End If   Next   Application.EnableEvents = True ' Worksheet_Change イベントの発行抑止を解除 End Sub ' ' //

回答No.2

こんにちは。 少し長くなりますが、大事なポイントで誤解があるようなので、 ひとつずつ説明して、最後に提案を添えます。 解答者側の都合を気にして急ぐような必要はありませんので、 じっくり考えてみて貰えるといいのですが。 1■実行時エラーの原因 について > その後、A列からC列を範囲選択してDeleteすると > デバック 「実行時エラー 型が一致しません」と出てしまいます。 原因は、↓ここ。 > If Target.Value = "" Then Targetが単一セルである場合、にのみ成立する判別式です。 例えば、[H17]がTargetであれば、 [H17]に設定されたひとつの値を評価しますから、 判別式 Target.Value = "" は[True|False]で結果を返します。 Targetが複数セルである場合には、   左辺 Target.Value は配列になります。   配列 = "" という比較式は、   成り立ちませんから、   (どれと比較するのか意味を成しませんから)   「実行時エラー 型が一致しません」 という結果になります。 続いて、これも誤解が多いのですが、   Targetが[セルの結合]を適用したセルである場合にも   Target単一セルではなく、   Targetが複数セルである場合にあたりますので、   同様の結果に陥ります。 このケースで、単にエラーを回避する為だけの対策としては、   If Target(1).Value = "" Then のように、先頭にある単一セル の値をみるようにすることで、 簡易的な対処は可能です。 但しこれは厳密には正しい判別法ではありませんので、 プロは絶対やらないけど、個人的にはこれで十分と思った場合 に限って有効なやり方と捉えていてください。 或いは、Targetが単一セルである場合だけ処理したい、 ということであれば、   If Target.Count > 1 Then Exit Sub と、先頭に1行書き加えるだけで、 複数セル選択時をエスケープさせることはできます。 この方法は初級の教科書にも出てくる基本的なやり方ですが、 複数セル範囲選択時を除外する、ということが妥当な場面なのか、 正しい判断が必要になります。 2■_SelectionChange イベント について > Private Sub Worksheet_SelectionChangeのVBAで > A列B列C列でワンクリックで文字が入力できるように設定致しました。 誤解があるように思うのですが、   _SelectionChange イベント は、   【選択セル範囲の変更】   をトリガーにします。   「セルをクリック」したタイミング   を捉えるようなイベントは用意されていませんし、出来ません。 例えば、   [H17]に手入力で、"(1)"を設定する際、Enterキーで確定すると、   選択範囲は、[H18]に移りますので、   [H18]にて_SelectionChange イベントが発行されます。 手入力を一切拒絶するような仕組みを、もしも作ることができたなら、 ある程度の機能を見込むことは出来ますが、 選択セル範囲の変更は他の切っ掛けでも発生するものですので、 正しく管理するのは非常に困難なことです。 3■Worksheet_ イベントの 【Cancel引数】 について Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)   _BeforeDoubleClick イベントには、   (ダブルクリックに追随した)セル[入力モード]状態をキャンセルする   引数 Cancel が用意されています。   Cancel = True を指定すれば、   セル[入力モード]状態を事前にキャンセルします。 Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)   _BeforeRightClick イベントには、   コンテクストメニュー(右クリック時のポップアップ)をキャンセルする   引数 Cancel が用意されています。   Cancel = True を指定すれば、   コンテクストメニューを事前にキャンセルします。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)   _SelectionChange イベントには、   ご覧の通り、【Cancel引数】は用意されていません。   従って、_SelectionChange イベントで、   Cancel = True を指定すれば、エラーになるだけですし、   仮にエラーにならないように書いても、何もしてくれません。 想像の話として、   選択セル範囲の変更をキャンセルして、   直前のセル範囲選択状態に戻す というようなニーズはあるのかも知れませんが、 これを実装するには、非常に高度な技術が求められます。 自力で実装する技術を持たなければ、 意図した通りの挙動を確保する為のメンテナンスも出来ませんから、 人に薦められて使ってみる、といった具合にはいかないでしょう。 こちらからは、お勧めできませんので、 他の方法を探ることをお奨めします。 ただ、今回のご質問については、恐らく、 _SelectionChange以外の他の他のWorksheet_イベントを 手本に流用した名残が誤って残っただけのことだろうと思います。 端的に、_SelectionChange イベントでは、 【Cancel引数】は扱いません。 4■セル値またはセル表示値としての -1 "(1)" について これはVBAではなくて、 元々表計算ソフトとして数値を扱う目的で開発された Excel(その他表計算アプリ共通)一般 の仕様に関するお話です。 はっきりと理解した上でのご質問ではないようなので、 一応、触れておきます。 できれば試してみて欲しいのですが、   新しいシートを用意して、どこか適当なセルに   (1)とタイプして、Enterキーを押してみてください。   値を設定したセルにカーソルを戻して、数式バーを見てください。   セルに表示されたセル表示値は (1)   数式バーに表示されている実際のセル値は -1   と喰い違いがあることに気が付く筈です。 つまり、特に意識しないで、セルに、   (1) を入力すると、Excelはこれを数値-1と看做し、 値は  -1 セルの表示形式は、"0_);(0)"が自動的に割り当てられ [負の値の表示形式]を括弧付数字(1234)として扱います。 端的にいうと、Excelでは(1)は-1として扱うのが普通の仕様なのです。 文字列としての   "(1)"をセルに設定する為には、   [セルの書式][表示形式]を[文字列]に   事前に   設定しておく必要があります。 見た目上は、同じ(1)に見えても、   数値-1が(1)と表示されているのか、   文字列"(1)"が設定されているのか ハッキリと使い分けを意識しておかないと (例えば、Excelの数式や[検索]等の代表的な機能でさえ、  2種類の(1)を別々のものとして扱いますので) 先々扱い難いシートになってしまいますから備えが必要です。 5■なさりたいこと について 実の処、思い通りに動いていないVBAの記述を手掛かりに 実際のニーズを的確に理解することは難しいのですけれど、 > .. Worksheet_SelectionChangeのVBAで ... > .. A列B列C列でワンクリックで文字が入力できるように設定 ... ご提示のコードが対象としているセル範囲は、 [H17:K100]ですので、この点喰い違いがあります。 説明文"A列B列C列"は推敲漏れとして[H17:K100]が正しいものとします。 [H17:K100]の列によって、(1)(2)(3)(4)を振り分けたい という意図は解ります。 条件分岐の仕方も > If Target.Value = "" Then > If Target.Value = "(2)" Then のように不統一なのですが、統一するのが自然でしょうから。   それぞれのセルの値が、予定値(n)であれば値を消去し、   それぞれのセルの値が、予定値(n)でなければ予定値(n)を設定 ということをなさりたいのかな、と。 > ... A列からC列を範囲選択してDeleteすると ... > ... 業務上、そのセルのデータは一気に消したい ... Deleteキーを押した場合は、 VBAは何も処理しないように設計を考えた方が宜しいかと。 文字数制限に納まらないので、回答文を分けますが、 次の投稿で、代替え案を提示してみます。 (次の回答へつづく)

  • Nouble
  • ベストアンサー率18% (330/1783)
回答No.1

間違えて、いたら 済みません エラーですが エラーNo.か、判らない ので、想像ですが #VALUE 辺りが 出て、いるように 思います 出現場所は If Target.Value = 間違いですか? で、 要するに やりたい、事は Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim rng As Range Set rng = Intersect(Target, Range("H17:K100"))  If Not rng Is Nothing _  Then   Cancel = True   If Target.cells(1,1).column = 8 _   Then    Target.Value = "(1)"   Else If Target.Value = "( & Target.cells(1,1).column - 7 & ")" _   Then    Target.Value = Empty   Else    Target.Value = "( & Target.cells(1,1).column - 7 & ")"  End If  End If End Sub ですよね? で、Targetに 単一セル、では なく 領域を、渡した 以前にも 領域を、渡した事は ある の、ですか? 領域を 渡す、場合 Target.Valueが "( & Target.cells(1,1).column - 7 & ")" の、ものと、 そうで、無い ものと、 が、 混在する と、思えますが 如何ですか? 混在した、場合 VBA の、身に なって、考えると 一体、如何したら 良い… ? で、しょう? 悩みませんか? VBAでの、処理は シート関数と、違い 逐次式です 包括的な ファジー処理を、与える のでは、なく 一つづつを 順次、処理します しかし、此は ファジー処理的で、且つ 一意の、判定を 許して、ません 駄目、上司 典型行動、です 領域を、与える 場合で If Target.Value = と、したくば For each で ループさせて セル、一つづつ 見て、いかないと と、思いますが 如何、ですか?

keiko21136my
質問者

お礼

取り急ぎ、ご回答いただけた事にお礼致します。 ありがとうございました。 私の説明不足ですみません。エラーNO13です。 ただ今、早急な仕事が入り、まだ、きちんとみれておりません・・・ 早急な仕事が終わり次第確認したいと思います。

関連するQ&A

  • VBAの記録を追加したい

    エクセル2002使用です。 VBAで次のコードを使っています。 Private Sub Worksheet_Change(ByVal Target As Range) Dim Rng As Range Set Target = Intersect(Range("C:C"), Target) If Target Is Nothing Then Exit Sub For Each Rng In Target If Rng.Value <> "" Then Rng.Offset(, -2).Value = Now Else ' (*) Rng.Offset(, -2).Value = "" ' (*) End If Next Rng End Sub (C列のセルに何か入力されると、A列の同じ行にその時刻が入る。) 同じシートで、F列に何か入力されるとE列の同じ行にその時刻が入るように書き直したいのですが、どうすればいいのでしょうか? すいませんが、よろしくお願いします。

  • VBAにお詳しい方!教えてくださいませ。

    エクセルで、E列に文字を入力した際にB列に、J列からM列に文字を入力した際にC列に入力した日付を自動的に入力されるようなマクロを教えてください。 自分で探した限りでは Private Sub Worksheet_Change(ByVal Target As Range) Dim r, rng As Range Set rng = Intersect(Target, Columns("E:E"))   If Not rng Is Nothing Then     For Each r In rng       If r.Value = "" Then         r.Offset(, -3).ClearContents       Else         r.Offset(, -3).Value = Date       End If     Next r   End If End Sub までしか出来ませんでした。 しかも複数条件を指定する方法もわかりません・・・・。 ぜひともお詳しい方、ご伝授くださいませ

  • エクセル VBA の質問です。

    A2~A20までのセルに文字を入力した段階で、それぞれB2~B20に入力日時を入れるVBAを以下のように組んでいます。 しかし、同様の条件を同一シートのE2~E20・F2~F20にも入力・自動表示できるようにしなければならなくなり、困っています。 どのように記述を変えればよいのか、教えていただけたらと思います。 宜しく御願いいたします。 Sub Worksheet_change(ByVal Target As Range) Dim Rng As Range Dim c As Range Set Rng = Range("A2:A20") If Intersect(Target,Rng) Is Nothing Then Exit Sub For Each c In Intersect(Target,Rng) If Not IsEmpty(c) Then c.Offset(, 1).Value = Now Else c.Offset(, 1).ClearContents End If Next Rng.Offset(, 1).EntireColumn.AutoFit End Sub 申し訳ありませんが、何卒、宜しく御願いいたします。

  • エクセル 数値結果の値によって日付を入れたい

    シート2の2列目にOKが入ると、シート1のC列にOKが入り、更新された日がB列に表示されるようにしたいです。 C列に手入力でOKと入力すればB列に日付が表示されるのですが、C列をVLOOKで呼ぶようにしたら表示されなくなってしまいました。 どのように修正していいのか分かりません。 お教えいただければと思います。よろしくお願いいたします。 Private Sub Worksheet_Change(ByVal Target As Range) Dim Rng As Range Dim TgRng As Range Set TgRng = Intersect(Range("C1:C2000"), Target) If Not TgRng Is Nothing Then Application.EnableEvents = False For Each Rng In TgRng If Rng.Value = "OK" Then Rng.Offset(, -1).Value = Date End If Next Application.EnableEvents = True End If Set TgRng = Nothing End Sub

  • エクセル VBA について

    エクセルで、 ダブルクリックしたら"*"を表示したい範囲に【入力】という名前をつけ、 ダブルクリックしたら9つ左のセルの内容を表示したい範囲に【金額】という名前をつけ、 二つの構文?をVisual Basicに作成したんですが、エラーが出てしまいます。 ひとつずつだと上手くいくのですが、なぜでしょうか? わかる方教えてください。 あと申し訳ないのですが、VBAはまったくわからないため、ネット上で構文をコピーして貼り付けました。 そんな者でもわかる修正の説明をお願いいたします。 以下が作成し、エラーとなってしまう構文です。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Const RangeName As String = "金額" If Target.Value = "" Then Target.Value = Target.Offset(0, -9).Value Cancel = True End If End Sub Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Const RangeName As String = "入力" If Not Intersect(Range(RangeName), Target) Is Nothing Then Cancel = True If Target = "*" Then Target = "" Else Target = "*" End If End If End Sub

  • 2つのVBAを組み合わせる方法

    お世話になります、2つのVBAを組み合わせる方法で迷っています。 1つ目が Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Intersect(Target, Range("C1,B9:B39")) Is Nothing Or Target.Count > 1 Then Exit Sub Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True End Sub です。 2つめが Private Sub Worksheet_Change(ByVal Target As Range)  Application.EnableEvents = True If Intersect(Target, Range("R8:R38")) Is Nothing Then Exit Sub Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End Sub です。2つのPrivate Sub Worksheet_Change(ByVal Target As Range)イベントのVBAですが、どのようにして組み合わせれば良いのでしょうか?

  • エクセル2007のVBAについて

    VBA初心者ですが、よろしくお願いします。 エクセルで入力したいシートタブを右クリック、コードの表示で、 VBAに以下のスクリプトを入力しました。 ネットに紹介されていたスクリプトに自分で一部書き足したものです。 U列に値が入っていれば、その行のT列をダブルクリックするとチェックマークがつくようにし、 それをU列の最終行までループしたいのですが、エラーなどはなくチェックマークが出現しません。 どこが間違っているのでしょうか?ご教授お願いします。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) MaxRow = Range("U65536").End(xlUp).Row For i = 1 To MaxRow Step 1 If Range("U" & i) <> Null Then If Intersect(Target, Range("T" & i)) Is Nothing = False Then Cancel = True If Target.Value = ChrW(10003) Then Target.ClearContents Else Target.Value = ChrW(10003) End If End If End If Next i End Sub

  • VBA 検索して一致したセルへジャンプさせたい

    Excelにて、シート1のA列とシート2のA列のデータにNoを入れます。 シート1のA列のNoをクリックすると、シート2のA列の同じNoにジャンプするマクロを組みたいです。 現在組んでいるマクロは、 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim Sht As Worksheet Dim Rng1 As Range Dim Rng2 As Range Dim FindCell As Range Set Sht = Worksheets("シート2") Set Rng1 = Range("A2:A100") Set Rng2 = Sht.Range("A2:A100")If Intersect(Target, Rng1) Is Nothing Then Exit Sub If Target.Count > 1 Then Exit Sub Set FindCell = Rng2.Find(Target.Value) If Not FindCell Is Nothing Then Application.Goto Reference:=FindCell, Scroll:=False End If End Sub です。 一応マクロは実行されますが、そうすると、シート1のA列の編集(Noを追加したり変更したり・・・)できません。 編集や変更もできて、検索マクロも実行できるというマクロの組み方はありますでしょうか?

  • Excel VBAについて

    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Excel.Range, cancel As Boolean) If Intersect(Target, Range("F:F")) Is Nothing Then Exit Sub Application.Goto Worksheets("人件費").Range("A1") Worksheets("人件費").Cells(Rows.Count, "A").End(xlUp).Offset(1).Value = Target.Offset(, -5).Value cancel = True End Sub Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Excel.Range, cancel As Boolean) If Intersect(Target, Range("G:G")) Is Nothing Then Exit Sub Application.Goto Worksheets("外注費").Range("A1") Worksheets("外注費").Cells(Rows.Count, "A").End(xlUp).Offset(1).Value = Target.Offset(, -5).Value cancel = True End Sub 上の指令はFの列をダブルクリックすると人件費のシートが開いてAある値を人件費の新しいセルのAに代入する指令ですが それをG列ダブルクリックで外注費シートに同じようにやろうと思いましたが出来ません。 たぶん根本的に書き方が間違っているのかと思われますが、ご指導のほどお願いします。

  • 行ごとに保護するマクロにパスワードを付けたい

    Excel2010を使用しております。 A列に「承認」という文字が入ると、その行が保護されるマクロがあります。 今の状態ですと、[校閲]-[シート保護の解除]を押すと解除されてしまいますので 保護を解除する際にパスワードを設定したいのですが上手く行きません。 どうかお助け下さい。宜しくお願い致します。 Private Sub Worksheet_Change(ByVal Target As Range) Dim r, rng As Range Set rng = Intersect(Target, Columns(1)) If Not rng Is Nothing Then If ActiveSheet.ProtectContents = True Then ActiveSheet.Unprotect End If For Each r In rng If r.Value = "承認" Then r.EntireRow.Locked = True Else r.EntireRow.Locked = False End If Next r ActiveSheet.Protect DrawingObjects:=True, Contents:=True, AllowFormattingCells:=True End If End Sub

専門家に質問してみよう