[[20140615160623]] 『インプットボックスをキャンセル』(りんご) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『インプットボックスをキャンセル』(りんご)

 いつもお世話になっております。
 本日も宜しくお願い致します。

 ユーザーフォーム内の「Button3」を押すとインプットボックスが表示され、
 入力したコードを元に必要な情報をフォーム上に表示させています。

 Private Sub Button3_Click() '検索

 Dim Searchkey As String
 Dim SearchArea As Range
 Dim Foundcell As Range

 Searchkey = Application.InputBox(Prompt:="コードを入力して下さい", Type:=2)

 Set SearchArea = Sheets("台帳").Range("A:A")

 Set Foundcell = SearchArea.Find(What:=Searchkey, SearchOrder:=xlByRows, _
 LookAt:=xlWhole, MatchCase:=False)

 If Foundcell Is Nothing Then ’データがない時
 MsgBox "データなし", vbCritical
 GoTo ExitHandler

 End If

 With Foundcell
 Me.Box1.Value = .Value               'コード
 Me.Box2.Value = .Offset(0, 4).Text   '完了予定月
 Me.Box3.Value = .Offset(0, 1).Text   '契約日
 Me.Box4.Value = .Offset(0, 2).Text   '完了日
 Me.Box5.Value = .Offset(0, 3).Text   '担当
 Me.Box6.Value = .Offset(0, 5).Text   'お客様名

 End With

 ExitHandler:
 Set SearchArea = Nothing
 Exit Sub

 End Sub

 この処理の際に、
 1、インプットボックスで条件一致の場合はデータを表示
 2、誤ったコードが入力されたら「データなし」を通知(未入力で実行した場合も)
 3、インプットボックスのキャンセルを選択したら「キャンセルしました」と通知
 以上、3つの選択を行いたいのです。
 現状ですと「キャンセル」選択時は、「データなし」が通知されます。
 色々調べたのですが、「空白」と「キャンセル」は同じ扱いになるようで
 「キャンセル」だけを別の処理と捉えたいのですが、どのようにすれば宜しいのでしょうか?

 皆様のお知恵をお貸し下さい。宜しくお願い申し上げます。

< 使用 Excel:Excel2013、使用 OS:Windows7 >


 こちらを参考にしてはどうでしょうか。
http://officetanaka.net/excel/vba/tips/tips37.htm
(マナ) 2014/06/15(日) 16:34

 マナ様

 ご回答ありがとうございました。
 こちらのサイトは何度も見ていたのですが、
 「InputBoxメソッドなら、[キャンセル]ボタンがクリックされた結果のFalseと、
 空欄("")のまま[OK]ボタンがクリックされたのを判別できます。それだけの話です。」
 この部分がいまいち理解出来ずにいます。

 先ほど記述したコードに追加しました↓

 If TypeName(Searchkey) = "Boolean" Then
 MsgBox "キャンセル"
 End If

 結果、キャンセル時に「キャンセル」と表示された後に「データなし」と表示されました。

 恐らく、
 If Foundcell Is Nothing Then ’データがない時
 この部分を存在しないコードが入力されたらとさせれば上手くいくような気がします。
 Searchkey と Foundcell がある為か難しく感じてしまってます。
 もう少し頑張ってみます。ありがとうございました。

(りんご) 2014/06/15(日) 17:45


 Sample9は理解できますか?
(マナ) 2014/06/15(日) 18:14

 マナ様
 ご連絡遅くなりました。申し訳ありません。
 時間がたち、Sample9の部分をもう1度読み直してみました。
 昨日とは違い、少し理解できたような気がしたので下記のように作成しました。

 Private Sub Button3_Click() '検索
 Dim Searchkey As Variant
 Dim SearchArea As Range
 Dim Foundcell As Range

 Searchkey = Application.InputBox(Prompt:="コード入力")
 If Searchkey = False Then
  MsgBox "キャンセルされました"
 Exit Sub
 End If

 If Searchkey = "" Then
 MsgBox "コードを入力して下さい"

 End If

 Sheets("台帳").Select
 Set SearchArea = Sheets("台帳").Range("A:A")

 Set Foundcell = SearchArea.Find(What:=Searchkey, SearchOrder:=xlByRows, _
 LookAt:=xlWhole, MatchCase:=False)

 If Foundcell Is Nothing Then
 MsgBox "該当するデータはありません"
 GoTo ExitHandler
 End If
 --------------------以下、省略----------------------------

 上記で希望通りに動きましたが何か問題点等はないでしょうか?
 宜しくお願い致します。
(りんご) 2014/06/16(月) 14:22

こんな感じにすると、コードが入力されるまで、次に進みません。

 Sub test()
    Dim ret As String

    Do
        If ret = "False" Then
            MsgBox "キャンセルしました"
            Exit Sub
        ElseIf ret = "" Then
            ret = Application.InputBox("コードを入力してください")
        Else
            Exit Do
        End If
    Loop

    MsgBox "コードが入力されたので検索を実行します"

 End Sub

