• ベストアンサー

エクセル:Application.OnKeyについて

5行目のセルにカーソルがある時に矢印キー「↑」を押すと、 カーソルは1つ上のセルへ移動し(通常の「↑」キーの処理を行い)、 更に特定の処理をする(例えばメッセージボックスを出すとか)、 といったコードを組みたいです。 5行目以外のセルで「↑」が押された場合は、 カーソルが1つ上のセルへ移動するという「↑」キーの通常の処理だけを行いたいです。 検索してApplication.OnKeyという書き方を見つけたのですが、 これは{UP}キーの機能が常に別のものになるように限定してしまうものばかりでした。 5行目にある時のみ、といった条件を入れたいです。 書き方わかる方いましたらよろしくお願いします。

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

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

こんにちは。 >[↑]を押した時に移動先がロックされていれば更にその上のセルへ移動して欲しいのですが、 >「マクロによる変化は有効」なのでしっかり1つ上のセルへ移動します。 それは、ワークシートの設定と、今回の私の書いたマクロの内容が合致していません。メッセージだけの問題なら、入力規則を組み合わせるなどしたほうが良いように思います。 マクロの場合は、最終的な目的が、何かということが大事だと思います。メッセージを出すことなのか、それとも、セルポインター(↑)に仕掛けを組み込ませるのか、ということです。条件の内容も違ってきてしまっていますから、話は似ていてもマクロでも、違った内容になってきてしまいます。 以下は、シートモジュールだけで、それ以外のOnKeyの設定コードは削除してください。 Private PreRow As Long Private Sub Worksheet_SelectionChange(ByVal Target As Range)  If PreRow = 0 Then PreRow = ActiveCell.Row  If Target.Row = 5 And PreRow - Target.Row > 0 Then   MsgBox "5行目にカーソルがあります。", vbInformation  End If  PreRow = Target.Row End Sub

tktk1228
質問者

お礼

回答ありがとうございます。 結局目的が曖昧なままで色々手間かけさせて申し訳ありません。 最終的な目的はちゃんとあるのですが、 そのまま質問すると「私はこれが欲しいから全部作ってください」と言わんばかりなので、 細かいサンプルを聞いて、それを自分用に組み立てるつもりでした。 (文字にしてみると「全部作って」とたいして変わりませんね…) いまさらですがやりたかったことは以下です。  ・1~2行目を「ウインドウ枠の固定」で固定する。  ・A3に文字を入力しておく。  ・A4,A6,A8,A10のみセルの書式設定で「ロックしない」。  ・保護をかけ「ロックされたセル範囲の選択」は許可しない。  ・ウィンドウを小さくして1~9行目だけしか表示されないようにする。 この状態だとカーソルが移動できるのはA4,A6,A8,A10の4つのみ。 [↑]キーを押すと、A4→A10→A8→A6→A4、の順にカーソルが移動する。 A4より上にはカーソルが移動できずA10へ移動するので、矢印キーによる操作だけではA3に書かれた文字は今後見えることは無い。 A3にはカーソルが移動できない条件下で、 A3に書かれた文字を見えるようにしたい、というのが目的でした。 で、考えたのは、 A6からA4にカーソルを移動させる時にスクロールバーをA3まで移動させる、という案です(可能かどうかは別問題)。 コードにすると以下のような感じになったかと(可能であるなら)。 If [↑]キーを押した then   If カーソルの位置="A6" then     ActiveWindow.ScrollRow = 3   End If   ActiveCell.Offset(-1).Select EndIf 手段の時点から聞けばもっといい方法を教えてもらえたかもしれませんが、 とりあえず手段くらいは自分で考えるべきかと思ったというか…。 要するにエゴです。 ご迷惑おかけしました。

その他の回答 (5)

  • WWolf
  • ベストアンサー率26% (51/192)
回答No.6

Wendy02さん代わっての回答ありがとう御座います。 また、質問者さん返事が遅くなり申し訳ありません。 #1のコードのaaaのコードを下記の様に変更して下さい。 Sub aaa() If AR = 5 Then MsgBox AR & "行で↑が押されました" End If ActiveCell.Offset(-1, 0).Select Do While ActiveCell.Locked = True ActiveCell.Offset(-1, 0).Select If ActiveCell.Row = 1 Then ActiveCell.Offset(6, 0).Select Exit Do End If Loop セルを上に上げた時ののセルのロックをチェックし上へ上へ上げています。 セルの行が1行目まで行った場合、強制的に6行目を選択していますが、参考にして組み直してください。 本来Wendy02さんのコードに追加すれば質問者さんにとって助かると思いますが、横槍になってしまう為、ご了承下さい。

tktk1228
質問者

お礼

>質問者さん返事が遅くなり申し訳ありません。 とんでもないです、回答ありがとうございます。 仕組みも理解でき、動作もいい感じになりました。 Wendy02さん(ANo.5)への返信(言い訳ですけど)にも書いたように、 実際にやりたかったのは所定の位置にカーソルがある時に[↑]押すとスクロールさせる、 ということだったんですが、 挙げていただいたコードを組み込んだら「スクロールさせる」という記述を入れなくてもスクロールしました。 (ANo.5の「お礼」での具体例で言うなら、ActiveWindow.ScrollRow = 3を入れなくてもA3に書かれた文字が見えるようになった) 結果オーライです。 ありがとうございました。

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

