こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

EXCELでVBAを使用してセル移動のコントロールをしています。

EXCELでVBAを使用してセル移動のコントロールをしています。
主にENTERキー、SHIHT+TAB キーでのセル移動の制御を行っていますが、
EXCELの機能で矢印キー↑↓←→のキー操作が邪魔で、
思うような位置にセルが移動しなく、
たぶんEXCEL側の制御の動きをしているのではないかと思うのです。
VBAでセル移動の制御をしているせいか、
EXCEL制御で動く矢印キーが思うように制御しません。
そこで、このEXCEL制御の矢印キーの動きをしないようにと考えてます。
どのようにしたら、矢印キー制御を阻止できるでしょうか?
教えて頂けませんか?

投稿日時 - 2010-03-03 23:23:38

QNo.5722884

すぐに回答ほしいです

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

こんにちは。

以下、的外れでしたらすみません。

今ひとつ、やりたい事の『目的』と『状況』が解らないのですが、

> セル移動のコントロール

とは、具体的にどのような事をなさりたいのでしょうか?

例えば、下記の過去質問のようなことをやりたいと言う事でしょうか?

■過去質問
Do Loop Until 条件停止後のセル位置について
http://qanda.rakuten.ne.jp/qa5320531.html

だとした場合ですが、

1)キーの動作を設定する
  ApplicationオブジェクトのOnKeyメソッドで、キー動作の設定or無効化などの
  設定が可能です。

 <例>
    Application.OnKey "{UP}", ""   '[↑]キーを無効化
    Application.OnKey "{UP}"     '[↑]キーを標準動作に戻す

2)入力されたキーの状態を得る(キースキャン)
  WindowsAPI関数の"GetAsyncKeyState"などを使用すれば、入力キーの状態
  を取得できます。

 <例>
  グローバルで、

    Public Const VK_UP = &H26   '[↑]キーの仮想キーコードの定義
    'WinAPI "GetAsyncKeyState"の参照定義
    Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vkey As Long) As Long

  と宣言しておいて、

    Dim iUp As Integer    '[↑]キー検出用
    iUp = GetAsyncKeyState(VK_UP) And &H8000

  で、[↑]キーの押下状態を取得できます。
  ※&H8000は、現在そのキーが押されているか否かを判定するための
   ビットマスク値として使用しています。

以上のような方法が利用できるかもしれません。

■参考サイト
VBAマクロ応用講座 API関数 マウス キー イベント GetAsyncKeyState OnKey
http://home.att.ne.jp/zeta/gen/excel/c04p07.htm

MSDN GetAsyncKeyState 関数
http://msdn.microsoft.com/ja-jp/library/cc364583.aspx

参考までに、上記にあげた過去質問のようなキー制御を行うサンプルマクロを
掲載してみました。

マクロを実行すると、ワークシート上のアクティブなセルが「緑」色の表示になり、
以後、カーソル移動キー(↑、↓、←、→、Enter、Tab、Shift+Enter、Shift+Tab)
の操作で、「緑」色のセルが上下左右に移動します。
※[Esc]キーを押すとマクロが終了します。

注)下記マクロは、Excel2000で作成しましたが、他のバージョンのExcelの場合、
  上手く動作するかどうかは判りません。

■キー制御のサンプルマクロ
注1)このマクロは、「標準モジュール」のコードとして実装して下さい。
注2)インデント等のため、全角スペースを入れています。

/////↓ここから///////////////////////////////////
Option Explicit

'仮想キーコードの定義
Public Const VK_SHIFT = &H10  '[Shift]キー
Public Const VK_CONTROL = &H11 '[Ctrl]キー
Public Const VK_ESCAPE = &H1B '[Esc]キー
Public Const VK_TAB = &H9   '[Tab]キー
Public Const VK_UP = &H26   '[↑]キー
Public Const VK_DOWN = &H28  '[↓]キー
Public Const VK_LEFT = &H25  '[←]キー
Public Const VK_RIGHT = &H27  '[→]キー
Public Const VK_RETURN = &HD  '[Enter]キー
Public Const VK_HOME = &H24  '[Home]キー
Public Const VK_END = &H23   '[End]キー
Public Const VK_PRIOR = &H21  '[PageUp]キー
Public Const VK_NEXT = &H22  '[PageDown]キー

