- ベストアンサー
エクセル(VBA)上でINPUTBOX以外の入力方法ないでしょうか?
子供向けに暗算ドリルを作成しようと考えています。 VBAで、Range("A1")=InputBox("答えは?")と記述すれば、シート上にINPUTBOXが現れて、セルA1に答えを入力できますね。画面上にINPUTBOXを表示させるのは、違和感を感じてます。 「A1に問題を次々に表示させ」「A1に”答えは?”と表示させ」「A1に答えを入力させ」「A1に”正解です”表示」するような、スマートな入力方法はありますか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 もしも、#1のコードで私のコンセプトを書いたのにも関わらず、そして、私のアドバイスがあまり役に立たないようでしたら、とりあえず、コードを見せてください。そして、どのようなご要望なのかお書きになっていただけませんか? InputBox 以外では、イベント・ドリブン型マクロが最適だと思います。
その他の回答 (3)
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。 全体のコードを見せていただきたいのですが、今は、ほとんど分かりません。 >乱数は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)
こんにちは。 こんにちは。 すみません。一度、そのコードを試していただければ、ご質問に対する回答は分かっていただけると思ったのですが、こちらの勝手な思い込みでした。参考にはしていただけなかったようです。今回の私のプログラムは、ある程度、VBAの経験者でないと、その起動やメカニズムが分からないかもしれませんが。この種のものは、想像するより遥かに難しい種類のものだと思います。 >画面上にINPUTBOXを表示させるのは、違和感を感じてます。 一応、そのご質問に対する回答したと思っていたのですが、お分かりにならなかったようですね。 私の書いたコードでは、読み切れれば分かるはずですが、回答の結論からすると、InputBox の代わりにWorksheet_Change イベント・ドリブン型を使ったら、どうか、ということです。アプリケーション内部のものなら、反応スピードも速いし、使い勝手も悪くありません。 それに、VBA上の InputBox では、まず、文字が小さすぎます。ある程度の大きさがないと、認識スピードが落ちます。私の場合は、ワークシート上に、出現する問題のフォント・サイズは、20ポイントを使用しています。 完全に、Active X コントロール形式にするなら、UserForm上で、TextBox とLabel を駆使して行えばよいと思います。しかし、UserFormは若干、反応スピードが遅いように思います。UserFormは、VB のForm とは違って、ワークシートという巨大なメモリ消費があるし、Active X コントロールという、ある意味では、外部プログラム・ツールだからだと思います。 ちなみに、私は、VBA歴4年目に入りますが、アルゴリズムは、そんなに使いこなせるレベルではありません。今回の乱数発生のアルゴリズムは知りません。そういうものは、存在するのでしょうか?
補足
ありがとうございます。 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)
こんにちは。 それは、やはりセル上で行ったほうがよいですね。 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
お礼
ありがとうございます。 VBA浅くしか知らないのですが、出題のアルゴリズムは 出来ています。答え入力させるところだけ不本意でありながら、INPUTBOX使ってます。 ご回答いただいたどの部分が、「回答入力」に相当する箇所でしょうか? If IsNumとか Exit Subを知らない素人です。 宜しく教示お願いします。
お礼
ありがとうございました。 PC電源アダプター故障でT社にメンテに出したら、1月以上要し、ご返事できませんでした。 VBに関してかなり素人ですので、ご回答を理解できるよう努力したと思います。