• ベストアンサー

エクセル(VBA)上でINPUTBOX以外の入力方法ないでしょうか?

子供向けに暗算ドリルを作成しようと考えています。 VBAで、Range("A1")=InputBox("答えは?")と記述すれば、シート上にINPUTBOXが現れて、セルA1に答えを入力できますね。画面上にINPUTBOXを表示させるのは、違和感を感じてます。 「A1に問題を次々に表示させ」「A1に”答えは?”と表示させ」「A1に答えを入力させ」「A1に”正解です”表示」するような、スマートな入力方法はありますか?

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

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

こんにちは。 もしも、#1のコードで私のコンセプトを書いたのにも関わらず、そして、私のアドバイスがあまり役に立たないようでしたら、とりあえず、コードを見せてください。そして、どのようなご要望なのかお書きになっていただけませんか? InputBox 以外では、イベント・ドリブン型マクロが最適だと思います。

kmasumi
質問者

お礼

ありがとうございました。 PC電源アダプター故障でT社にメンテに出したら、1月以上要し、ご返事できませんでした。 VBに関してかなり素人ですので、ご回答を理解できるよう努力したと思います。

その他の回答 (3)

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

こんにちは。 全体のコードを見せていただきたいのですが、今は、ほとんど分かりません。 >乱数はRange("A1") = Int((Ketasuu * Rnd) + 1)を Randomize は、使用しておられますか? 以下は、この方法では、無理です。 Do While Sheets("sheet1").Range("A1") = "答えは?" Sheets("sheet1").Range("A1").Select Loop また、Sheets("sheet1") ではなくて、Worksheets("Sheet1") の方がよいです。トラブルはありませんが、Sheets オブジェクトとWorksheets オブジェクトは、若干違います。 入力待ち状態を、Do ~ Loop でも出来ないことはありませんが、いくら、Application 側に、キーのインターラプトを許しても、メモリ消費が激しいので、それは、やめたほうがよいです。イベント・ドリブン型マクロのほうが安全です。そうでなければ、UserForm やコントロールツールのTextBox で、KeyDown イベントで、キーを監視させるか、いくつかの方法があります。 >UserFormと次のコマンドの組み合わせも考えましたが、InputBoxと同様になってしまうので止めました。 今の段階では、どちらがどうという話は、水掛け論になってしまいますから、辞めておきますが、UserForm の使い方は、もう少し別だと思います。 なお、アルゴリズムというのは、先人が作ったもので、汎用性・移植性・拡張性のあるコードです。古代から、現代に至るものまで、いろんな時代のコンピュータに移植されてきたプログラムの一種です。VBAでは、めったにお目にかからないものです。

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

こんにちは。 こんにちは。 すみません。一度、そのコードを試していただければ、ご質問に対する回答は分かっていただけると思ったのですが、こちらの勝手な思い込みでした。参考にはしていただけなかったようです。今回の私のプログラムは、ある程度、VBAの経験者でないと、その起動やメカニズムが分からないかもしれませんが。この種のものは、想像するより遥かに難しい種類のものだと思います。 >画面上にINPUTBOXを表示させるのは、違和感を感じてます。 一応、そのご質問に対する回答したと思っていたのですが、お分かりにならなかったようですね。 私の書いたコードでは、読み切れれば分かるはずですが、回答の結論からすると、InputBox の代わりにWorksheet_Change イベント・ドリブン型を使ったら、どうか、ということです。アプリケーション内部のものなら、反応スピードも速いし、使い勝手も悪くありません。 それに、VBA上の InputBox では、まず、文字が小さすぎます。ある程度の大きさがないと、認識スピードが落ちます。私の場合は、ワークシート上に、出現する問題のフォント・サイズは、20ポイントを使用しています。 完全に、Active X コントロール形式にするなら、UserForm上で、TextBox とLabel を駆使して行えばよいと思います。しかし、UserFormは若干、反応スピードが遅いように思います。UserFormは、VB のForm とは違って、ワークシートという巨大なメモリ消費があるし、Active X コントロールという、ある意味では、外部プログラム・ツールだからだと思います。 ちなみに、私は、VBA歴4年目に入りますが、アルゴリズムは、そんなに使いこなせるレベルではありません。今回の乱数発生のアルゴリズムは知りません。そういうものは、存在するのでしょうか?

kmasumi
質問者

補足

ありがとうございます。 VBAは年に数回使用する程度で深くは知らないのです。 乱数はRange("A1") = Int((Ketasuu * Rnd) + 1)を 使用してます。桁数で問題の難易度を調整しました。 色々試してみました。次のコマンドは、デバックモードでは有効なんですが、実行モードではループ状態になってしまいます。(入力を受け付けない状態) Do While Sheets("sheet1").Range("A1") = "答えは?" Sheets("sheet1").Range("A1").Select Loop UserFormと次のコマンドの組み合わせも考えましたが、InputBoxと同様になってしまうので止めました。 Worksheet_SelectionChange(ByVal target As Excel.Range)

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