'WinAPIの参照定義
Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vkey As Long) As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'
'キー操作テスト
'
Sub KeyScan()

  Dim iKey As Integer   '入力キーの識別コード
  Dim iUp As Integer   '[↑]キー検出用
  Dim iDown As Integer  '[↓]キー検出用
  Dim iLeft As Integer  '[←]キー検出用
  Dim iRight As Integer  '[→]キー検出用
  Dim iShift As Integer  '[Shift]キー検出用
  Dim iEsc As Integer   '[Esc]キー検出用
  Dim iTab As Integer   '[Tab]キー検出用
  Dim iEnter As Integer  '[Enter]キー検出用
  Dim cyMin As Long    'セル位置の最小行
  Dim cxMin As Long    'セル位置の最小カラム
  Dim cyMax As Long    'セル位置の最大行
  Dim cxMax As Long    'セル位置の最大カラム
  Dim cy1 As Long     '今回のセル位置(行位置)
  Dim cx1 As Long     '今回のセル位置(カラム位置)
  Dim cy2 As Long     '前回のセル位置(行位置)
  Dim cx2 As Long     '前回のセル位置(カラム位置)

  'セル位置の範囲を設定
  cyMin = 1        'セル位置の最小行
  cyMin = 1        'セル位置の最小カラム
  cyMax = Rows.Count   'セル位置の最大行
  cxMax = Columns.Count  'セル位置の最大カラム

  'アクティブセルの位置を取得
  cy1 = ActiveCell.Row
  cx1 = ActiveCell.Column
  cy2 = cy1
  cx2 = cx1

  '全セルをクリアする
  Range(Cells(1, 1), Cells(Rows.Count, Columns.Count)).Clear

  'タイトルバーに処理中メッセージ表示
  Application.ActiveWindow.Caption = "【カーソル制御中】- ※[Esc]キーで停止"

  '開始セルの選択&カラー設定
  Cells(cy1, cx1).Select
  Cells(cy1, cx1).Interior.ColorIndex = 4

  'カーソル移動関連のキー無効化
  Application.OnKey "{PGUP}", ""   '[PageUp]
  Application.OnKey "{PGDN}", ""   '[PageDown]
  Application.OnKey "{HOME}", ""   '[Home]
  Application.OnKey "{END}", ""    '[End]
  Application.OnKey "^{HOME}", ""   '[Ctrl]+[Home]
  Application.OnKey "^{END}", ""   '[Ctrl]+[End]
  Application.OnKey "^{UP}", ""    '[Ctrl]+[↑]
  Application.OnKey "^{DOWN}", ""   '[Ctrl]+[↓]
  Application.OnKey "^{LEFT}", ""   '[Ctrl]+[←]
  Application.OnKey "^{RIGHT}", ""  '[Ctrl]+[→]
  Application.OnKey "+{PGUP}", ""   '[Shift]+[PageUp]
  Application.OnKey "+{PGDN}", ""   '[Shift]+[PageDown]
  Application.OnKey "+{HOME}", ""   '[Shift]+[Home]
  Application.OnKey "+{END}", ""   '[Shift]+[End]
  Application.OnKey "+{UP}", ""    '[Shift]+[↑]
  Application.OnKey "+{DOWN}", ""   '[Shift]+[↓]
  Application.OnKey "+{LEFT}", ""   '[Shift]+[←]
  Application.OnKey "+{RIGHT}", ""  '[Shift]+[→]
  Application.OnKey "+^{HOME}", ""  '[Shift]+[Ctrl]+[Home]
  Application.OnKey "+^{END}", ""   '[Shift]+[Ctrl]+[End]
  Application.OnKey "+^{UP}", ""   '[Shift]+[Ctrl]+[↑]
  Application.OnKey "+^{DOWN}", ""  '[Shift]+[Ctrl]+[↓]
  Application.OnKey "+^{LEFT}", ""  '[Shift]+[Ctrl]+[←]
  Application.OnKey "+^{RIGHT}", ""  '[Shift]+[Ctrl]+[→]
  Application.OnKey "%{PGUP}", ""   '[Alt]+[PageUp]
  Application.OnKey "%{PGDN}", ""   '[Alt]+[PageDown]

  'エラー処理の設定(エラー発生時の停止回避)
  On Error Resume Next

  'ループ処理1:全体処理([Esc]キーが押されるまでループ)
  Do While (1)
    'ループ処理2:キー入力監視(指定のキーが押されるまでループ)
    iKey = 0  '入力キーの識別コードをリセット
    Do
      '入力キー検出
      iEsc = GetAsyncKeyState(VK_ESCAPE) And &H8000
      iUp = GetAsyncKeyState(VK_UP) And &H8000
      iDown = GetAsyncKeyState(VK_DOWN) And &H8000
      iLeft = GetAsyncKeyState(VK_LEFT) And &H8000
      iRight = GetAsyncKeyState(VK_RIGHT) And &H8000
      iEnter = GetAsyncKeyState(VK_RETURN) And &H8000
      iTab = GetAsyncKeyState(VK_TAB) And &H8000
      iShift = GetAsyncKeyState(VK_SHIFT) And &H8000

      '入力キーの識別コードセット
      If iEsc Then
        iKey = 99  '[Esc]
      ElseIf iUp Then
        iKey = 1  '[↑]
      ElseIf iDown Then
        iKey = 2  '[↓]
      ElseIf iLeft Then
        iKey = 3  '[←]
      ElseIf iRight Then
        iKey = 4  '[→]
      ElseIf iEnter And Not iShift Then
        iKey = 5  '[Enter]
      ElseIf iEnter And iShift Then
        iKey = 6  '[Shift]+[Enter]
      ElseIf iTab And Not iShift Then
        iKey = 7  '[Tab]
      ElseIf iTab And iShift Then
        iKey = 8  '[Shift]+[Tab]
      End If

      'システムに制御を渡す(※溜まっているメッセージの処理)
      DoEvents
    Loop While iKey = 0  '指定キーの入力が無ければループ

