ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Excel(エクセル)活用コミュのVBA 構文をもっとシンプルにしたい。

  • mixiチェック
  • このエントリーをはてなブックマークに追加
お世話になります。
ユーザーフォームに選択項目用にOptionButtonを59個用意しています。
それぞれ2個〜4個のグループに分ける為フレーム内に配置しました。

で、グループごとにどのボタンが押されたかを判別する為にシートに数字を入力しています。
OptionButtonがありすぎてForの構文がシンプルにならないのでなんとかシンプルに治めたいと思うのですが、どなたかいい方法ありませんでしょうか?
それぞれ判別グループにおいて1〜4の数字を入力し、シートのセルは右に向かって一つづつグループごとの値が入力されます。
※例)OptionButton1〜3の場合
OptionButton1がチェックされていればintRow行のの99列目に1を入力。同様にOptionButton2であれば2を入力
※例)OptionButton4〜5の場合
OptionButton4がチェックの場合intRow行の100列目に1を入力。。。といった具合です。


構文-------------------------------------
Dim myRoom As Integer, intRow As Integer, Ob As Integer
Worksheets("データ一覧").Activate
myRoom = ComboBox3 '部屋番号検索
Worksheets("データ一覧").Columns("A:A").Find(What:=myRoom, LookIn:=xlFormulas, LookAt:=xlWhole).Activate
intRow = ActiveCell.Row

For Ob = 1 To 3
If Controls("OptionButton" & Ob).Value = True Then '生年月日年号判別
Cells(intRow, 99).Value = Ob
End If
Next Ob

For Ob = 4 To 5
If Controls("OptionButton" & Ob).Value = True Then '性別判別
Cells(intRow, 100).Value = Ob - 3
End If
Next Ob

For Ob = 6 To 10
If Controls("OptionButton" & Ob).Value = True Then '介護度判別
Cells(intRow, 101).Value = Ob - 5
End If
Next Ob

For Ob = 11 To 14
If Controls("OptionButton" & Ob).Value = True Then '医療保険判別
Cells(intRow, 102).Value = Ob - 10
End If
Next Ob

For Ob = 15 To 18
If Controls("OptionButton" & Ob).Value = True Then '食事判別
Cells(intRow, 103).Value = Ob - 14
End If
Next Ob

For Ob = 19 To 22
If Controls("OptionButton" & Ob).Value = True Then '移動判別
Cells(intRow, 104).Value = Ob - 18
End If
Next Ob

For Ob = 23 To 25
If Controls("OptionButton" & Ob).Value = True Then '排泄判別
Cells(intRow, 105).Value = Ob - 22
End If
Next Ob

For Ob = 26 To 28
If Controls("OptionButton" & Ob).Value = True Then '更衣判別
Cells(intRow, 106).Value = Ob - 25
End If
Next Ob

For Ob = 29 To 30
If Controls("OptionButton" & Ob).Value = True Then '麻痺判別
Cells(intRow, 107).Value = Ob - 28
End If
Next Ob

For Ob = 31 To 32
If Controls("OptionButton" & Ob).Value = True Then '義歯判別
Cells(intRow, 108).Value = Ob - 30
End If
Next Ob

For Ob = 33 To 35
If Controls("OptionButton" & Ob).Value = True Then '視力判別
Cells(intRow, 109).Value = Ob - 32
End If
Next Ob

For Ob = 36 To 37
If Controls("OptionButton" & Ob).Value = True Then '聴力判別
Cells(intRow, 110).Value = Ob - 35
End If
Next Ob

For Ob = 38 To 39
If Controls("OptionButton" & Ob).Value = True Then '妄想判別
Cells(intRow, 111).Value = Ob - 37
End If
Next Ob

For Ob = 40 To 41
If Controls("OptionButton" & Ob).Value = True Then '健忘判別
Cells(intRow, 112).Value = Ob - 39
End If
Next Ob

For Ob = 42 To 43
If Controls("OptionButton" & Ob).Value = True Then '見当識判別
Cells(intRow, 113).Value = Ob - 41
End If
Next Ob

For Ob = 44 To 45
If Controls("OptionButton" & Ob).Value = True Then '理解力判別
Cells(intRow, 114).Value = Ob - 43
End If
Next Ob

