アプリ版:「スタンプのみでお礼する」機能のリリースについて

セルに入力したあとその入力したキーが「Delete」キーかどうか判定するプログラムを作りたいのですが、下記のようにコードを書きました。

'標準モジュール
Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long

'Microsoft Excel Objects(ワークシート)
Private Sub Worksheet_Change(ByVal Target As Range)
If GetAsyncKeyState(46) <> 0 Then 'キーボードの「Delete」キーかどうか判定
○○
Else
○○
End If
End Sub

ところが、「Delete」キーを押してもGetAsyncKeyState(46)の値が「0」になり、「Delete」キーを押してないことになってしまいます。どのようにすればよいのでしょうか?
回答よろしくお願いします。

A 回答 (6件)

#1 のコードを部分訂正。

。。。

どうも、こうやらないとダメみたい。

' // DELキーを送信
Call Auto_Close
AppActivate Application.Caption
SendKeys "{DEL}", True
Call Auto_Open
    • good
    • 0
この回答へのお礼

「Onkey」でも動きますね。しかし、初心者なものでコードの内容は全部は分かりませんでした。勉強したいと思います。

ありがとうございました。

お礼日時:2007/08/09 11:11

こんにちは。



何か、求めている方向が違っているような気がします。実際、API関数を使う場面というのは、VBAでは、ほとんど出てこないというか、私などは、VBAでは、あまり必要とすることがありません。

今回の「お礼」側に書かれて内容からすると、ある程度、既出の問題のような気がします。

全体的なマクロコードは見せられていないので、はっきりとしたことはいえないのですが、単に、このようなことではないでしょうか?入力後の移動自体というのも、関係ないような気がします。


'同じ列の違う行に自動的に入力する

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
  Application.EnableEvents = False
  Target.Offset(10).Value = Target.Value
  Application.EnableEvents = True
End Sub
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2007/08/13 08:59

こんにちは。



日にちが経ったもので、補足側に書かれると、どうしても、確認が遅くなってしまいます。多少でもよいので、お礼側に、「質問があります」とか、少しでも書かないと、補足側に付けられては、ここを再び開けるまで確認できないのです。

>ステップインするとやはり値が0になってしまいます。

どうして、同じような質問になるのか、私には良く分からないのです。

アットタイムで、その判定を取りたいなら、MsgBox を出せばよいのではありませんか?

ステップモードで必ずしも正しく取れるものではありません。話が、ごちゃごちゃになっていると思うのです。VBEditor で動かして、それで、キーボードとして判定するのは、無理です。それは、VBAの範囲ではありません。あくまでも、キーボードが押され、API関数が感知する範囲だと思います。

>プログラムを一時停止して動かしたとき

もともと、それは、何をするものですか?キーボード自体の判定を目的にするなら、VBAプログラムは、もうあきらめたほうがよいのではありませんか?

VBAで、コードを作る場合は、Office アプリケーションの扱える範囲内で、どういう仕事を目的にするか、ということだと思います。

はたして、本当に、API関数が必要なのか、もう一度、考え直したほうがよいのではないか、と思います。Delete 自体を押したことを判定するなら、#1 さんの示した、OnKey で十分なのです。
    • good
    • 0
この回答へのお礼

すいません。補足に付けると確認ができないんですね。

ステップモードで必ずしも正しく取れるものではないというのは初めて知りました。

もともと、それは、何をするものですか?>これはワークシートのある一定のセルに入力したときに、同じ列の違う行に自動的に入力するようなプログラムを作りたかったからです。今セルがどこにあるのか判定するためなのですが、セルに入力すると移動し、「Del」キーの場合は移動せずに変わってしまうのでその判定をしたかったのです。
あと、オプションの入力後の移動を変えても正しく判定するようにしたいと思っていました。

ありがとうございました。

お礼日時:2007/08/09 10:20

直接の回答ではありませんが、