こんにちは。 それは、やはりセル上で行ったほうがよいですね。 InputBox は、あまり関心しません。 「A1に問題を次々に表示させ」 「A1に”答えは?”と表示させ」 「A1に答えを入力させ」 「A1に”正解です”表示」 問題を一旦、消してしまうのですか? 大人用でしたら、消してもよいと思いますが、ちょっと問題がシビアではありませんか? 問題は答えを入れて、合ったら消すという方法がよいのではないかと思います。 A2, B2, C3, 答えは、E2  A  B    C   D   E  F               正解です!/間違っています(^_^;)  5  +   3  = (ここに答えを入れる)                     以下は、ご質問のイメージはかなり違うと思いますが、私の作ったものを、サイズダウンしてたものです。本当は、以下のコードに重複チェッカーと言って、同じものが出てくる場合に、それを回避するプログラムなどが付けられます。どちらかというと、これは、高齢者向けかもしれません。 試してみると、なんとなく、問題の出方に癖があるような気がします。一度、参考にしてみてください。 最初だけ、MakeQuestion で、問題を表示させてください。後は、続いて、問題が出てきます。10問終えると、続けるかどうか聞いてきます。 '--------------------------------------------------------------- '標準モジュール 'Option Explicit Public Const QT_TOTAL As Integer = 10 '問題数 Public myCount As Variant 'カウント Sub MakeQuestion() '問題作成 Dim Arg1 As Variant Dim Arg2 As Variant Dim Arg3 As Variant Dim ArgTmp As Variant Dim Res As String Dim Sn As Integer Dim Ope As Variant Dim Ret As Integer '問題数のカウント If myCount >= QT_TOTAL And Not myCount = Empty Then  Ret = MsgBox("問題数は、" & myCount & "個行いました。" & vbCrLf & _   "再び続けますか?", vbInformation + vbYesNo)  If Ret = vbYes Then    myCount = Empty  ElseIf Ret = vbNo Then    myCount = Empty    Exit Sub  End If End If Start: '乱数発生   Arg1 = Empty   Arg2 = Empty   ArgTmp = Empty   '開始   Randomize '乱数ジェネレータの初期化      Arg1 = Int(Rnd() * 9) + 1   Do   ArgTmp = Int(Rnd() * 9) + 1   Loop Until Arg1 <> ArgTmp   Arg2 = ArgTmp   '演算子選択   Randomize   Sn = Int(Rnd() * 4)   Ope = Array("+", "-", "×", "÷")   '演算      Select Case Sn    Case 0 '足し算     Res = Arg1 + Arg2    Case 1 '引き算     If Arg1 < Arg2 Then      ArgTmp = Arg2      Arg2 = Arg1      Arg1 = ArgTmp      Res = Arg1 - Arg2     Else      Res = Arg1 - Arg2     End If    Case 2 '掛け算     Res = Arg1 * Arg2    Case 3     If (Arg1 * Arg2) / Arg2 = 1 Then      Do       Arg1 = Int(Rnd() * 9) + 1       Arg2 = Int(Rnd() * 9) + 1      Loop Until ((Arg1 * Arg2) / Arg2) <> 1     End If     Arg1 = Arg1 * Arg2     Res = Arg1 / Arg2   End Select   '問題数のカウント   myCount = myCount + 1   '問題表示   Application.EnableEvents = False   Range("A2").Value = Arg1   Range("B2").Value = Ope(Sn)   Range("C2").Value = Arg2   Range("D2").Value = "= "   Application.EnableEvents = True End Sub '----------------------------------------------- 'シートモジュール 'Option Explicit Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Sub Worksheet_Change(ByVal Target As Range) Dim Arg1 As String, Arg2 As String, Arg3 As String Dim Ret As Long Dim Ope As String  'E2に解答を入れます。  If Target.Address(0, 0) <> "E2" Then Exit Sub  If Target.Count > 1 Then Exit Sub  Arg1 = Range("A2").Value  Arg2 = Range("C2").Value    Select Case StrConv(Range("B2").Value, vbWide)  Case "-"    Ope = "-"  Case "×"    Ope = "*"  Case "÷"    Ope = "/"  Case "+"    Ope = "+"  Case Else    Ope = "?"  End Select  If Ope = "?" Then    Range("E1").Value = "エラーが起きていますので、もう一度問題を作ります。"    Sleep 1500    Range("E1:E2").Clear    Range("E2").Select    Call MakeQuestion    Exit Sub  End If  If IsNumeric(Target.Value) Then   Ret = Evaluate("=" & Arg1 & Ope & Arg2)  Else   Range("E1").Value = "答えをを入れてくださいね"   Sleep 1500   Range("E1:E2").Clear   Range("E2").Select   Exit Sub  End If  If Target.Value = Ret Then    Range("E1").Font.ColorIndex = 3    Range("E1").Value = "ハイ!正解です。 (残り" & CStr(QT_TOTAL - myCount) & "個)"    Sleep 1500    Range("E1:E2").Clear    Range("E2").Select    Call MakeQuestion    Exit Sub  Else    Range("E1").Value = "間違えました。(^_^;)"    Beep    Sleep 1500    Range("E1").Value = "もう一度答えを入れてください。"    Sleep 1000    Range("E1:E2").Clear    Range("E2").Select    Exit Sub  End If End Sub

kmasumi
質問者

お礼

ありがとうございます。 VBA浅くしか知らないのですが、出題のアルゴリズムは 出来ています。答え入力させるところだけ不本意でありながら、INPUTBOX使ってます。 ご回答いただいたどの部分が、「回答入力」に相当する箇所でしょうか? If IsNumとか Exit Subを知らない素人です。 宜しく教示お願いします。

関連するQ&A

専門家に質問してみよう