For Ob = 46 To 47
If Controls("OptionButton" & Ob).Value = True Then '入浴判別
Cells(intRow, 115).Value = Ob - 45
End If
Next Ob

For Ob = 48 To 49
If Controls("OptionButton" & Ob).Value = True Then '徘徊判別
Cells(intRow, 116).Value = Ob - 47
End If
Next Ob

For Ob = 50 To 51
If Controls("OptionButton" & Ob).Value = True Then '睡眠判別
Cells(intRow, 117).Value = Ob - 49
End If
Next Ob

For Ob = 52 To 53
If Controls("OptionButton" & Ob).Value = True Then '言語障害判別
Cells(intRow, 118).Value = Ob - 51
End If
Next Ob

For Ob = 54 To 55
If Controls("OptionButton" & Ob).Value = True Then '不潔行為判別
Cells(intRow, 119).Value = Ob - 53
End If
Next Ob

For Ob = 56 To 57
If Controls("OptionButton" & Ob).Value = True Then '意思疎通判別
Cells(intRow, 120).Value = Ob - 55
End If
Next Ob

For Ob = 58 To 59
If Controls("OptionButton" & Ob).Value = True Then '認知症判別
Cells(intRow, 121).Value = Ob - 57
End If
Next Ob
----------------------------------------
因みに変数(Ob)を使いまわすのはよくないと調べたら出てきたんですが数が多いので変数を使いまわしています。これもいい方法がないものかと思案中です。

Win7 エクセル2010です。
よろしくお願いします。

コメント(15)

For Ob = 開始 To 終了
ということで考えると、
Cells(intRow, 列の位置).Value = Ob - (開始 -1)
という規則性が見えてきますね。

「開始」と「終了」と「列の位置」を引数で渡して
処理をしてくれるプロシージャを作るとコードがすっきりしそうですね^^

ちなみに、変数の使いまわしがいけないとは思いません。
同じ変数を毎回違う意味で使用するのはコードの可読性が落ちます。
ですが、今回は毎回ループのカウンタとして使用されているので
そういった意味で問題があるようには思えないですがいかがでしょうか。
僕ならFor Each ... Nextを使ってオブジェクトを総当たりし、その中からオプションボタンについてだけ処理をするようにします。
処理はオプションボタンの番号についてSelect Caseで条件分けして処理させます。
ああ、よっちゃんさんの方がすっきりしますね。
>>よっちゃんさん
ありがとうございます。そうなんです。規則性がありそうなんでシンプルにできると思うんですが、どうにも自分の頭では上手くできないんですよね。。。

自分でももう少し考えてみます。
> 自分でももう少し考えてみます。

そうですね。
Danielさんが後から見てわかり易いようなコードであったり、
気分的にも納得のいくような形が見つかるとよいですね。

ちなみに私が上で書いたことですが、ミスがあったようです。

よく見ると
= Ob - (開始 -1)
ではなく、「そのグループの中で何個目のオプションボタン」のようですね^^

ということは、プロシージャわけするならこんな感じかな?

