見守り電球またはGPS端末が特価中!

はじめまして。
ExcelのVBでタイピングゲームもどきを作っているのですが、
どうしてもうまくできません。
いろいろ調べたのですが、解決できませんでした。
まだ途中なのですがこれができないと先に勧めません。
Sheet2からランダムに文章を選び表示し、
入力した文字が正しければ文字を下のテキストボックスに
落していくみたいな感じに作ろうとしています。
解決方法、直したほうがいいとこがりましたら回答のほう
お願いします。
まるまるプログラムを変えたほうがいいような感じのときは
どのようなプログラムにしたらいいのかお願いします。


Private Sub CommandButton1_Click()
Dim n As Long
Dim k As Long
Dim L As Variant
Dim X As Long
Dim O As Variant
Dim WrkRow As Long
Dim WrkCol As Long
Dim WrkRange As Variant
With Sheets("Sheet2")
WrkRow = .Cells(Rows.Count, 1).End(xlUp).Row
WrkCol = .Cells(1, Columns.Count).End(xlToLeft).Column
WrkRange = .Range("A1").Resize(WrkRow, WrkCol)
End With
L = ""
TextBox1 = ""
Randomize
n = Int(Rnd() * 10)
k = n + 1
TextBox1 = WrkRange(k, 1)
TextBox2 = WrkRange(k, 2)
O = k
L = WrkRange(k, 2)
X = 0
End Sub
Private Sub CommandButton1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal shift As Integer)
If X > 6 Then Exit Sub
KC = KeyCode
If Chr(KC) = X Then
X = X + 1
TextBox2 = Right(L, 7 - X)
TextBox3 = Left(L, X)
End If
End Sub

このQ&Aに関連する最新のQ&A

A 回答 (6件)

#1です。


繰り返したいロジック(L = ""~X = 0)をサブプロシージャ(sGetWord)にして
CommandButton1_KeyDownの終了判定後sGetWordをコールすればループできます。
そのときWrkRangeをパブリック変数にするのを忘れないように。
---
Private Sub CommandButton1_Click()
(略)
Call sGetWord
End Sub


If LCase(Chr(KC)) = C Then
X = X + 1
TextBox2 = Right(L, B - X)’←文字数BからXを引いたLを表示
TextBox3 = Left(L, X)’←LのX番目の文字を表示
If X >= B Then
rtn = MsgBox("もう一度実行しますか。", vbYesNo)
If rtn = vbNo Then Exit Sub
Call sGetWord
Exit Sub
End If
End If
    • good
    • 0
この回答へのお礼

遅れてすみません。
回答ありがとうございます。

無事完成することができました。
これまでアドバイスや指摘などありがとうございました。

お礼日時:2009/01/23 20:39

#2です。


ウォッチで動作確認をしてみてください。
"c"を押下したときKCの値は"67"でChr(KC)とすると"C"に変換されます。
なので
If LCase(Chr(KC)) = C Then
もしくは
If Chr(KC) = UCase(C) Then
とすればTrueで判定されます。
ただし、大文字小文字を区別したければ細工が必要です。
mt2008さんの指摘も参考に。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
If Chr(KC) = X Then

If LCase(Chr(KC)) = C Then
に変えたら無事、求めていた状態になりました。
ありがとうございます。

最後に、1単語タイプし終えた後L = ""までループで戻すには、どうしたらいいのでしょうか?
時間があったら回答お願いします。

お礼日時:2009/01/21 20:57

No1です。


> 実行すると
> If Chr(KC) = Mid(L, X + 1, 1) Then
> の部分がエラーになってしまいます。

そうですか……どんなエラーでした?
「どんなエラー」だったかと言う情報が重要です。


> 一応私なりに思考したコードを貼ります。
> 指摘お願いします。

1.プロシジャー内の変数宣言にPrivateが使用されています。
修正前---
Private n As Long
Private k As Long

修正後---
Dim n As Long
Dim k As Long


2.文字数に達した時に抜けられません
修正前---
If X > B Then Exit Sub’←この場合、5文字より多くなったら終われ

修正後---
If X >= B Then Exit Sub’←この場合、5文字より多くなったら終われ

これで動くと思いますがいかがですか?
あと、変数宣言でVariant型は便利ですが、使いすぎると何の為の変数か判らなくなり、ミスの元になります、可能な限りちゃんとデータ型を指定するクセをつけた方が良いですよ。
    • good
    • 0
この回答へのお礼

回答、指摘ありがとうございます。
エラー13だったと思います。
エラーって重要なんですね。
指摘&No5の回答をもとに修正したら無事、求めていた状態になりました。
ありがとうございます。
また、これからはVariantをあまり使わないようにしようと思います。
本当にありがとうございました。

お礼日時:2009/01/21 20:52

No.1です。


ちょっと間が空いてしまいましたのでもう解決されたかもしれませんが、念のために回答しておきます。
提示されたソースには大きな問題が2つあります。

1.変数の適用範囲の問題
Sub CommandButton1_Click で宣言した変数「L」「X」を、Sub CommandButton1_KeyDown でも使おうとしています。
Sub CommandButton1_Clickで宣言した変数は、そのSub内でしか使用できません。
Sub CommandButton1_KeyDownで使用している変数「L」「X」は、Sub CommandButton1_Click で宣言した変数とはまったく別な物です。

