InputBoxメソッドでセルを指定させる目的の、以下のコードについて質問です。
VBA
1 2Public Sub test() 3 Dim outputcell As Variant 4 5 'セル取得 6 outputcell = Application.InputBox("セルを選択してください", , , , , , , 8) 7 If outputcell = False Then 8 MsgBox False 9 Exit sub 10 End If 11 12 outputcell.value = "セル取得成功" 13 14End Sub 15
InputBoxメソッドの引数Typeに8を設定し、セル参照(Rangeオブジェクト)のみを入力可能にしています。
キャンセルを押されたときのことを考え、変数outputcellをVariant型にしました。
これを実行すると、セルを指定してもキャンセルを押してもoutputcellにfalseが入ってしまいます。
因みに、引数Typeに12(論理値またはセル参照)を設定すると、論理値しか指定できなくなってしまいました。
適切な値を得るには、どうしたらよいのでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
んと、、、
https://www.moug.net/tech/exvba/0150102.html
http://officetanaka.net/excel/vba/tips/tips37.htm
この辺を参考にすると、
セル範囲を変数に代入するときは、
Setステートメントを使用しなければなりません。
単に変数の型をVariant型にするだけでは、
「オブジェクト」を変数に代入できません。
つまり、Set outputcell = Application.InputBox("セルを選択してください", , , , , , , 8)
こうかかないといけません。
が、キャンセルを押すと、Falseという論理値が返ってくるので、
エラーになりますよね。
両方に対応するのは厄介ですね。
こういうときは、
On Errorステートメントを使い、エラーを回避します。
エラーを無視したときは、
変数の中身はNothingのままですので、
変数の中身がNothingかどうかで、キャンセルが押されたかの判定をします。
ExcelVBA
1Option Explicit 2 3Public Sub test() 4 Dim outputcell As Range 5 6 Application.DisplayAlerts = False '空でOKしたときの的外れなメッセージの表示を抑制 7 On Error Resume Next 8 Set outputcell = Application.InputBox("セルを選択してください", , , , , , , 8).Cells 9 On Error GoTo 0 10 Application.DisplayAlerts = True 11 12 If outputcell Is Nothing Then 13 MsgBox "キャンセルしました。" 14 Else 15 outputcell.Select 16 MsgBox outputcell.Address(False, False) & " を選択しました。" 17 End If 18End Sub
投稿2019/07/13 00:59
編集2019/07/13 01:17総合スコア2167
0
ベストアンサー
VBAの「値型とオブジェクト型で代入の方法が異なる」という仕様の関係上、きれいに処理することは難しいです。
またVarType関数についても、仕様上今回の用途では使いにくいです。
対策案1 エラーで判定
キャンセルを考慮せず、セル(オブジェクト)が返されるという前提で処理を行い、
エラーが発生したらキャンセルされた、と判断する方法です。
恐らくこちらの方が一般的な方法だと思います。
On Error Resume Next
によって、代入時のエラーに対して処理を行っています。
vba
1'https://teratail.com/questions/200242 2Public Sub teratailQ200242_OnError() 3 Const XlInputBoxTypeRange = 8 4 5 Dim outputcell As Excel.Range 6 7 'セル取得 8 On Error Resume Next 9 Set outputcell = Application.InputBox("セルを選択してください", Type:=XlInputBoxTypeRange) 10 'キャンセルされた場合はBooleanが返ってくるので 11 'エラー番号91:オブジェクト変数または With ブロック変数が設定されていません。 12 'のエラーが発生する 13 If Err.Number <> 0 Then 14 MsgBox False 15 Exit Sub 16 End If 17 On Error GoTo 0 18 19 outputcell.Value = "セル取得成功" 20 21End Sub
対策案2 結果で判定
「値型とオブジェクト型で代入の方法が異なる」という仕様
に関しては、代入部分を別プロシージャに切り出し、参照渡しの引数を使うことでむりやり対処することができます(例:下記コードSetVar
)。
結果を変数に入れてしまえば、後は普通に判定するだけ、となります。
この判定のときの注意として、
If inputBoxResult = False Then
とした場合、セルの値が0、空(Empty)、Falseの場合もNGになってしまいますし、エラー値や複数セル選択の場合はエラーで止まってしまいます。
If VarType(inputBoxResult) = vbBoolean Then
とした場合、VarType関数は既定のメンバーの値を見に行くため、セルにFalseが入っている場合もNGとなってしまいます。
そのため下記コードでは「Object型に適合するかどうか?」の判定関数であるIsObject
を使って判定しています(VBAのほとんどのオブジェクトはObject型に適合し、ExcelのRangeもそうであるため)。
vba
1'https://teratail.com/questions/200242 2Public Sub teratailQ200242_NotOnError() 3 Const XlInputBoxTypeRange = 8 4 5 'セル or Flase 取得 6 Dim inputBoxResult As Variant 7 SetVar(inputBoxResult) = Application.InputBox("セルを選択してください", Type:=XlInputBoxTypeRange) 8 9 If Not VBA.IsObject(inputBoxResult) Then 10 MsgBox False 11 Exit Sub 12 End If 13 14 Dim outputcell As Excel.Range 15 Set outputcell = inputBoxResult 16 17 outputcell.Value = "セル取得成功" 18 19End Sub 20 21'https://qiita.com/nukie_53/items/bde16afd9a6ca789949d#%E5%A4%89%E6%95%B0%E3%81%B8%E4%BB%A3%E5%85%A5 22Public Property Let SetVar(outVariable As Variant, inExpression As Variant) 23 If VBA.IsObject(inExpression) Then 24 Set outVariable = inExpression 25 ElseIf VBA.VarType(inExpression) = vbDataObject Then 26 Set outVariable = inExpression 27 Else 28 Let outVariable = inExpression 29 End If 30End Property
投稿2019/07/13 00:47
総合スコア2166
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
セル取得以外の場合は TanakaHiroakiさんの回答でいいのですが、
セル取得(Type引数が8)の場合はそれではダメです。
エラー処理で判断します。
vba
1Public Sub test() 2 On Error Resume Next 3 Dim outputcell As Range 4 'セル取得 5 Set outputcell = Application.InputBox("セルを選択してください", Type:=8) 6 If Err.Number <> 0 Then 7 MsgBox "キャンセルされました。" 8 Exit Sub 9 End If 10 On Error GoTo 0 11 outputcell.Value = "セル取得成功" 12End Sub
投稿2019/07/13 00:41
編集2019/07/13 00:49総合スコア34352
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
<回答後追記>
複数の方から、今回の質問、つまり、Application.InputBoxでセル取得(Type引数が8)の場合、キャンセルを判定するために、単にVBAのVarType関数を用いるだけでは不可能であるとのご指摘をいただきました。
下記回答を撤回します。
キャンセルについては、以下のように、VarTypeで判定する方法があります。
VBA
1' If outputcell = False Then 2 If VarType(outputcell) = vbBoolean Then 3 MsgBox False 4 Exit Sub 5 End If
投稿2019/07/12 16:23
編集2019/07/13 01:32総合スコア1065
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。