こんばんは。 以下のようにしてください。 #1 さんの書き方のように、標準モジュールに、プロシージャ、MyMacro を置けば済みます。 なお、変数の場合は、モジュールレベルに、Public ステートメントをつけると、プロジェクト内は共通になります。プロシージャも同じようなものですが、プロシージャの場合は、Public ステートメントをあえてつける必要性はありません。つけてもよいですが。 前のものは、一度、削除するか、上書きしてください。 '※標準モジュールへ移動 Sub MyMacro() On Error GoTo ErrHandler  If ActiveCell.Row <> 5 Then   ActiveCell.Offset(-1).Select  Else   MsgBox "5行目にカーソルがあります。", vbInformation   ActiveCell.Offset(-1).Select  End If   Exit Sub ErrHandler: End Sub 'ThisWorkbookモジュール Private Sub Workbook_Open()   Application.OnKey "{UP}", "MyMacro" '登録したシートのマクロ End Sub 'シートモジュール Private Sub Worksheet_Activate()  Application.OnKey "{UP}", "MyMacro" End Sub Private Sub Worksheet_Deactivate()  Application.OnKey "{UP}" End Sub

tktk1228
質問者

お礼

回答ありがとうございます。 正常に動作しました。 ちょっと派生した質問なのですが(別スレ立てた方がいいのかな)、 If ActiveCell.Row <> 5 Thenの時の動きは「[↑]キーのデフォルトの動き」が欲しいです。 デフォルトはOffset(-1).Selectだと思いますが、 現在このシート、  ・保護しているが、「マクロによる変化は有効」にしている。  ・ロックしたセルは選択させない設定。 という状態になっています。 [↑]を押した時に移動先がロックされていれば更にその上のセルへ移動して欲しいのですが、 「マクロによる変化は有効」なのでしっかり1つ上のセルへ移動します。 この部分(Offset(-1).Select)だけ「マクロによる変化は有効」を解除できたりはしないでしょうか。

tktk1228
質問者

補足

書き忘れました。 >モジュールレベルに、Public ステートメントをつけると~ ご説明ありがとうございます、理解できました。

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

こんにちは。 >一度Sheet2に切り替え、再度Sheet1に切り替えるとすると動作しました。 >何故開いた直後は(開いた時はSheet1が開く)動作しないのでしょうか。 その場合は、 ThisWorkbook モジュールに Private Sub Workbook_Open()   Application.OnKey "{UP}", "Sheet1.MyMacro" '登録したシートのマクロ End Sub 細かい仕様が気になる場合は、私の書いたものは、新たに作り直したほうがよいと思います。

tktk1228
質問者

お礼

回答ありがとうございます。 サンプルコード内では正常に動きました。 が、実際使いたいコード内に組み込むと何故か「Sheet1.MyMacroが見つからない」と出てしまい、動きませんでした。 シート名を変更してもダメ、 ThisWorkbook モジュールとシートモジュールにおける今回の質問の動作に必要なコード以外を消してもダメ、 といった状態で、もう少し時間がかかりそうです。

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

こんばんは。 こんな感じかな? シートモジュール(のみ)に貼り付けてください。 Private Sub Worksheet_Activate()  Application.OnKey "{UP}", Me.Name & ".MyMacro" End Sub Sub MyMacro() On Error GoTo ErrHandler  If ActiveCell.Row <> 5 Then   ActiveCell.Offset(-1).Select  Else   MsgBox "5行目にカーソルがあります。", vbInformation   ActiveCell.Offset(-1).Select  End If   Exit Sub ErrHandler: End Sub Private Sub Worksheet_Deactivate()  Application.OnKey "{UP}" End Sub

tktk1228
質問者

お礼

申し訳ありません、ちゃんと動きました。 Sheet1に貼り付けたのですが、 ファイルを開いた後、 一度Sheet2に切り替え、再度Sheet1に切り替えるとすると動作しました。 何故開いた直後は(開いた時はSheet1が開く)動作しないのでしょうか。

tktk1228
質問者

補足

回答ありがとうございます。 シートモジュールというのは、 Sheet1で行うならSheet1で右クリックして「コードの表示」で出てくるウィンドウですよね? 挙げていただいたコードをここにそのままコピーしたのですが、 動作しません。 そのままコピー&ペーストするのはまずいでしょうか? できれば1つのシート内にコードがあると嬉しいので、 よろしくおねがいします。

  • WWolf
  • ベストアンサー率26% (51/192)
回答No.1

こんにちは。 少し強引ですが ***ThisBookのコードに*** Private Sub Workbook_Open() Application.OnKey "{UP}", "aaa" Worksheets(1).Range("A1").Select End Sub ***Sheet1のコードに*** Private Sub Worksheet_Activate() AR = ActiveCell.Row End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) AR = ActiveCell.Row End Sub ***Moduleのコードに*** Public AR Sub aaa() If AR = 5 Then MsgBox AR & "行で↑が押されました" End If ActiveCell.Offset(-1, 0).Select End Sub これで出来ますが如何でしょう?

tktk1228
質問者

お礼

回答ありがとうございます。 望んだように動きました。 なにやら見たことのない記述の仕方があり、ちょっと理解に時間はかかりそうです。 Public ARとは、どこのシートでも使える変数の宣言でしょうか? 型名がないのが気になりますが。

関連するQ&A

専門家に質問してみよう