変数「L」「X」を、このモジュール内のプロシジャーで共有するばあい、プロシジャーの前で宣言します。

VBAは、デフォルトでは変数宣言をしなくても変数をいきなり使えるので、この様なミスが起こりがちです。モジュールの先頭に Option Explicit を入れて、変数は宣言しないと使用できないようにした方がミスは起こりにくくなりますのでお勧めです。


修正前---
Private Sub CommandButton1_Click()
Dim n As Long
Dim k As Long
Dim L As Variant
Dim X As Long
Dim O As Variant



修正後---
Option Explicit'←変数宣言強制
Private L As Variant'←変数Lはモジュール内で共有
Private X As Long'←変数Xはモジュール内で共有

Private Sub CommandButton1_Click()
Dim n As Long
Dim k As Long
'←プロシジャー内でのL、Xの宣言は削る
Dim O As Variant



2.比較対象の問題
変数Xは、入力する文字列の位置だと思いますが、Sub CommandButton1_KeyDown 内では、その位置と、キー押下した文字を比較しています。
比較するのは、その位置にある文字とキー押下した文字だと思われます。

修正前---
If Chr(KC) = X Then

修正後---
If Chr(KC) = Mid(L, X + 1, 1) Then

それと、Sub CommandButton1_KeyDown 内で、変数「KC」の宣言をするのもお忘れなく。
    • good
    • 0
この回答へのお礼

遅れました。2度目の回答ありがとうございます。

問題は解決していません。
No.2の回答とも見比べながらやったのですがどうもうまくいきません。
実行すると
If Chr(KC) = Mid(L, X + 1, 1) Then
の部分がエラーになってしまいます。
一応私なりに思考したコードを貼ります。
指摘お願いします。

Option Explicit
Private L As Variant'←共有
Private X As Long’←共有

Private Sub CommandButton1_Click()
Private n As Long
Private k As Long
Dim WrkRow As Long
Dim WrkCol As Long
Dim WrkRange As Variant
With Sheets("Sheet2")
WrkRow = .Cells(Rows.Count, 1).End(xlUp).Row
WrkCol = .Cells(1, Columns.Count).End(xlToLeft).Column
WrkRange = .Range("A1").Resize(WrkRow, WrkCol)
End With
L = ""
TextBox1 = ""
Randomize
n = Int(Rnd() * 10)
k = n + 1
TextBox1 = WrkRange(k, 1)’←例)ココア
TextBox2 = WrkRange(k, 2)’←例)cocoa
L = WrkRange(k, 2)’←例)cocoa
X = 0
End Sub

Private Sub CommandButton1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger,
_
ByVal shift As Integer)
Dim KC As Variant
Dim B As Variant’←文字数
Dim C As Variant’←キーの位置(?
B = Len(L)’←例)cocoaより、B=5文字
If X > B Then Exit Sub’←この場合、5文字より多くなったら終われ
C = Mid(L, X + 1, 1)’←何文字目か(?
KC = KeyCode
If Chr(KC) = C Then
X = X + 1
TextBox2 = Right(L, B - X)’←文字数BからXを引いたLを表示
TextBox3 = Left(L, X)’←LのX番目の文字を表示
End If
End Sub

お礼日時:2009/01/20 00:38

>私が聞きたいこと


の最初の方はリンク先で説明されていましたが。。。
プロシージャレベルではそのプロシージャを抜けた時点で変数の値は保存されず、メモリも解放されると記述されています。
でどうするかは、モジュールレベル変数もしくはパブリック変数に変えればよいということです。
どちらがよいかは設計者ではないので判断できかねます。
下記のリンク先も参考にして判断してください。
次ですが、文字数はLen関数を使用すれば取得できるので必要はないかと思います。
---
If X > Len(L) Then Exit Sub

If Chr(KC) = Left(L,1) Then
X = X + 1
TextBox2 = Right(L, Len(L) - X)
TextBox3 = Left(L, X)

参考URL:http://pc.nikkeibp.co.jp/article/NPC/20070803/27 …
    • good
    • 0
この回答へのお礼

遅れてすみません。
回答ありがとうございます。

やっぱりキーを押しても無反応のままです。
Lenを使ってみました。
Lenを使うとTextBox2とTextBox3に文字数が表示されるような形になりました。
さらに、キーを押すとエラーになってしまいます。

この回答でLenを使うことで文字数を取得できるということを知りました。ありがとうございます。
ですが、問題が解決できなかったので残念です。

お礼日時:2009/01/20 00:24

もっと具体的に、何がどううまく行かないのかの説明が無いと誰も答えられないと思います。


さっとコードを眺めただけですが、変数の適用範囲について理解が不足しているように思えました。まずは、リンク先の説明をよく読む事をお勧めします。

参考URL:http://support.microsoft.com/kb/141693/ja
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
参考URL読みました。
LやXの値がリセットされているということなのでしょうか?
理解力がなくすみません。
私が聞きたいことは、
・この途中までのコードを実行したときにキーを押しても反映されず、
どうしたら反映されるか。
・Lにローマ字の単語と字数を入れる方法。(検索ワードがわからないので)
 例:L= Ball (4字) 
 みたいな感じで記憶する方法。
です。
説明不足ですみません。
回答の方よろしくお願いします。

お礼日時:2009/01/16 22:06

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


人気Q&Aランキング