(マナ) 2014/06/16(月) 20:06


 ちょっと気になったので・・・。
 気になったのは、InputBoxメソッドのキャンセルクリックの判断の仕方です。
 りんごさんが最初に投稿された

 >If TypeName(Searchkey) = "Boolean" Then
 >   MsgBox "キャンセル"
 >End If

 この戻り値をTypeName関数で判断する手法をどうして変えられたのかなあ?

 というのが気になった点です。もっとも全体としては、本当に細かい事なんですが
 (細かい事が気になるのが 僕の悪い癖 ←杉下右京風)。

 > 「InputBoxメソッドなら、[キャンセル]ボタンがクリックされた結果のFalseと、
 >空欄("")のまま[OK]ボタンがクリックされたのを判別できます。それだけの話です。」
 >この部分がいまいち理解出来ずにいます。

 VBAでダイアログを表示させて、ユーザーに文字を入力要求する機能には、

 InputBox関数と

 ApplicationオブジェクトのInputBoxメソッドがあることは、マナさんご紹介のリンク先にもあります。

 InputBox関数

 Sub test1()
    Dim mes As String
    mes = InputBox("何か入力してください")
    If mes = "" Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 InputBox関数は、上記のコードのようにキャンセルボタンを押された時は、空欄("")が返ります。

 これだと、未入力の状態で OKボタンを押された時とキャンセルボタンを押された時の
 区別がつかない事になります。 

 その証拠に 上記のtest1で何も入力しないでOKボタンを押すと
 「キャンセルボタンが押されました」と表示されます。

 厳密にこのInputBoxの機能にこだわれば、
 「OKボタンが押されたら、入力されたデータを返し(例え、空欄でも)、キャンセルボタンが押されたら、キャンセルボタンが押されたことが認識できる」という仕様でなければなりませんよね?

 InputBox関数では厳密に判断できないので ApplicationオブジェクトのInputBoxメソッドなら出来るよ
 という事なんです(実は、InputBox関数でもできますが)。
 が・・・。

 りんごさんが2回目に投稿されたキャンセルをFalseで判断する方法だと

 Sub test2()
    Dim mes As Variant
    mes = Application.InputBox("何か入力してください")
    If mes = False Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 これだと、確かに空白とキャンセルボタンの区別は付きますよね!!

 でもこれだと、 「False」という文字列を取得できません、キャンセルボタンを押したと
 判断されてしまいます。

 OKボタンが押されたら、入力された文字列を返さなければならないのに・・・。

 文字列の"False"でキャンセルを判断すると、少しはよくなりますが(Test2は、Falseもfalseもダメ)

 Sub test3()
    Dim mes As String
    mes = Application.InputBox("何か入力してください")
    If mes = "False" Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 これでも 文字列 「False」をOKボタンで取得できません。

 よって、最初にりんごさんが投稿したTypeName関数を使う方法がよいと思うのです。

 Sub test4()
    Dim mes As Variant
    mes = Application.InputBox("何か入力してください")
    If TypeName(mes) = "Boolean" Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 これだと、空欄もFalseもOKボタンを押せば、文字列として取得できますし、キャンセルボタンの判断もしてくれます。

 でも、りんごさんがコードを変えたのがFalseとした方がわかりやすい という理由なら、納得もできます。

 test4を以下のようなコードにすると、わかりやすさも少し克服できると思います。

 Sub test5()
    Const Cancel As Variant = False
    Dim mes As Variant
    mes = Application.InputBox("何か入力してください")
    If mes = Cancel Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 ***************************************

 因みにInputBox関数でも以下のようにすると、空白文字列でOKボタンを押した場合とキャンセルボタンの区別をしてくれます。

 これは、StrPtr関数の意味や String型の変数の内部構造を知らないと意味は理解できないかもしれませんが・・・。

 Sub test6()
    Const Cancel As Long = 0
    Dim mes As String
    mes = InputBox("何か入力してください")
    If StrPtr(mes) = Cancel Then
       MsgBox "キャンセルボタンが押されました"
    Else
       MsgBox "入力されたデータは  " & mes
    End If
 End Sub

 以上です。

(ichinose) 2014/06/17(火) 05:12


 ありがとうございます。TANAKAさんよりわかりやすい説明です!

 0が入力されたとき区別がつかないと、いつからか思い込んで、
 今まで、Type2のときは、TypeNameで判定しないようにしていました。

(マナ) 2014/06/17(火) 07:56


 マナ様・ichinose様

 様々なご指導をありがとうございます。
 ichinose様のご指摘を解読しようとゆっくり時間をかけて読んでみました。
 まだ少し私の知識が追い付いていかない部分もあるのですが、
 おっしゃている事は何となくですが、理解できたような気がします。

 コードを変えた理由は、自分のコードに自信がなかったので
 マナ様に教えて頂いたサイトを参考に作成してみただけです。
 まだ、どちらが適切か。という判断に自信が持てないので。。。

 マナ様に教えて頂いたループコードを参考にますます希望通りのものができました。
 本当にありがとうございました。
 今後とも宜しくお願い致します!
(りんご) 2014/06/17(火) 13:31

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.