何をしたいために「Del」キーの押下をチェックするのか判りませんが、
もし、改変されたくないセルを保護するためだけなら、「シート保護」で対応するなど、
「はたして、VBAで対応すべき」かどうかを全体的に考え直すことも必要です。
VBAを組み込んでしまうと、
1.メンテを作成者にしか頼めなくなる
2.VBAでなくても実現できることもVBAに走るクセがつく
2.マクロ入りのエクセルを開くと表示される「ウイルス」云々の警告メッセージに
 エンドユーザーが過剰反応してしまう。
ということがおきがちです。
    • good
    • 0
この回答へのお礼

そうですね。プログラムでやらなければいけないか考えなくてはいけませんね。プログラムで便利な部分と不便な部分と考えて作りたいと思います。

ありがとうございました。

お礼日時:2007/08/09 11:16

こんにちは。



こちらで、そのコードを試してみましたが、一応、問題なく動作します。

>「Delete」キーを押してもGetAsyncKeyState(46)の値が「0」になり

この部分で、どのようにチェックされているのかは分かりませんが、それは、このAPI関数取得のタイムラグの許容範囲を越えているのではありませんか?それと、念のために、GetAsyncKeyState の値をクリアしてから、やってみたらいかがでしょうか?

しかし、
>セルに入力したあとその入力したキーが「Delete」キーかどうか判定するプログラムを作りたいのですが、

この内容にもよると思います。これで次のイベントが発生したら、すべてご破算になってしまいます。元が、Worksheet_Change イベントですから、他のコントロールのKeyDown やKeyUp イベントのように、キーに対するイベントにはなっていません。

#1 さんのような、OnKey で、[Delete]キーを固定した方法が良いかもしれません。Worksheet_Change イベントの場合は、[Delete]キー自体を監視するというよりも、ワークシートのデータに関わる監視のはずです。そのキー自体を監視する目的ではないでしょう。

今回、一応、以下のように試してみました。

'シートモジュール
Private Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Private Const VK_DELETE As Long = &H2E

Private Sub Worksheet_Change(ByVal Target As Range)
Call GetAsyncKeyState(0&)
If GetAsyncKeyState(VK_DELETE) <> 0 Then 'キーボードの「Delete」キーかどうか判定
 Beep
Else
 '------------
End If
End Sub

参考:
プラットフォーム SDK
GetAsyncKeyState
http://msdn.microsoft.com/library/ja/default.asp …

この回答への補足

ブレークポイントを解除してプログラムを走らせたところGetAsyncKeyStateで問題なく動きました。
しかし、ブレークポイントを設定(If GetAsyncKeyState(46) <> 0 Thenの部分)してチェックしてステップインするとやはり値が0になってしまいます。
これはプログラムを一時停止して動かしたときに他の入力をしたことにより「Del」キーが無効になったということでしょうか?
よろしくお願いします。

補足日時:2007/08/01 08:11
    • good
    • 0

ご提示していただいた方法では、



DEL キー押下 --> セルのデータが消去される --> イベント発生

となって初めてキー状態のチェックですからね、、、通常 DEL キー
は長押ししないし、連打もしないですからキーの入力判定の段階では
既に DEL キーは押されてないからでは?

ループで監視でもしない限り GetAsyncKeyState API での判定は無理
だと思います。

代わりに OnKey メソッドを使ってみたら?

' // 場所:標準モジュール

Sub Auto_Open()
  Application.OnKey "{DEL}", "PressDelKey"
End Sub
Sub Auto_Close()
  Application.OnKey "{DEL}"
End Sub

Private Sub PressDelKey()

  If UCase$(TypeName(Selection)) = "RANGE" Then
    If ActiveSheet Is ThisWorkbook.Worksheets("Sheet1") Then
      MsgBox "Sheet1 で Delキーが押されました", vbInformation
    End If
  End If
  ' // DELキーを送信
  AppActivate Application.Caption
  SendKeys "{DEL}", True

End Sub
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A