• ベストアンサー

エクセルVBA/フォームのオプションボタンを元に戻す

ワークシート上に、フォームのオプションボタンが7個貼ってあります。 名前はOP1~OP7とします。 ある一定の条件に合致した場合、押されたオプションボタンがxlonになるのをキャンセルし、前にオンになっていたオプションを再度xlonにしたいのですが、Appication.Undoではエラーになってしまいました。 どうやったら前の状態に戻せるのでしょうか?

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

  • ベストアンサー
  • taocat
  • ベストアンサー率61% (191/310)
回答No.14

こんにちは。 Application.Callerとは何とお洒落な。。(^o^) ------------------------------------------------------------------ Public myOpValues(7) As Integer 'これmyOpValues(7) ってどういう意味ですか? ●ひとつ前の7個のオプションボタンの状態を保持するための配列 ------------------------------------------------------------------- If n <> OpNo And myOpValues(n) = 1 Then 'このmyOpValues(N) はなんですか? ●配列myOpValues()にはひとつ前のオプションボタンの状態が入っているので元に戻すためにそこをチェックしています ---------------------------------------------------------------     ActiveSheet.OptionButtons(n).Value = 1 ●そしてここで元の状態に戻しています ----------------------------------------------------------------    myOpValues(N) = 0 'このmyOpValues(N)=0 はどんな意味ですか? ●現在のオプションボタンの状態を配列に再設定する為に先ず、Offにしているだけです。 ------------------------------------------------------------    If N = OpNo Then myOpValues(N) = 1 ●そしてここでいまクリックされたオプションボタンの状態"On"を配列に保持 ----------------------------------------------------------- ということになりますがある別の場合も考えていたのでちょと分かり難いコードになりました。 そこで単純に補足のようなことでよければ以下のようにシンプルにすることもできますね。 ========================================================= Sub OpCheck(OpNo)  Dim N As Integer  If ActiveSheet.CheckBoxes("CCK" & OpNo).Value <> 1 Then    MsgBox "そこは選べないわよ。", vbCritical, "Sorry!!"     For N = 1 To 7       ActiveSheet.OptionButtons(N).Value = myOpValues(N)     Next N  End If  For N = 1 To 7    myOpValues(N) = ActiveSheet.OptionButtons(N).Value  Next N End Sub ============================================================ それから、こんな時はどうするのでしょう。 例えば、CCK3にチェック、OP3がONの状態の時、CCK3のチェックを外した場合、OP3はONのまま?それともOFFにする? 以上です。  

merlionXX
質問者

お礼

ご丁寧にありがとうございました。 > CCK3にチェック、OP3がONの状態の時、CCK3のチェックを外した場合、OP3はONのまま?それともOFFにする? これは下記のコードで対処済みなんです。 Sub CCK_Click() Dim x As Integer x = Right(Application.Caller, 1) With ActiveSheet If .CheckBoxes("CCK" & x).Value = 1 Then Exit Sub If .OptionButtons("Opt" & x).Value = xlOn Then MsgBox "これははずしちゃだめ!", vbCritical, "Sorry!!" .CheckBoxes("CCK" & x).Value = 1 End If End With End Sub

merlionXX
質問者

補足

すみません、あとひとついいですか? ActiveSheet.OptionButtons(n) ですが、現在はOption Button 1~7に、それぞれOpt1~Opt7の名前を付けていますので問題ないと思いますが、これが仮にOption Button 1~7という規則的ならびではなかったものをOpt1~Opt7の名前をつけていたとしたらやはり使えないんでしょうねぇ?

その他の回答 (14)

  • taocat
  • ベストアンサー率61% (191/310)
回答No.15

