[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『VBA 英語の前置詞を学習する教材の開発。』(OREO)
はじめまして、こんばんは。掲示板を初めて利用させて頂きます。不備などございましたら申し訳ございません。改善致します。
ただいま英語の前置詞を学習することを目的とした教材開発を行っております。そこでお伺いしたいことがございますので、ご回答頂ければ幸いです。
お伺いしたいことは2点あります。1つ目は、コンボボックスで選択している値と同じ値のある行を参照したいこと(伝わりづらいと思いますので下で詳しく書きます)。2つ目は、問題の選択肢の表示方法についてです。
教材の簡単な内容ですが、イラストを表示し、イラストに合う1文を選択するものです。問題文はすべて前置詞が含まれています。例えば、「机の上の本が欲しい」と見て理解できるイラストを表示し、正解の選択肢である "I want the book on the table." と、不正解の選択肢である "I want the table on the book." を表示するというものです。ちなみに、選択肢はActive x コントロールのオプションボタンで選択できるようにしようと考えています。
――――
まず1つ目です。
シート1にコンボボックスを配置していて、そのコンボボックスでは前置詞の種類を選べるようにしてあります(onやinなど)。問題を開始するためのコマンドボタンも配置しています。そして、別のシート(Sheet6)に問題をいくつか用意してあります。
シート6のA列には前置詞の種類、B列には正解の選択肢、C列には不正解の選択肢、D列には画像の参照先(まだ設定していません)、E列には問題文をシャッフルする乱数を設けています。乱数の小さい順で、例えば3問、問題を出題するようにしようと考えています。
シート1のコンボボックスで選択している前置詞と同じ前置詞の問題だけを出すようにしたいのですが、どうすればよいでしょうか?問題を出すのは、シート2の画面へ、イラスト、オプションボタンと正解の選択肢、オプションボタンと不正解の選択肢の3点セットを表示させたいです。場所は表示させる場所は今のところ決めていませんが、イラストをシート2の上部に、その下へ選択肢2つを上下にセットで配置しようと考えています。
――――
2つ目です。問題の選択肢の表示方法についてです。
出題される問題の乱数は設定しており、ランダムに問題が出題されるようにと考えています。それと同時に上下に表示する予定の選択肢(例えば、セルのA10へオプションボタンと正解の選択肢を、A12へオプションボタンと不正解の選択肢を表示する)もシャッフルしたいと思っています(A10が不正解にA12が正解になることもあるように)。
ただし、問題1問1問を1行ごとに用意していて、既に出題する問題をランダムに出すための乱数を用意しています。
どのようにすれば選択肢もシャッフルできるでしょうか?
――――
大変長くなり申し訳ございません。
1つ目、コンボボックスと同じ前置詞の問題を表示する。
2つ目、シート6の1行ごとに正解と不正解の選択肢があり、問題をシャッフルするための乱数も同じ行で1種類ある時に、さらに選択肢の表示を上下シャッフルする。
についてご意見ご教授頂ければ幸いです。
< 使用 Excel:Excel2016、使用 OS:Windows10 >
レイアウトとサンプルデータを掲示して頂くと理解しやすいのですが・・
>シート1のコンボボックスで選択している前置詞と同じ前置詞の問題だけを出すようにしたい
シート6のA列を順にチェックして、
コンボボックスと同じ前置詞だけピックアップしていけばいいと思うんですけど、
何かネックになることがあるんでしょうか?
>出題される問題の乱数は設定しており、ランダムに問題が出題されるようにと考えています。
ここ、ちょっと分からないです。
VBAで処理する場合、普通はその都度乱数を発生させるので、
「設定しており」があらかじめ書いてあるような印象を受けますが、実際どうなんでしょうか?
(半平太) 2018/12/11(火) 09:19
補足です。
> レイアウトとサンプルデータを掲示して頂くと理解しやすいのですが・・
配置図は正確に、データは適当(※)でいいです。
※ 本物である必要はないです。下例のような表現で結構です。
例:前置詞Toの質問1番目、前置詞Forの質問3番目の正解
(半平太) 2018/12/11(火) 09:39
シート6(問題が格納されたシート)のサンプルを書きます。改行等はうまくできていますかね?プレビューの段階では理解できるように整頓しているつもりですが。横長なもので・・・。
A B C D E
種類 正解文 不正解文 画像の参照 問題の乱数
on I want the book on the table. I want the table on the book. 画像を参照するコード 乱数
on I want the book on the PC. I want the PC on the book. 画像を参照するコード 乱数
in I want the pencil case in the box. I want the box in the pencil case. 同上 乱数
A〜Eは列を示しています。1行目にはタイトル行を用意しています。さらにその下へ次々と問題があるという形です。ちなみに、問題は追加できるようにシート5に問題追加用のユーザーフォームを用意してあります。D列の画像を参照するコードですが、各問題と一緒に表示するイラストを抽出(?)するためのものと考えていますが、まだ調べてコードを書いてという作業ができていませんので、実際のデータでは空欄にしています。
>正解か不正解かの2択で考えています。目的語と前置詞句内の名詞(最初の問題の正解文で言えば、book と table のことです)がどのような関係にあるのかを認識するための教材として考えており、厳密には前置詞による後置修飾の教材と考えています。どちらも文法的には誤りのない文ですが、イラストに合うかどうかで正解かどうかが決まるため、問題の構造上必然的に2択になったといった感じでしょうか。
>コンボボックスと同じ前置詞の問題を扱うには、シート6のそれぞれの行に対してIFなどを用いてコンボボックスの値と同じ時に・・・という操作になるでしょうか?
>乱数は確かにその都度発生するものですよね。おっしゃる通りで、問題を始める際に乱数を発生し直し、毎回ランダムに問題が出されるようにはしております。シート1にある問題開始をするためのコマンドボタンにそのコードは書いてあります。仕様書を作っていた際にはシート6のF列に選択肢をシャッフルするための乱数を発生させればよいと安直に考えていましたが、同じ行内に正解と不正解の選択肢があるため、単にF列に乱数を発生させても意味が無いと気づきました。そこで、別のシートへ必要な行だけ(一回のプレイで問題を解く数は未定ですが、開発者側が5問であったり10もんであったりと設定できるようにと考えています。5問解いてもらうなら、5行だけ)をコピーしてさらに正解と不正解の選択肢を2行に分けて、それぞれに乱数を振ろうと考えました。しかし、それでは以下のようになってしまうと考えました。
――――
選択肢 乱数
I want the book on the table. 3
I want the table on the book. 2
I want the book on the PC. 4
I want the PC on the book. 1
――――
乱数の小さい順で表示していけば、別の問題の、イラストに合うはずのない選択肢が表示される場合があります。むしろイラストに合った正解の選択肢が表示されない場合があります。問題ごとに別々のシートを用意しようかとも思いましたが、10問出題するのに、余分に10個のシートを扱うのはどうも経済的ではない気がしまして・・・。
そこで、選択肢をシャッフルして出すにはどうすればいいか迷っておりました。また、正解か不正解かを判断するために、オプションボタンを用意しようと考えていましたが、そうなるとさらにどうすれば良いか見当もつかないようになってしまいました。オプションボタンではない方が良いなどの意見も頂ければと存じます。
現在のところ、正解だと思うオプションボタンを選択し、決定のボタン(コマンドボタン)を押すことで正解か不正解かが分かるようにし、次の問題へと移る、というように考えています。選択肢2つをコマンドボタン2つで表示するだけの方が良いでしょうか?どちらにせよ、ボタンも選択肢と一緒にシャッフルした上で、正解か不正解かを正しく表示できるようにしたいです。
質問が増えてしまっていますね・・・。
意見だけでも結構ですので、頂ければ幸いです。よろしくお願い致します。
(OREO) 2018/12/11(火) 11:08
回答ではないが。 書き込むときに頭に半角スペースを入れると書き込んだとおりに表示される。 (ねむねむ) 2018/12/11(火) 11:11
そして、現在はシート上にボタン等を置いて操作する事を考えているようですが、1問解く毎にユーザーフォーム上で画像や問題、選択肢を表示して、選択肢ボタンを押していく、なんていう実現方法はいかがでしょうか?
(???) 2018/12/11(火) 11:55
ほぼすべてマクロで考えています。開発者ではない別の第3者が扱うことをメインに考えているので、特に教材の利用者が触るシート1のスタート画面や、シート2の問題が表示される画面に数式を入力するのは避けたいと考えていました(問題追加のシートや問題集のシートは教材の利用者は編集できないようにしています)。セルの保護等をすれば問題はないかもしれませんが、できることであれば不必要な痕跡は残したくないと考えています。乱数は問題のプレイをする度に発生します。1回のプレイで解く問題数は可変にしたいです。そして、問題をプレイするためのコマンドボタンをクリックすれば、乱数が発生し、それにより問題が5問なり10問なり抽出されるようにしたいです。
とにかく今解決したいのは、問題を出す方法と、選択肢をどうシャッフルするかです。
ユーザーフォームで表示する場合、選択肢の配置のシャッフルは可能でしょうか?例えば、同じ問題が2度目以降のプレイで表示された時、前回と変わらず、正解の選択肢が上で不正解の選択肢が下に表示されるのではなく、回数を経る度に配置が変えられるようにしたいということです。
以下は問題をプレイするためのコマンドボタンを押した時のコードの一部です。他にタイマー設定などもしていますが、省いています。
シートのオブジェクト名を "ws1" や "ws2" のようにしています。
――――
Private Sub スタート_Click()
'乱数で用いる変数
Dim i As Long, ran As Long, myNum As Long
Dim myFlag(1 To 10000) As Boolean
'リストから前置詞を選んで問題を開始させるさせる。 If ws1.ComboBox1.MatchFound = False Then
MsgBox "リスト内のデータを入力して下さい。" Exit Sub
End If
ran = ws6.Cells(Rows.Count, 1).End(xlUp).Row
'乱数のリセット
ws6.Columns("E").Clear
ws6.Range("E1").Value = "問題の乱数"
'乱数系列を初期化 Randomize
For i = 2 To ran Do '乱数=Int((最大値 - 最小値 +1 ) * Rnd + 最小値) myNum = Int(((ran - 1) - 1 + 1) * Rnd + 1) Loop Until myFlag(myNum) = False
ws6.Cells(i, 5).Value = myNum myFlag(myNum) = True Next i
With ws2 .Range("I1", "J1").Clear .Select End With
End Sub
――――
最後にシート2で少し操作していますが、ここにどんどんコードを書いていき、問題が表示できるマクロにしたいと思っています。I1とJ1をクリアしていますが、タイムリミットの表示を一旦消すためのものなので、お気になさらないで下さい。
(OREO) 2018/12/11(火) 12:43
シート6(Sheet6、と仮定)だけ使って(ランダム列は使いません)、フォームで実現する例なぞ作ってみましたので、試してみてください。 マクロって、使い方次第で何だってできるのですよ。
まず、UserForm1をプロジェクトに挿入した後、ComboBoxとImage、TextBoxを2つ貼ってください。 後は、フォームモジュールに以下のマクロを貼ってください。
シート側にはActiveXのボタンを貼っているかと思いますが、そこに UserForm1.Show とだけ書くと、ボタンを押すとフォーム表示して開始になります。
Const SU = 3 Dim cDimQ() As String Dim cDimA() As String Dim iCount As Long Dim iCountOK As Long Dim iCountNG As Long Dim iFlag As Long Dim iMax As Long
Private Sub ComboBox1_Change() If iFlag = 1 Then If MsgBox("リセットしても良いですか?", vbYesNo Or vbQuestion) = vbYes Then iFlag = 0 Call qStart End If End If End Sub
Private Sub CommandButton1_Click() If cDimA(iCount - 1) = CommandButton1.Caption Then iCountOK = iCountOK + 1 Else iCountNG = iCountNG + 1 End If Call qChg End Sub
Private Sub CommandButton2_Click() If cDimA(iCount - 1) = CommandButton2.Caption Then iCountOK = iCountOK + 1 Else iCountNG = iCountNG + 1 End If Call qChg End Sub
Private Sub UserForm_Initialize() Dim i As Long
With Sheets("Sheet6") iMax = .Cells(.Rows.Count, "A").End(xlUp).Row For i = 2 To iMax ComboBox1.Text = .Cells(i, "A").Text If ComboBox1.ListIndex < 0 Then ComboBox1.AddItem .Cells(i, "A").Text End If Next i End With Call qStart iFlag = 1 End Sub
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
Randomize
With Sheets("Sheet6") For i = 2 To iMax If ComboBox1.Text = .Cells(i, "A").Text Then ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1 End If Next i End With
For i = 1 To UBound(cDimQ) iw = WorksheetFunction.RandBetween(0, iC - 1) cw = cDimQ(iw) cDimQ(iw) = cDimQ(i) cDimQ(i) = cw Next i
ReDim cDimA(UBound(cDimQ)) For i = 0 To UBound(cDimQ) vw = Split(cDimQ(i), "|") cDimA(i) = vw(0) If Rnd() * 2 < 1 Then cDimQ(i) = vw(1) & "|" & vw(0) & "|" & vw(2) End If Next i
iCount = 0 iCountOK = 0 iCountNG = 0 Call qChg End Sub
Sub qChg() Dim vw As Variant
If iCount < SU Then vw = Split(cDimQ(iCount), "|") CommandButton1.Caption = vw(0) CommandButton2.Caption = vw(1) Image1.Picture = LoadPicture(vw(2)) iCount = iCount + 1 Caption = iCount Else MsgBox "正解:" & iCountOK & vbLf & _ "不正解:" & iCountNG, vbInformation, "終了" Call qStart End If End Sub (???) 2018/12/11(火) 14:40
さて、マクロの方ですが、問題の選択肢もシャッフルできていて、ちゃんと動作することを確認できました。本当にありがとうございます。このコードを基に教材の開発を進めていきたいと思います。
本当にありがとうございました。重ねてお礼申し上げます。
(OREO) 2018/12/11(火) 15:34
すぐ上の頂いたコードで、前置詞の種類を選ぶコンボボックスがユーザーフォーム内にあると思うのですが、シート上に表示したいと思っています。あるいは、そのままでも大丈夫ですが、今の状態ですと、前置詞の種類を選択するのがうまくいかない場合があります。具体的に言えば、一度前置詞の種類を選んでしまうと、すぐ後に選びなおすことができません。1問解いた後だったらリセットできるようなのですが、うまくいく方法はないでしょうか?
また、今は一度のプレイで正解数と不正解数を表示されるだけですが、前置詞の種類ごとに正解数を記録したいと考えています。例えば、onでの正解数は今までで10問であるといった具合です。できれば、15問中10問のような正解率がシートへ表示できると、よりよいかと思っています。
前回ご回答頂いた日から随分とあいてしまいましたが、どうかよろしくお願い致します。どなたでも、アイディアだけでもありがたいです。
(OREO) 2018/12/25(火) 11:26
シート上にコンボを置く、というより、「データの入力規則」を使って、セルをコンボ選択させると簡単でしょう。 この場合、選択肢固定で良ければ、後は難しくないと思います。 ComboBox1 に関係する箇所が不要になり、選択肢はセル値を参照するようになりますね。
または、別案としては、コンボ選択するフォームと、回答するフォームの2つに分けてしまっても、すっきりするのではないかと思います。 回答を最後まで行うと、コンボフォームに戻って、このときに成績記録すれば良いでしょう。
(???) 2018/12/25(火) 11:51
そういうことだったのですね。確かに、前回は質問と回答についてでした。
データの入力規則ですか。名前はたまに聞いたり目にしたりしますが、使ってみたことが無いので勉強してみます。
別のフォームを使うというのはなぜ思いつかなかったのだろうと今ご回答を拝見して感じました。確かに分けてしまえば途中で前置詞の種類を選択し直すことはできなくなりますね。
1つお伺いしたいのですが、コンボを選択するフォームに戻って成績を記録するというのはどのような状態(?うまく表現できません)でしょうか?今回のプレイ結果を表示させて、それを記録するといった感じでしょうか?
データの入力規則は急いで調べてきます。ご回答ありがとうございます。
(OREO) 2018/12/25(火) 12:03
データの入力規則についてです。よく思い返せば、作ったことはありませんが使ったことはありました。
そこでようやく、先ほどの
>選択肢固定で良ければ
の意味が理解できました。データをどんどん追加していく性質上、選択肢を固定にしたくはありません。そこでおとなしくフォームをさらに設けようと思います。
取り急ぎ追記させて頂きます。
(OREO) 2018/12/25(火) 12:12
ユーザーフォームを2つ設けて試しています。しかし、ユーザーフォーム1で選んだ前置詞が、ユーザーフォーム2(問題のフォーム)へうまく反映されません。どうすればフォーム1で選んだ前置詞が反映されるでしょうか?
また、コンボボックスのリストの範囲を今はシート6から取って来ていると思いますが、シート4のA列を参照したいと思っています。
シート4で前置詞の種類ごとの成績を用意しようと考えていて、A列にそれぞれ前置詞の種類が入っています。さらに、前置詞の種類を指定せずにすべての問題から出題がされるようにしたいとも考えていますので、コンボボックスには「すべて」の選択肢も増やしたいと思っています。そのためシート4には、「すべて」と前置詞の「on」「in」「under」などがA列に記入されています。先日教えて頂いたコードで、以下のws6(ws6というのは、シート6のことです。シートのオブジェクト名をすべて ws1 〜 ws6 にしています
)をws4に変えると、エラーが出ました。
Private Sub UserForm_Initialize()
Dim i As Long
With ws6 '←ここをws4に変えました。 iMax = .Cells(.Rows.Count, "A").End(xlUp).Row For i = 2 To iMax UserForm1.ComboBox1.Text = .Cells(i, "A").Text If UserForm1.ComboBox1.ListIndex < 0 Then UserForm1.ComboBox1.AddItem .Cells(i, "A").Text End If Next i End With Call qStart iFlag = 1 End Sub
――――
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
Randomize
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = ws4.Cells(i, "A").Text Then 'ここへws4を追加しています。 ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1 End If Next i End With (以下省略)
以上を変えると、vw = Split(cDimQ(iCount), "|")という部分でエラーが出たようです。
Sub qChg() Dim vw As Variant
If iCount < SU Then vw = Split(cDimQ(iCount), "|") '←この部分が黄色くマーカーをひかれました。 CommandButton1.Caption = vw(0) CommandButton2.Caption = vw(1) Image1.Picture = LoadPicture(vw(2)) iCount = iCount + 1 Caption = iCount Else MsgBox "正解:" & iCountOK & vbLf & _ "不正解:" & iCountNG, vbInformation, "終了" Call qStart End If End Sub
いろいろ試してみましたがどれもうまくいきませんでした。
ユーザーフォーム1には、前置詞の種類を選ぶためのコンボボックスと、問題をスタートするためのコマンドボタンが1つずつあります。
ユーザーフォーム2には、イメージが1つ、選択肢を表示するためのコマンドボタンが2つあります。
フォーム1で選んだ前置詞の問題がちゃんと表示されるようにするには、また、フォーム1の前置詞の種類を選択するためのコンボボックスのリストの範囲をシート4のA列にするためにはどうしたらよいでしょうか?
(OREO) 2018/12/25(火) 20:24
Const SU = 3
Dim cDimQ() As String Dim cDimA() As String Dim iCount As Long Dim iCountOK As Long Dim iCountNG As Long Dim iFlag As Long Dim iMax As Long
Private Sub CommandButton1_Click()
UserForm1.Hide
UserForm2.Show (vbModal)
End Sub
Private Sub UserForm_Initialize() Dim i As Long
With ws4 'ここをws6からws4へ変更。 iMax = .Cells(.Rows.Count, "A").End(xlUp).Row For i = 2 To iMax UserForm1.ComboBox1.Text = .Cells(i, "A").Text If UserForm1.ComboBox1.ListIndex < 0 Then UserForm1.ComboBox1.AddItem .Cells(i, "A").Text End If Next i End With Call qStart iFlag = 1 End Sub
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
Randomize
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = ws4.Cells(i, "A").Text Then 'ここにws4を追加で記述。 ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1 End If Next i End With
For i = 1 To UBound(cDimQ) iw = WorksheetFunction.RandBetween(0, iC - 1) cw = cDimQ(iw) cDimQ(iw) = cDimQ(i) cDimQ(i) = cw Next i
ReDim cDimA(UBound(cDimQ)) For i = 0 To UBound(cDimQ) vw = Split(cDimQ(i), "|") cDimA(i) = vw(0) If Rnd() * 2 < 1 Then cDimQ(i) = vw(1) & "|" & vw(0) & "|" & vw(2) End If Next i
iCount = 0 iCountOK = 0 iCountNG = 0 Call qChg End Sub
Sub qChg() Dim vw As Variant
If iCount < SU Then vw = Split(cDimQ(iCount), "|") UserForm2.CommandButton1.Caption = vw(0) UserForm2.CommandButton2.Caption = vw(1) UserForm2.Image1.Picture = LoadPicture(vw(2)) iCount = iCount + 1 Caption = iCount Else MsgBox "正解:" & iCountOK & vbLf & _ "不正解:" & iCountNG, vbInformation, "終了" Call qStart End If End Sub
――――――――――――――――――――――――――――――――――――――――
フォーム2のコードを
Const SU = 3
Dim cDimQ() As String Dim cDimA() As String Dim iCount As Long Dim iCountOK As Long Dim iCountNG As Long Dim iFlag As Long Dim iMax As Long
Private Sub CommandButton1_Click() If cDimA(iCount - 1) = CommandButton1.Caption Then iCountOK = iCountOK + 1 Else iCountNG = iCountNG + 1 End If Call qChg End Sub
Private Sub CommandButton2_Click() If cDimA(iCount - 1) = CommandButton2.Caption Then iCountOK = iCountOK + 1 Else iCountNG = iCountNG + 1 End If Call qChg End Sub
Private Sub UserForm_Initialize() Dim i As Long
With ws6 iMax = .Cells(.Rows.Count, "A").End(xlUp).Row For i = 2 To iMax UserForm1.ComboBox1.Text = .Cells(i, "A").Text If UserForm1.ComboBox1.ListIndex < 0 Then UserForm1.ComboBox1.AddItem .Cells(i, "A").Text End If Next i End With Call qStart iFlag = 1 End Sub
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
Randomize
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = .Cells(i, "A").Text Then ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1 End If Next i End With
For i = 1 To UBound(cDimQ) iw = WorksheetFunction.RandBetween(0, iC - 1) cw = cDimQ(iw) cDimQ(iw) = cDimQ(i) cDimQ(i) = cw Next i
ReDim cDimA(UBound(cDimQ)) For i = 0 To UBound(cDimQ) vw = Split(cDimQ(i), "|") cDimA(i) = vw(0) If Rnd() * 2 < 1 Then cDimQ(i) = vw(1) & "|" & vw(0) & "|" & vw(2) End If Next i
iCount = 0 iCountOK = 0 iCountNG = 0 Call qChg End Sub
Sub qChg() Dim vw As Variant
If iCount < SU Then vw = Split(cDimQ(iCount), "|") UserForm2.CommandButton1.Caption = vw(0) UserForm2.CommandButton2.Caption = vw(1) UserForm2.Image1.Picture = LoadPicture(vw(2)) iCount = iCount + 1 Caption = iCount Else MsgBox "正解:" & iCountOK & vbLf & _ "不正解:" & iCountNG, vbInformation, "終了" Call qStart End If End Sub
上のように変えると、まだましにはなりました。コードが重複しているところがあり問題があるような気がしますが・・・。
このマクロでの問題を具体的に言えば、フォーム1で例えばonを選んだとします。そうすれば、フォーム2では、in,under,underの順に問題が一旦表示されました(ちなみにinはリストの一番上、underはリストの一番下です)。そして続けて2回目のプレイに入ると、onの問題のみが表示されるようになりました。
なぜこのような動作になったのかが不明ですが、ひとまずフォーム1で選択した前置詞をフォーム2の問題へ反映させることには近づいた気がします(フォーム2のコードでフォーム1にあるコードと同じようにws4に変更すると、やはりエラーになりました)。
以上参考になるかわかりませんが追記させて頂きます。
(OREO) 2018/12/25(火) 20:46
iCountとiFlag、そのほか、以下のコードで定義している変数、以下のコードがひとかたまりごとに何をしているコードなのかを教えて頂けないでしょうか?
それと、ところどころ出てくる | この文字?は何のためにあるものでしょうか?
以下のコードなどで出てくるものです。
cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells
いろいろ試してみてはいるのですが、エラーばかりになってしいうまくいきません・・・。少しだけでも良いのでご教授お願いします。
以下が問題をスタートさせるためのコードかと思います。
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
iMax = ws6.Cells(ws6.Rows.Count, "A").End(xlUp).Row
Randomize
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = .Cells(i, "A").Text Then ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1 End If Next i End With
For i = 1 To UBound(cDimQ) iw = WorksheetFunction.RandBetween(0, iC - 1) cw = cDimQ(iw) cDimQ(iw) = cDimQ(i) cDimQ(i) = cw Next i
ReDim cDimA(UBound(cDimQ)) For i = 0 To UBound(cDimQ) vw = Split(cDimQ(i), "|") cDimA(i) = vw(0) If Rnd() * 2 < 1 Then cDimQ(i) = vw(1) & "|" & vw(0) & "|" & vw(2) End If Next i
iCount = 0 iCountOK = 0 iCountNG = 0 Call qChg End Sub (OREO) 2018/12/26(水) 16:49
あと、1つ目のフォームはコンボに値セットするまでだけで十分です。 それとボタンを1つ貼って、Show UserForm2 とかして2つ目のフォームに処理を移せばよろしい。 2つ目のフォームでは、UserForm1.Combobox1.Text を見れば前置詞が分かるので、後は元と同様にするだけ。 ついでに、結果表示の直前にでも、結果をシートに代入する処理を追加しましょう。 結果表示後は、Unload Me として2番目のフォームを閉じれば、1つ目のフォームに戻ります。
元のソースを、2つのフォームにコピーして2倍のコードにするのは冗長ですよ。 いっぱい書くから読めなくなって、訳が分からなくなって、直せなくなってしまうのです。 最小限だけ書けば、読みやすいし直しやすいし、バグも減るので、デバッグも簡単になる、ってもんです。
(???) 2018/12/26(水) 20:54
パイプですか。そのようなことができるものがあるんですね。配列の知識がほとんど無いのでまた余裕ができたら勉強してみようと思います。
昨日1人で悩みながらなんとかうまく動かせるようにはなりました。デバッグのやり方も恐らくままならないような状態で、とにかく試すだけ試すような力業でどうにか乗り越えようとしているので時間がかかってしまいました・・・。
結果、ユーザーフォーム1のコードは必要最低限に抑えました。シート4の前置詞をコンボボックスには表示しておいて、問題はシート6の問題集から出題することにも成功したのでようやくまた一歩進み始めました。
それともう一つ質問よろしいでしょうか?だいたいの変数とコードは少しずつ理解できてきているのですが、どうしても
Private Sub UserForm_Initialize()のプロジェクト?の部分で、 iFlag = 1 の部分がなんのためにあるのかがわかりません。これはどういうことを意図して書かれたものなのでしょうか? またお時間の許す時にご回答頂ければ幸いでございます。 (OREO) 2018/12/27(木) 22:51
iFlagは、フォームを1つにまとめた事による問題を解決するためのものだったので、フォームを分けたときは不要です。
1つにまとめていると、初期化時にコンボにデータをセットした際に、ComboBox1_Changeイベントが発生します。 しかし、最初はまだ人間が選択した訳ではないので、これは無視したかったのです。 なので、コンボへのセットが完了した際に1とすることで、人間のコンボ変更時だけ処理するようにしています。 フォーム分離したならば、問題をリセットするトリガーはコマンドボタンで行えば良いので、ComboBox1_Change時の処理が丸ごと不要になっているはずです。(qStartは、UserForm2にだけ残したはず)
元のコードを貼ったブックで、iFlagに関係する箇所(見ているのはComboBox1_Changeだけなので、ここをコメントアウトすればOK)をコメントアウトしてみれば、何故この変数を用意したのかが判ると思いますよ。
(???) 2018/12/28(金) 12:36
Split関数に関係しているのですね。VBAは私にはまだまだ分からないことばかりなのでもっと勉強しなくてはいけません。
iFlagにはそういった意図があったのですね。コメントアウト・・・コメントを使うのにそういう方法もあるんですね。たしかにいちいち消して戻してよりはるかに効率的な方法ですね。もっと早くに知っておけたならよかったと思いました。何度コードを消して戻してを繰り返したことでしょうか。
ご回答ありがとうございました。
最後になると思うのですが、もう1点お伺いしたいことがございます。今は前置詞の種類をコンボボックスより選んで、その前置詞の問題だけが出題されていると思います。コンボボックスに「すべて!」という選択肢を増やし、「すべて!」を選んだ時は全問題から出題されるようにしたいと思っています。少しやってみました。
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = .Cells(i, "A").Text Then
ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1
ElseIf UserForm1.ComboBox1.Text = "すべて!" Then
ReDim Preserve cDimQ(iC) cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1
End If
Next i End With
qStartのマクロコードにこのようにElseIfで単純に記述してみたのですが、やはりうまくはいきませんでした。エラーでピタリとも動きませんでした。すべての問題から出題するにはどのようにコードを書けばよいのでしょうか?
次々と別の質問をしてしまって申し訳ございません。
(OREO) 2018/12/28(金) 19:30
しかし、どんなエラーが表示されたのか判りませんが、エラーになりそうなコードには見えませんよ? 部分的に書き出すのではなく、全部書いてください。 おそらく、今回書かなかった部分に原因があるのでしょう。(うまく動かない、という人に限って、うまくいかない原因のある部分を見逃すものです) また、コーディングしたならエラーになることもありますが、それを書いたのは自分自身ですから、間違いを調べるのも自分でやらないと駄目ですよ。(!が、全角半角違ってた、とかいうオチだったなら怒りますよ?)
(???) 2018/12/30(日) 07:48
ElseIfでも試しましたが、今回は動作しました。前回はインデックスが有効範囲にありませんといったエラーメッセージだったと思います。
!の半角か全角かは、「すべて!」を追加しようとしたときからかなり注意をしていましたので、間違えてはいなかったと思うのですが、今やってみて動いたので100%の自信はなくなりました。もしかしたら同時に他のコーディングもしていたので、その部分で引っかかっていたのかもしれません。
まだまだ未完成ですが、以下にユーザーフォーム1と2のコードを貼っておきます。
今はさらに問題を解くときにタイマーを付けようとしているところです。あとは問題一問一問ごとに正解か不正解かも分かるように(不正解の文字を表示すれば意気消沈する恐れもあるので、「正解はコッチ」で正解の選択肢を示すように)しようと思っています。タイマーはCallメソッドで、正解不正解を一問一問表示するのはIf文ですぐに作れると思っています。
――――――――――――――――――――――――――――――――――
'こちらがユーザーフォーム1です。
Private Sub CommandButton1_Click()
If UserForm1.ComboBox1 = "" Then MsgBox "前置詞が選択されていません。" Exit Sub
End If
UserForm2.Label1.Caption = UserForm1.ComboBox1.Value
UserForm1.Hide UserForm2.Show (vbModal)
End Sub
Private Sub UserForm_Initialize() Dim LastRow As Integer Dim i As Integer
LastRow = ws4.Cells(Rows.Count, 1).End(xlUp).Row
'ユーザーフォームのコンボボックスのリストの範囲指定 For i = 2 To LastRow UserForm1.ComboBox1.AddItem ws4.Range("A" & i).Value Next i
End Sub ―――――――――――――――――――――――――――――――――― 'こちらがユーザーフォーム2です。 Dim qNum As Long '問題数の設定 Dim cDimQ() As String Dim cDimA() As String Dim iCount As Long Dim iCountOK As Long '問題の正解数 Dim iCountNG As Long '問題の不正解数 Dim iFlag As Long Dim iMax As Long 'シート6(問題集)の問題数(タイトル行があるので厳密には-1)
Private Sub CommandButton1_Click()
If cDimA(iCount - 1) = CommandButton1.Caption Then iCountOK = iCountOK + 1 '正解の時、正解数が+1 Else iCountNG = iCountNG + 1 '不正解の時、不正解数が+1 End If
Call qChg
End Sub
Private Sub CommandButton2_Click()
If cDimA(iCount - 1) = CommandButton2.Caption Then iCountOK = iCountOK + 1 '正解の時、正解数が+1 Else iCountNG = iCountNG + 1 '不正解の時、不正解数が+1 End If
Call qChg
End Sub
Private Sub UserForm_Initialize()
Call qStart
End Sub
Sub qStart() Dim i As Long Dim iC As Long Dim iw As Long Dim cw As String Dim vw As Variant
iMax = ws6.Cells(ws6.Rows.Count, "A").End(xlUp).Row
Randomize
With ws6 For i = 2 To iMax If UserForm1.ComboBox1.Text = .Cells(i, "A").Text Or UserForm1.ComboBox1.Text = "すべて!" Then
ReDim Preserve cDimQ(iC) '動的配列における配列変数の上限値を設定 cDimQ(iC) = .Cells(i, "B").Text & "|" & .Cells(i, "C").Text & "|" & .Cells(i, "D").Text iC = iC + 1
End If
Next i End With
For i = 1 To UBound(cDimQ) iw = WorksheetFunction.RandBetween(0, iC - 1) cw = cDimQ(iw) cDimQ(iw) = cDimQ(i) cDimQ(i) = cw Next i
ReDim cDimA(UBound(cDimQ)) For i = 0 To UBound(cDimQ) vw = Split(cDimQ(i), "|") cDimA(i) = vw(0) If Rnd() * 2 < 1 Then cDimQ(i) = vw(1) & "|" & vw(0) & "|" & vw(2) End If Next i
iCount = 0 iCountOK = 0 iCountNG = 0
Call qChg
End Sub
Sub qChg() Dim vw As Variant
qNum = ws4.Range("C2").Value 'シート4のC2セルの数字が問題数
If iCount < qNum Then
vw = Split(cDimQ(iCount), "|") UserForm2.Label2.Caption = iCount + 1 & " / " & qNum & "問" '何問目かを表示 UserForm2.CommandButton1.Caption = vw(0) UserForm2.CommandButton2.Caption = vw(1) UserForm2.Image1.Picture = LoadPicture(vw(2)) iCount = iCount + 1
Else
'正解数をメッセージボックスに表示。 MsgBox "正解:" & iCountOK & vbLf & _ "不正解:" & iCountNG, vbInformation, "終了"
'正解数をユーザーフォーム1に表示、0問正解の時は励まし If iCountOK < 1 Then
UserForm1.Label3.Caption = "次は頑張ろう!"
Else UserForm1.Label3.Caption = iCountOK + iCountNG & "問中" & iCountOK & "問正解!"
End If
'満点の時に"Excellent!"を表示 If iCountOK = qNum Then
UserForm1.Label4.Caption = "Excellent!"
Else
UserForm1.Label4.Caption = ""
End If
Dim LastRow As Integer Dim i As Integer
LastRow = ws4.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To LastRow
If UserForm1.ComboBox1.Text = ws4.Range("A" & i).Value Then
ws4.Range("B" & i).Value = ws4.Range("B" & i).Value + iCountOK
End If
Next i
iCount = 0 iCountOK = 0 iCountNG = 0
Unload UserForm2 UserForm1.Show
End If
End Sub
Sub myTimer() Dim myStartTime As Long 'タイマーで用いる変数 Dim iTimer As Long '秒数の変数
iTimer = ws4.Range("D2").Value 'シート4のD2セルの数字がタイムリミット
'タイマー If ws1.OptionButton2.Value = True Then 'タイムリミットモード選択の時に・・・
myStartTime = iTimer '秒数指定
myEndTime = DateAdd("s", myStartTime, Time)
Do Until myStartTime <= 0
myStartTime = DateDiff("s", Time, myEndTime)
UserForm2.Label3.Caption = myStartTime UserForm2.Label4.Caption = "Sec"
DoEvents
Loop
MsgBox "タイムオーバー"
End If
End Sub ―――――――――――――――――――――――――――――――――― タイマーもざっくりとは作っていますが、まだCallしていないので、動作確認はしていません。また、タイムオーバーになった時に問題を不正解にするコーディングもしていません。
最後になりましたが、今回ご指導して頂いた皆様、最後までアドバイスを下さった???様本当にありがとうございました。
配列の便利さには驚かされましたが、いまだに理解できていないことしかないくらいの理解度なので、時間に余裕を見つけて配列の勉強もしていきたいと思います。
本当にありがとうございました。
(アイス) 2018/12/30(日) 12:05
たぶんこれも。 http://excelfactory.net/excelboard/excelvba/excel.cgi?mode=all&namber=188319&rev=0 https://oshiete.goo.ne.jp/qa/10898512.html (BJ) 2018/12/30(日) 15:05
oshieteの方の質問を見たら、 こんな事が書いてありました。
>センター試験等の採点がどうなっているかはわからないのですが、 >生徒に何も考えずに答えることをやめさせたいので、 >同じ答えを2回以上答えた場合は、正解であってもどちらも不正解にしたいと考えています。 > >上記の例で言えば、すべて1と答えた生徒も、 >(1),(2)をどちらも1,(3),(4)をどちらも3と答えた生徒も0点となるように採点したいのです。
一教師が独断でこんな出鱈目やっていいのぉ?
(半平太) 2018/12/30(日) 16:47
最後にアイスのまま投稿してしまったのは申し訳ないと思っております。
ただ、私が投稿しているのはOREOとアイスだけですよ?あつあげ様や桃様、その他の方々は一切存じ上げません。
私が作っていたのは前置詞(onやinなど)の(厳密に言えば後置修飾の)教材です。因みに私は教員でも教育関係の仕事をしているわけではありません。もうひとつ言えば、私が掲示板に書き込んだのは今回が初めてでです。少し後に書いたのがアイス名義の方ですね。
別名を名乗ることの問題点は何かありますか?特に問題が無いと判断したので別名を利用したまでです。むしろ別名の方が便利だと思いましたので別名で利用しました。別にいろんな人を装って誹謗中傷を行なっているわけでもありませんからね。名前を変えられるのであれば必要に応じて利用するのは問題無いと思いますが。なんにせよ、好きなように想像されるのは構いませんが、関係の無い他の方々は巻き込まないで下さい。擁護していたら怪しいですが、私のせいでその方々に迷惑はかけられませんので。何度も申し上げますが、別名で投稿したことに関しては、何も問題のある行動をしたと認識はしていません。勉強不足の為に回答者様の答えを蔑ろにしてしまっているようなので、その点については申し訳ないと思っております。VBAの勉強を始めたのが1年半ほど前で、専門に勉強しているわけではなく、空き時間に少しやる程度なので、1年半といっても量としてはそれほどできていません。今ゆっくり調べる時間も無かったので蔑ろになってしまったのですかね。本当に申し訳なく思っています。後ほどアイスの方も更新します。
半平太様のコメント内容ですが、出鱈目は少し言い過ぎなような気もします。oshiete様がどのような立場の方かは分かりませんが、選択肢でずっと1をつけるような生徒に点数を付けたくなくなる気持ちはわかります。ただし、それはやってはいけないことだとも同時に思います。そもそも、全部同じ選択肢だと点数をゼロにするというのは良くないだろうと思います。点数がゼロになるからではなく、すべて同じ選択肢(例えば1)が正解の時もあると思います。まぁそのようなテストは作るべきではないですが(問題数にもよります)。正解がすべて1になる可能性もあることを考えれば、もし1ばかり付けた場合が0点になれば、子どもは同じ選択肢はずっと続かないと考えます。問題数が少なければなおさらです。センター試験のように問題数があればまた話は別かもしれませんが。なんにせよ子どもに余計なことを考えさせるべきではないです。宝くじではなくテストなのですから、選択肢を選ぶことではなく、テスト内容に集中させるべきですね。選択肢を選ばせるテストは、極論を言えば運が良いと100点を取れます。そのデメリットも考えた上で選択肢を選ばせるようにしているのであれば、数字が同じだからといって0点にするのは良くないと思います。どうしてもそれが嫌なら選択肢から選ばせる問題ではないようにする、あるいは、選択肢と一緒に数字を表示せずに(例えば、1.on 2.in)、語群だけを表示(例えばon,in, at, underの4つの選択肢を四角で囲っておくなどして表示)するようにすべきではないかと思います。しかし電子媒体だとなかなか難しいかもしれませんね。VBAに詳しいわけではないのでここで止めておきます。
以上が私の考えです。ここで述べても仕方ないことですが、一応その方々が私ではないことと否定しなければなりませんので、申し上げておきます。
ちなみに私の作っている教材というのは、あくまでも練習用(定着を少しでも促すためのもの)の目的で、点数をつけたり成績をつけたりするようなことは考えて作っていません。塾等なら話は変わるかもしれませんが、もし私の作っている教材の得点次第で、子どもに点数をつけて成績に入れるようなことは望ましくありません。
今の学校教育の現場は、評価の真正性を大切にしなければならないはずです。授業内容と評価、あるいはテスト内容と評価が一体となっていなければ、つけられた成績に意味が無いからです。近年は特に文部科学省がこのことを大切にしているはずです。
最後になりましたが、HNアイスの方ですが、今PCが手元に無い場所で携帯電話で投稿しているので、また後ほどPCを手元に更新します。コードを確認してからでないと投稿できませんので。
それでは失礼致します。こちらの掲示板で返すべきことには返したつもりですが、何かご不明な点などがございましたらまたご連絡頂ければと思います。無ければ無いで大丈夫です。
(OREO) 2018/12/30(日) 21:10
別名を名乗ることの問題点は何かありますか?特に問題が無いと判断したので別名を利用したまでです。むしろ別名の方が便利だと思いましたので別名で利用しました。別にいろんな人を装って誹謗中傷を行なっているわけでもありませんからね。名前を変えられるのであれば必要に応じて利用するのは問題無いと思いますが。
逆に、HN使い分けるとどのようなメリットがあるんですか?
そりゃ内容にもよるでしょうけど、同じ説明をする必要がある内容だったら、別人だと思って一生懸命答えたところで、「いや、別HNのほうでさっき聞きましたから」みたいな反応されると悲しくなりますけど。
また、今回のように後から指摘されてわかった場合、あんまり心象はよくないようにおもうので、それが原因で回答者からそっぽ向かれたら困るのはご自身なのでは?
なので私には、別人を装う(というか使い分け?をする)メリット?がよくわかりませんが、どうしてもというのであれば、別名義で投稿している旨書いておくべきでしょうね。
マルチポストも然り。好かれる行為ではないですから、もしマルチポストをしているのであればちゃんと表明しておくほうがよいでしょう。
もちろん、いずれも規約上禁止になっていませんので自由にすればよいでしょうけど、こんなこといちいち言われるのも嫌でしょうから、はじめから書いておいたほうがよいのです。
そうすれば、気に入らないと思う人はコメントしないだけですから。
このほか、重複しますし余計なお世話でしょうけど、このサイトを使い続けるのであれば、今後投稿される場合はどちらかを使うようにしたほうがよいですよ。
過去ログをみてどこまでは理解されているのかな〜なんて確認してから回答をつけることもありますから、質問の度にニックネーム変えられちゃうとイチから説明しなおし(されなおし)になります。
また、マルチポストされているのであればですけど、それぞれのサイトに別サイトでついた回答を責任もってフィードバックしたほうがよいでしょう。
特に、このサイトはずっと保存されますから、同じ悩みをもってこのトピックにたどり着いた方へのヒントになるはずです。
(なので、URL貼り付けて終了。とされると将来リンク切れになる可能性があるのでよろしくないです。)
(もこな2) 2018/12/30(日) 22:58
「oshiete様」は、「CaveatEmptor」さんと言う人です。
OREOさんとは別人との由、大変失礼いたしました。 m(__)m
・・であれば、ここで「出鱈目」について議論する意味はありません。
>別名を名乗ることの問題点は何かありますか?
意見が分かれるところです。私としては問題無いと思っています。 ※ ただし、同一トピック内では、変えてはならない。
私自身も、トピック内容に合わせて適宜HNを変えたいと思っているんですけどねぇ・・ 残念ながら「空気」を読むとそれは出来ないです。
あと、掲示板によっては、変えないようにハッキリ要請しているところもあります。 この板は、さほど明瞭ではないと思っています。
(半平太) 2018/12/30(日) 23:07
半平太様、大丈夫です。私の行為が元となってしまったことですから。このような誤解を与えるデメリットもありますね。気をつけます。
今後とも何かありましたらよろしくお願い致します。
別の掲示板の方は名前を変えられないので(もちろん登録し直せば別かもしれませんが)、これからはOREOで基本的には投稿しようと思います。
ただし、今この掲示板にてアイス名義で立ち上げたスレッドについてはアイスのまま進めさせていただきます。
(OREO) 2018/12/30(日) 23:31
先程私がCaveatEmptor様(私がosiete様と呼んでいた方)の投稿内容は熟読したわけではなく、半平太様のコメントを主に見て、あくまでも私の考えを述べただけです。私は大学の先生のような教育学のスペシャリストではございませんので、全てが合っているとまでは申し上げられせん。
得点を0にするかどうかも時と場合次第だと思います。0にするメリットが薄い場合しか私には思いつきませんが…。
以上追記でした。
(OREO) 2018/12/30(日) 23:36
校長先生の意見
私もユーザー登録したくはないのですが、 反対意見が多いですね。 同一人が複数ニックネームを使用したり偽物が登場したりするのをなんとかしたいのですが。 (BJ) 2018/12/31(月) 01:17
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.