'@@:DBG
    'デバッグ表示:イミディエイトウィンドウにキー識別コードを表示
    Debug.Print "iKey=" & iKey
'@@:DBG

    '[Esc]キーが押されたらループを抜ける
    If iKey = 99 Then Exit Do

    '今回のセル位置取得
    cy1 = ActiveCell.Row
    cx1 = ActiveCell.Column

    'セル位置が変わったら表示更新
    If cy1 <> cy2 Or cx1 <> cx2 Then
      '前回セル位置のカラーをクリアして、今回セル位置のカラーをセット
      Cells(cy2, cx2).Interior.ColorIndex = xlNone
      Cells(cy1, cx1).Interior.ColorIndex = 4
      'セル位置のセーブ(前回値へ)
      cy2 = cy1
      cx2 = cx1
    End If
  Loop

  'エラー処理の解除
  On Error GoTo 0

  '前回セル位置のカラーをクリア
  Cells(cy2, cx2).Interior.ColorIndex = xlNone

  'タイトルバーの表示を戻す
  Application.ActiveWindow.Caption = ThisWorkbook.Name

  'キー無効化の解除
  Application.OnKey "{PGUP}"   '[PageUp]
  Application.OnKey "{PGDN}"   '[PageDown]
  Application.OnKey "{HOME}"   '[Home]
  Application.OnKey "{END}"    '[End]
  Application.OnKey "^{HOME}"   '[Ctrl]+[Home]
  Application.OnKey "^{END}"   '[Ctrl]+[End]
  Application.OnKey "^{UP}"    '[Ctrl]+[↑]
  Application.OnKey "^{DOWN}"   '[Ctrl]+[↓]
  Application.OnKey "^{LEFT}"   '[Ctrl]+[←]
  Application.OnKey "^{RIGHT}"  '[Ctrl]+[→]
  Application.OnKey "+{PGUP}"   '[Shift]+[PageUp]
  Application.OnKey "+{PGDN}"   '[Shift]+[PageDown]
  Application.OnKey "+{HOME}"   '[Shift]+[Home]
  Application.OnKey "+{END}"   '[Shift]+[End]
  Application.OnKey "+{UP}"    '[Shift]+[↑]
  Application.OnKey "+{DOWN}"   '[Shift]+[↓]
  Application.OnKey "+{LEFT}"   '[Shift]+[←]
  Application.OnKey "+{RIGHT}"  '[Shift]+[→]
  Application.OnKey "+^{HOME}"  '[Shift]+[Ctrl]+[Home]
  Application.OnKey "+^{END}"   '[Shift]+[Ctrl]+[End]
  Application.OnKey "+^{UP}"   '[Shift]+[Ctrl]+[↑]
  Application.OnKey "+^{DOWN}"  '[Shift]+[Ctrl]+[↓]
  Application.OnKey "+^{LEFT}"  '[Shift]+[Ctrl]+[←]
  Application.OnKey "+^{RIGHT}"  '[Shift]+[Ctrl]+[→]
  Application.OnKey "%{PGUP}"   '[Alt]+[PageUp]
  Application.OnKey "%{PGDN}"   '[Alt]+[PageDown]

End Sub
/////↑ここまで///////////////////////////////////

※添付画像は、上記マクロ実行中のExcelブックのキャプチャ画像です。

以上です。参考になれば幸いです。

投稿日時 - 2010-03-04 08:13:10

お礼

ありがとうございます。
上記のようなメソッド、APIを使って行っていました。
そして、VBAでセル移動をコントロールしていた(ENTER,SHIFT+TAB)手前、
矢印キーの動きがどうもおかしい現象が発生し、
矢印キーの制御をVBAでなく
EXCELの本来の制御で行うようにしました。
よって、VBA内のWorkSheet_SelectionChange()から
矢印キーを検知したら
このイベントから抜けてEXCEL側に制御させるようにしました。

投稿日時 - 2010-03-04 09:41:48

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(1)

あなたにオススメの質問