こんばんは。 CCK3にチェック、OP3がONの状態のとき云々は、杞憂でしたね。(^^; >Option Button 1~7という規則的ならびではなかったものをOpt1~Opt7の名前をつけていたとしたらやはり使えないんでしょうねぇ? やりかた次第で可能だと思いますよ。 何れにしても、も少し具体的な例(なるべく実態に近い例)を挙げて貰えれば答えやすいのですが。。。 以上です。  

merlionXX
質問者

お礼

> も少し具体的な例(なるべく実態に近い例)を挙げて貰えれば答えやすいのですが。。。 わかりました。 まとめまして新しい質問として再度投稿します。 ありがとうございました。

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

こんにちは。 >それはわたしも考えましたが、オプションボタンを押して初めてマクロが走るんですから、押したあとでEnabled=Falseでは意味がないんです。 読んでいても、おやりになりたいことが、良く理解できないのですが、押した後でダメなら、C1の.Enabled=False の条件だけにすればよいと思いますね。  If Range("C1").Value = True And t = 3 Then         ↓  If Range("C1").Value = True Then でも、#11 の「回答に対するお礼」の例では、 C1 に 3 を入れて、以下のようにすればよいのではありませんか? 'これ以外は、#12 と他は全て同じです。 Sub OPValueStock()   Dim t As Integer   'オプションボタンの値を確保   With ActiveSheet   t = .Shapes(Application.Caller).DrawingObject.Index   If Range("C1").Value = t Then    MsgBox "それは選べません。", 16    Me.OptionButtons(t).Value = 0     j = i     Call OPRecover   End If     j = i     i = t   End With End Sub

merlionXX
質問者

お礼

ありがとうございました。 これからもご指導くださいますようお願いいたします。

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

こんばんは。 Wendy02の#8 発言、間違いでした。#2の「回答に対するお礼」の読み違えです。taocat さんの書き込みで、その流れを気づきました。 >どのオプションボタンを押したかで、条件が整うのです。仮にC1セルの値が「TRUE」の時に3番目のオプションボタンを押されたら「キャンセル」させるといった具合です これは、単に、C1 が、True だったら、OptionButtons(3).Enable =False っていうことではありませんか? キャンセルというよりも、選べなくすればよいと思います。 具体的には、このようになります。   t = .Shapes(Application.Caller).DrawingObject.Index   If Range("C1").Value = True And t = 3 Then    Me.OptionButtons(3).Enabled = False   Else    Me.OptionButtons(3).Enabled = True   End If とすればよいのでは? それから、これは、難しく考えないで、ものすごくシンプルに考えればよいのではありませんか? 'シートモジュール Private i As Integer Private j As Integer Sub OPValueStock()   Dim t As Integer   'オプションボタンの値を確保   With ActiveSheet   t = .Shapes(Application.Caller).DrawingObject.Index   If Range("C1").Value = True And t = 3 Then    Me.OptionButtons(3).Enabled = False   Else    Me.OptionButtons(3).Enabled = True   End If     j = i     i = t   End With End Sub Private Sub OPRecover()   'オプションボタンの値を戻す(UnDo)    On Error Resume Next    Me.OptionButtons(j).Value = 1 End Sub '======================================= '設定用マクロ'(一回だけでよい) Sub SettingMacro() 'オプションボタンの設定 Dim o As Variant For Each o In ActiveSheet.OptionButtons   o.OnAction = Me.Name & ".OPValueStock" Next o End Sub

merlionXX
質問者

お礼

何度も何度もお手間かけ、申し訳ありません。 >キャンセルというよりも、選べなくすればよいと思います。 それはわたしも考えましたが、オプションボタンを押して初めてマクロが走るんですから、押したあとでEnabled=Falseでは意味がないんです。 今回は11番のtaocatさんのやり方に、Application.Callerを組み合わせて何とかできました。ほとんどわかってないんですが・・・・。 これからもいろいろご教示いただければ幸いです。 ありがとうございました。

  • taocat
  • ベストアンサー率61% (191/310)
回答No.11

こんばんは。 merlionXXさん、ほんとに色んなことされてますねぇ。(^^; 要するにセルC1に値がある時は、OptionButton3を選択できないようにする、ということですね? (全て標準モジュール) -------------------------------------------- Public myOpValues(7) As Integer ----------------------------------- Sub オプション1_Click()   Call OpCheck(1) End Sub ----------------------------------- Sub オプション2_Click()   Call OpCheck(2) End Sub ----------------------------------- Sub オプション3_Click()   Call OpCheck(3) End Sub ----------------------------------- Sub オプション4_Click()   Call OpCheck(4) End Sub ----------------------------------- Sub オプション5_Click()   Call OpCheck(5) End Sub ----------------------------------- Sub オプション6_Click()   Call OpCheck(6) End Sub ----------------------------------- Sub オプション7_Click()   Call OpCheck(7) End Sub ------------------------------------------ Sub OpCheck(OpNo)  Dim N As Integer  Dim Q As Integer  If OpNo = 3 And Range("C1").Value <>"" Then    For N = 1 To 7      If N <> 3 And myOpValues(N) = 1 Then         ActiveSheet.OptionButtons(N).Value = 1         Exit Sub      End If    Next N  End If  For N = 1 To 7    myOpValues(N) = 0    If N = OpNo Then myOpValues(N) = 1  Next N End Sub -------------------------------------------- なお、分かり易くするためにOptionButtonの数は質問の7に固定し、名前もデフォルトにしてあります。 実際にはwendy02さんのようにcount,redimなど使用すべきですね。 勘違いしてましたら平にご容赦願います。(^^;;; 以上です。  

merlionXX
質問者

お礼

taocatさん、お世話になります。 実はちょっとやり方を変え、やはりフォームでチェックボックスを7個つくり(CCK1~CCK7)、このチェックボックスの番号に対応するオプションボタン(OP1~OP7でひとつのグループ)があるんです。 で、チェックボックスがチェックされてない番号のオプションボタンが押されたときに無効にしたいのです。(CCK1がチェックされてないのにOP1は押せない) 試行錯誤の結果、ぜんぜん意味がわからないんですが下記のコードでなんとかできるようになりました!でも、ぜんぜんわからないので教えてください。 Public myOpValues(7) As Integer 'これmyOpValues(7) ってどういう意味ですか? Sub Opt_Click() ’これを各オプションボタンにセットしました。 Dim x As Integer x = Right(Application.Caller, 1) ’これでどのオプションボタンが押されたかわかります。 Call OpCheck(x) End Sub Sub OpCheck(OpNo) Dim N As Integer Dim Q As Integer If ActiveSheet.CheckBoxes("CCK" & OpNo).Value <> 1 Then MsgBox "そこは選べないわよ。", vbCritical, "Sorry!!" For N = 1 To 7 If N <> OpNo And myOpValues(N) = 1 Then 'このmyOpValues(N) はなんですか? ActiveSheet.OptionButtons(N).Value = 1 Exit Sub End If Next N End If For N = 1 To 7 myOpValues(N) = 0 'このmyOpValues(N)=0 はどんな意味ですか? If N = OpNo Then myOpValues(N) = 1 Next N End Sub

noname#22222
noname#22222
回答No.10

s_husky です。 ルーチンとコードの記述内容は同じです。

merlionXX
質問者

お礼

ありがとうございます。 ちょっとわたしには手におえませんでした。ごめんなさい

  • bonaron
  • ベストアンサー率64% (482/745)
回答No.9

#7です。 >Private Sub SetOption(Idx As Integer, sw As Boolean) >Sheet2.Shapes("Opt" & Idx).ControlFormat.Value = sw >Private Sub SetOption(Idx As Integer, sw As Boolean) ActiveSheet.Shapes("Opt" & Idx).ControlFormat.Value = sw にしてください。ゴメン

merlionXX
質問者

お礼

ありがとうございます。 ちょっとわたしには手におえませんでした。ごめんなさい。

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

こんばんは。 >でも、考えたんですが、各オプションボタンにSub OPValueStock()を登録しても、それで保存されるのはオプションボタンを押した状態での配列ですよね?押す前の状態は保存されないのでは? まったく、押されていない、すべてオフの状態では、登録をしたところで、全部オフです。 しかし、もしも、すでに、押されている状態を取得するのでしたら、Sheet_Activate イベントやWorkbook_Open イベントで取ります。 もし、固定状態でしたら、最初から、配列で、どれか1つに、1を代入すればよいわけです。 後は、配列の中身を、ローカルウィンドウで確保されているかみてください。 On は、1として入っているはずです。

  • bonaron
  • ベストアンサー率64% (482/745)
回答No.7

エクセルは門外漢ですが。 フォームのオプションボタンをはじめて使いました。。。 Option Explicit Dim OptionIndex As Integer Private Function CheckCondition() As Boolean 'キャンセルする条件の場合 True を返してね。 CheckCondition = False End Function Private Sub SetOption(Idx As Integer, sw As Boolean) Sheet2.Shapes("Opt" & Idx).ControlFormat.Value = sw If sw Then OptionIndex = Idx Else OptionIndex = 0 End If End Sub Private Sub CheckOption(Idx As Integer) If Not CheckCondition Then OptionIndex = Idx Else If OptionIndex <> 0 Then SetOption OptionIndex, True Else SetOption Idx, False End If End If End Sub Public Sub Opt1_Click() CheckOption 1 End Sub Public Sub Opt2_Click() CheckOption 2 End Sub '・・・・・・ Public Sub Opt7_Click() CheckOption 7 End Sub

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

こんにちは。 >Sub OPRecoverを走らせましたが、オプションボタンは元には戻りませんでした。 大方、それは、モジュールレベル変数が抜けているのだと思います。 Private Ops() As Long '←これ ただし、他のプロシージャが同一のモジュールにない場合は、Public にしてくださいね。

merlionXX
質問者

お礼

> Private Ops() As Long '←これ いいえ、忘れていません。同一モジュールの一番上にあります。 でも、考えたんですが、各オプションボタンにSub OPValueStock()を登録しても、それで保存されるのはオプションボタンを押した状態での配列ですよね?押す前の状態は保存されないのでは?(よくわかってもないのにすみません)

noname#22222
noname#22222
回答No.5

s_husky です。 回答を外しましたので訂正! 入力は手動。 キャンセルはコマンドボタンのようです。 ならば、多少、変更が必要です。 Private Sub OptionButton1_Click()   UpdateOption 1 End Sub Private Sub OptionButton2_Click()   UpdateOption 2 End Sub  |  | Private Sub OptionButton7_Click()   UpdateOption 7 End Sub Private Sub cmdCancel_Click()   UpdateOption 0 End Sub Public Sub UpdateOption(ByVal intIndex As Integer) On Error Resume Next   Static OldIndex(1)  As Integer   Dim OptionsValues(7) As Boolean   Dim isCancel     As Boolean   isCancel = intIndex = 0   intIndex = IIf(isCancel, OldIndex(1), intIndex)   If isCancel Then     OptionsValues(OldIndex(1)) = False     OptionsValues(intIndex) = True     Me.OptionButton1.Value = OptionsValues(1)     Me.OptionButton2.Value = OptionsValues(2)     Me.OptionButton3.Value = OptionsValues(3)     Me.OptionButton4.Value = OptionsValues(4)     Me.OptionButton5.Value = OptionsValues(5)     Me.OptionButton6.Value = OptionsValues(6)     Me.OptionButton7.Value = OptionsValues(7)   End If   OldIndex(1) = OldIndex(0)   OldIndex(0) = intIndex End Sub

関連するQ&A

専門家に質問してみよう