For Ob = 1 To (終了 - 開始 + 1) Step 1
  If Controls("OptionButton" & (開始 - Ob + 1).Value Then
    Cells(intRow, 列の位置).Value = Ob
    Exit For
  End If
Next Ob

おっと、intRowも引数で渡してあげる必要がありそうですねぇ。
>>Yujinさん
なるほど。そういうアプローチもありですね。

>>よっちゃんさん
なんかすごくシンプルになってるじゃないですか!!!!
あとは引数の渡し方だけですね。。。←問題はそこなんですけどね(笑)

終了は59(固定)としても、開始の引数、列の位置が。。。。wwwww
列の位置はグループで1づつ増えるわけだから(開始+98)ってことかな?
intRowは構文の前後で取得してるので大丈夫です!

引数を考えすぎて頭が混乱してきました。。。。

開始と終了、列の位置の引数がどうしても割り出せない。。。。
Please HELP ME。。。。。
うーん、開始・終了の数字に規則性がないので、配列等を使うしかないのかなと思いましたが、どうでしょう?

列の位置については、グループごとにセルに入力されたら右へ1ずらすようにすれば良いのでは?
>>Yujinさん
配列ですか。すいません具体的には配列ってどういったことをさすのでしょう?
>>11
多分、こんな感じ?に配列に規則性の無いパラメータを放り込んでやれば、
すっきり書けますよ、という提案だと思います。あくまで一例ですが。


Dim nChoices(23) As Integer '各オプショングループの選択肢数配列
Dim nGroupNo As Integer '項目グループNo.
Dim nIndex As Integer 'コントロールのインデックス番号

nChoices(1) = 3 '生年月日年号判別
nChoices(2) = 2 '性別判別
nChoices(3) = 5 '介護度判別
nChoices(4) = 4 '医療保険判別
nChoices(5) = 4 '食事判別
nChoices(6) = 4 '移動判別
nChoices(7) = 3 '排泄判別
nChoices(8) = 3 '更衣判別
nChoices(9) = 2 '麻痺判別
nChoices(10) = 2 '義歯判別
nChoices(11) = 3 '視力判別
nChoices(12) = 2 '聴力判別
nChoices(13) = 2 '妄想判別
nChoices(14) = 2 '健忘判別
nChoices(15) = 2 '見当識判別
nChoices(16) = 2 '理解力判別
nChoices(17) = 2 '入浴判別
nChoices(18) = 2 '徘徊判別
nChoices(19) = 2 '睡眠判別
nChoices(20) = 2 '言語障害判別
nChoices(21) = 2 '不潔行為判別
nChoices(22) = 2 '意思疎通判別
nChoices(23) = 2 '認知症判別

nIndex = 1
For nGroupNo = 1 To UBound(nChoices)
For Ob = 1 To nChoices(i)
If Controls("OptionButton" & nIndex).Value = True Then
Cells(intRow, 98 + nGroupNo).Value = Ob
End If
nIndex = nIndex + 1
Next Ob
Next nGroupNo
Danielさんへ

> intRowは構文の前後で取得してるので大丈夫です!

書かれたコードでは変数のスコープがプロシージャレベルになっています。
他のプロシージャからは参照することができない。
なので、変数のスコープを変えるか渡してあげるかしないといけないです。


> Please HELP ME。。。。。

これでいかがでしょう。
 ↓
Sub 処理(ByVal 開始 As Long, ByVal 終了 As Long _
    , ByVal 行の位置 As Long, ByVal 列の位置 As Long _
    )

  Dim Ob As Long

  For Ob = 1 To (終了 - 開始 + 1) Step 1
    If Controls("OptionButton" & (開始 + Ob - 1)).Value Then
      Cells(行の位置, 列の位置).Value = Ob
      Exit For  'これだけの処理ならExit Subでも・・・。
    End If
  Next Ob
End Sub


>>7で「こんな感じかな?」と書いたコードは特に検証していなかったのですが
よくよく見ると構文エラーなとありました(スミマセン)ので微修正してあります。
変数は全て Long 型で受けています。


で、使い方はこう。
 ↓
Sub 使い方サンプル()
  '前略 (変数Obがここで不要なら定義は削除しておいたほうが・・)

  Call 処理(1, 3, intRow, 99)  '生年月日年号判別
  Call 処理(4, 5, intRow, 100)  '性別判別
  Call 処理(6, 10, intRow, 101) '介護度判別

  '後略
End Sub


変数名やプロシージャ名などは説明しやすいように日本語で書いています。
気にいらなければDanielさんの好みで変えてくださいね^^

ご参考までに。
Minonさんの仰る通りです。
僕ならそうするかなと。
>>Minonさん
ありがとうございます。なるほど、配列とはそういった処理のことなんですね。
この方法でも僕の記述よりはかなりすっきり見えますね。

>>よっちゃんさん
なるほどそういうことでしたか。面目ないです。
コードありがとうございます。
Callでプロシージャを呼び出す方法もすっきりしますね。

ほんとうにこのコミュにはいつもお世話になってばかりです。。。
皆様には頭が下がるばかりです。
明日、コードの記述をおこなって色々試してみたいと思います。

ありがとうございました。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Excel(エクセル)活用 更新情報

Excel(エクセル)活用のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。