• ベストアンサー

エクセルVBAで xlOn xlOff の切替

エクセル2000です。 ワークシート上に配置したオブジェクトのVisibleのTrue Falseについては、test01の方法で切り替えることが出来ます。 では、Test02でIfで判定している、xlOn xlOff の切替についても同様にNOTを使って簡単に記述することはできないでしょうか?xlOn xlOff はTrue False ではないから無理なのでしょうか? Sub test01() Dim o As Object For Each o In ActiveSheet.Buttons o.Visible = Not o.Visible Next o End Sub Sub test02() Dim o As Object For Each o In ActiveSheet.CheckBoxes If o.Value = xlOn Then o.Value = xlOff Else o.Value = xlOn End If Next o End Sub

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

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

こんばんは。 あまり、難しく考えなくても、単に、こういうことではありませんか? これも、ビット演算のひとつでしょうね。  For Each o In ActiveSheet.CheckBoxes   o.Value = -Not (xlOff - o.Value)  Next o

merlionXX
質問者

お礼

-Not (xlOff - o.Value) !!!! こんな式、はじめて見ました! ありがとうございました。 でも、確かにうまく行きましたが・・・・。???? xlOn が1で、xlOffがなぜか -4146なのは存じていましたが、計算につかえるんですね。 でもxlOff-xlOffなら、0ですけど、xlOff-xlOnの場合は -4147 ですよね? それを-Not? 不可思議です・・・。

その他の回答 (4)

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

こんばんは。 >VBAではTRUEはマイナス1なのですね?! そうなのです。 ワークシートと仕様が違うので気をつけないといけませんね。ワークシート側のTRUE は、0 以外なので、それは、C言語と同じことになります。また、Win32APIも、TRUE(全部大文字) は、「0 」以外となりますので、Not(False) ということになります。 なお、Excelの DEC2BIN()関数は、16ビットは計算できないので、VBAでユーザー定義関数を作るか、Vector で、そういうソフトを手に入れるか、筆算で答えを出すかぐらいしかありません。 筆算で出す方法 例 16     余 2 16    16/2 2  8 0   8/2 2  4 0   4/2 2  2 0   2/2 2  1 1   1/2  ------------   1000 となります。

merlionXX
質問者

お礼

有難うございました。 VBAでは、TRUE=-1、FALSE=0 ∴TRUE+TRUE=-2 ワークシートでは、TRUE<>0、FALSE=0 ただし、ワークシート上でTRUEを計算に使うときは1になる。 ∴TRUE+TRUE=2 勉強になりました。

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

こんばんは。 まだ、私は、この方面は、初歩の初歩なもので、間違いがありましたら、お許しください。 >それならば、Falseが0だとすると >Not Falseは -(0+1) =1でTrueになるのならばなんとか理解はできます。(Not 0がTrueを返さないのは理解できませんが) >しかし、Trueが1だとすると >Not Trueは -(1+1) =-2で、これがなぜFalseを返すのでしょうか? まず、以下は、8ビットの計算 False =0, True = -1 (Byte型 =255)         2進     10進 ----------------------------------- False    00000000     0 Not(False)  11111111    -1 反転 ----------------------------------- True    11111111     -1 Not(True)  00000000     0 反転 ------------------------------------ 3    00000011 Not(3)  11111100   =-4 ------------------------------------ 10    00001010 Not(10) 11110101  =-11 ------------------------------------ ということになるはずです。 10進の計算ですると、  Not(False) は、Not(0) = -1 .... -(0 +1)  Not(True) は、Not(-1) =0 ..... -(-1 + 1)  Not(3) =-4 ................. -(3 + 1)  Not(10) =-11 ............... -(10 + 1) -Not(xlOff - xlOn) -Not(xlOff - xlOff) こちらは、ご覧のとおり16ビットにします。 なお(-[マイナス負数])にするということは、各ビットを反転させて、右端の桁に、1を加えて作ることです。 例: xlOff - xlOn    xlOff   11101111 11001110 - xlOn    00000000 00000001 -----------------------------------         11101111 11001101 Not(xlOff - xlOn)         00010000 00110010 反転 ----------------------------------- -Not(xlOff - xlOn) 負数で反転         11101111 11001101 Not(xlOff - xlOn)を反転         00000000 00000001 1を足す ------------------------------------         11101111 11001110  =-4146 =============================================== xlOff - xlOff   xlOff   11101111 11001110 - xlOff   11101111 11001110 -----------------------------------         00000000 00000000 Not(xlOff - xlOff)         11111111 11111111  反転 =-1 ----------------------------------- -Not(xlOff - xlOff)  負数で反転         00000000 00000000  Not(xlOff - xlOff)を反転         00000000 00000001  1を足す -----------------------------------         00000000 00000001  =1 このような計算をしているのだと思っています。 少し、書いていて、疲れました(^^;

merlionXX
質問者

お礼

お手数をおかけいたし申し訳ありませんでした。 ちょっと難しすぎてわたしにはお手上げです。 わたしはこれまで、エクセルではTRUEは1、FALSEは0と理解してきましたが、VBAではTRUEはマイナス1なのですね?!

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

こんにちは。Wendy02です。 最近、新しい言語の勉強をし始めたもので、まだ、本当に、私もよく分かっているわけではないです。 >それを-Not? 不可思議です・・・。 これは、ビット演算ですよね。 同様のプロパティ値は、値は違っていても、単にバイアスが掛かっているだけだと思ったのです。だから、merlionXXさんの思いつきは、間違っていなかったと思います。ただ、これは、VB系の中では、あまり活かされることはないような気がします。 True が、-1 なら、Not(True) は、1 を足して、正負を逆に(反転)する、ということだ思いました。本来は、ビットで見なければならないのですが、ビット数が多いので、途中で分からなくなってしまいました(^^;。 ところで、ちょっと、今回の件とは直接は関係がないけれども、以下は、Excel VBAの基礎的な問題のひとつです。#1の中で、気になりました。 VBE を通さず、見て分かりますか?意外に知らない問題なのです。もし、ご存知でしたら、お見捨ていただいて結構です。 Sub Test1() Dim i As Integer Dim ret As Variant  i = 0  ret = IIf(i <> 0, 10 / i, "エラー") End Sub 1. 0 2. 1 3. "エラー" 4. 10 5. そのどちらでもない それから、VBE に、実際に通してみてください。その理由を、想像してみてください。

merlionXX
質問者

お礼

すみません、Not FalseがTrue、Not TrueがFalseを返すのは存じておりましたが、VBAでNotは何を返すのでしょうか? たとえば、 Not 0が-1 Not 1が-2 Not 3が-4 Not 10が-11 どうも -(対象+1) という計算をしているように思えます。 となると、 -Not (xlOff - xlOn) は -(-((-4146-1)+1))で、-4146=xlOff、 -Not (xlOff - xlOff) は -(-((-4146-(-4146))+1))で、1=xlOnになるのだと思うのです。 それならば、Falseが0だとすると Not Falseは -(0+1) =1でTrueになるのならばなんとか理解はできます。(Not 0がTrueを返さないのは理解できませんが) しかし、Trueが1だとすると Not Trueは -(1+1) =-2で、これがなぜFalseを返すのでしょうか? それから、#3でのIIFの例は、通常のIf Then else だと、最初のIf条件に適うとelseの指示はスルーするけど、IIFではTrueもFalseも両方計算されるから要注意というアドバイスですね。だから例では0で除算という実行時エラーになるのだと思いました。気をつけなきゃいけないですね、有難うございました。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

Booleanでないので、Notで反転、と簡単にはいかないですね。同じようなユーザ定義関数 Function MyNot(N as Integer) as Integer  If N = xlOn Then   MyNot = xlOff  else   MyNot = xlOn  End If End Function を作っておいて、 o.Value = MyNot(o.Value) とするか、あるいはIIFを使って、 o.Value = IIF(o.Value = xlOn, xlOff, xlOn) とするとか。

merlionXX
質問者

お礼

> Booleanでないので、Notで反転、と簡単にはいかないですね やはりそうですよねぇ。 虫のいいことを考えましたが・・・・・。 IIF関数で逃げることにします。有難うございました。

関連するQ&A

  • エクセルVBAでShapesまたはDrawingObjects

    シート上のフォームなどを表示/非表示するためtest04を書きましたが、「実行時エラー438 オブジェクトはこのプロパティまたはメッソッドをサポートしていません」となります。 しかし、Test05のように同じことをForNextで回せばうまくいきます。 また、Test06のようにShapesをDrawingObjectsに書き換えただけでもうまくいきます。 では、Test04がエラーになるのはなぜでしょうか? Sub test04() With ActiveSheet.Shapes If .Visible = False Then .Visible = True Else .Visible = False End If End With End Sub Sub test05() For Each sp In ActiveSheet.Shapes If sp.Visible = False Then sp.Visible = True Else sp.Visible = False End If Next End Sub Sub test06() With ActiveSheet.DrawingObjects If .Visible = False Then .Visible = True Else .Visible = False End If End With End Sub

  • エクセル・マクロでIf Thenの使い方

    このような質問は、ルール(エチケット、マナー)違反になるでしょうか? もしそうならお許し下さい。 名前ボックスに表示される名前を、マクロで非表示にし、元に戻す、という操作を次の二つのボタンで実行するように作りました。エクセル2003です。 Private Sub CommandButton1_Click() Dim tname As Name For Each tname In ThisWorkbook.Names tname.Visible = False Next End Sub Private Sub CommandButton2_Click() Dim tname As Name For Each tname In ThisWorkbook.Names tname.Visible = True Next End Sub これを一つのボタンで、If Then Elseを使い実行できるようにしたいのですが If ・・・ Then の間の書き方が分からずうまくいきません。   If Names.Visible = False Then   If ThisWorkbook.Names.Visible = False Then If ThisWorkbook.tname.Visible = False Then Private Sub CommandButton3_Click() Dim tname As Name If Names.Visible = False Then 'これでは駄目 For Each tname In ThisWorkbook.Names tname.Visible = False Next Else For Each tname In ThisWorkbook.Names tname.Visible = True Next End If End Sub 苦し紛れにこんなことをやってごまかそうとしているのですがこれって邪道ですしかっこうわるいですよね。 Private Sub CommandButton3_Click() Dim tname As Name If Range("g1").Value = " " Then   For Each tname In ThisWorkbook.Names   tname.Visible = False   Next Range("g1").Value = "1" Else   For Each tname In ThisWorkbook.Names   tname.Visible = True   Next Range("g1").Value = " " End If End Sub ど素人ですがよろしくご教導ください。

  • VBAで、デバッグをお願いします。

    作りたいプログラムはpartsno_01から、partsno_20までのテキストボックスに、エクセルのセルA1から、A20までにある製品番号を入力し、データをsubmitするものです。 Sub pn() Dim ObjIE As Object Dim ObjShell As Object Dim ObjWindow As Object Dim WinExist As Boolean WinExist = False Set ObjShell = CreateObject("Shell.Application") For Each ObjWindow In ObjShell.Windows If TypeName(ObjWindow.document) = "HTMLDocument" Then WinExist = True Set ObjIE = ObjWindow End If Next Set ObjShell = Nothing If Not WinExist = True Then MsgBox "製品番号検索を開いてください。" Exit Sub End If ObjIE.Visible = True Do While i < 21 i = 1 Set elements = ObjIE.document.getElementsByName("partsno_0" & "i") If elements Is Nothing Then Exit Sub End If elements.Item(0).Value = Worksheets(1).Cells(i, 1).Value i = i + 1 Loop End Sub で、 elements.Item(0).Value = Worksheets(1).Cells(1, 1).Value が常にエラーになります。 間違っていはいないと思うんですが・・・・。 何がいけないのでしょうか。

  • エクセルVBAでLockされてないセルをClearContents

    エクセル2000です。 シートでロックされていないセルだけ中身を削除するマクロを作っています。以下でも一応作動はするのですが、いちいちForNextでまわさずにできないものかと質問させていただきました。 よろしくお願いします。(o。_。)oペコッ Sub クリアテスト() Dim c As Range For Each c In ActiveSheet.UsedRange If c.Locked = False Then c.ClearContents End If Next End Sub

  • エクセルVBA ラベル表示/非表示の切替速度

    質問失礼します。 エクセル2003でラベル(コントロールツール)を作成し、 ラベルの表示/非表示を別に作成したボタンを押すたびに 切り替えるマクロを作成しています。 一応、自分で作成したものは動作するのですが、余りにも処理が遅いです。 (ボタンを押下後、処理が完了するまでに8秒前後かかります。) 『この場合はこうした方がいい』や『こうすれば早くなる』、または『それが限界』などの ご意見があれば、ご返答お願い致します。 ※ラベルは1グループ18個のa・b・cの3グループで合計54個あります。 ※ラベルのオブジェクト名はa1・a2・a3・・・という規則性でつけています。 <作成例> Private Sub button1_Click() Dim test As Boolean If a1.Visible Then test = False Else test = True End If With ActiveSheet For i = 1 To 18 Step 1 .OLEObjects("a" & i).Visible = test .OLEObjects("b" & i).Visible = test .OLEObjects("c" & i).Visible = test Next i End With End Sub

  • Excel VBA チェックボックスの一括オン、オ

    1.2.のように2つマクロを作成し、それぞれチェックボックスのオン、オフが一括でできるようになったのですが、1つにまとめることはできますでしょうか? 1回クリックすると、一括オン、もう一度クリックすると一括オフを繰り返すようにしたいです。 1.チェックオフ Dim myobj As OLEObject For Each myobj In ActiveSheet.OLEObjects If TypeName(myobj.Object) = "CheckBox" Then _ myobj.Object.Value = False Next 2.チェックオン Dim myobj As OLEObject For Each myobj In ActiveSheet.OLEObjects If TypeName(myobj.Object) = "CheckBox" Then _ myobj.Object.Value = True Next

  • VBA エクセル 文字列

    A列に、【鈴木 太郎】、【佐藤 一郎】・・・・と続いていて、B列には鈴木、佐藤・・・と表示させたい場合は以下のソースに、 =LEFT(A1,FIND(" ",SUBSTITUTE(A1," "," "))-1) と同じソースを書けばいいのはわかるのですが、勉強不足でわかりません。教えていただけませんでしょうか。下記のソースも教えていただきました。すごく助かります。 Sub PickupWords() Dim Matches As Object Dim Match As Object Dim buf As String Dim c As Variant With CreateObject("VBScript.RegExp") .Pattern = "【(.+)】" .Global = False Application.ScreenUpdating = False For Each c In Range("A1", Cells(Rows.Count, 1).End(xlUp)) If .Test(c.Value) Then buf = c.Value Set Matches = .Execute(buf) c.Offset(, 1).Value = Matches.Item(0).SubMatches(0) '括弧の中を取り出す End If Next c Application.ScreenUpdating = True End With End Sub

  • 複数のセルのなかに該当があればオートシェイプを表示

    http://okwave.jp/qa/q8365189.html 上記質問の続きです。 画像のようなチェック表をExcelで作っています。 右側欄外に表を作成し、 ◎を付ける番号、○をつける番号をそれぞれ入力し、 「入力内容を反映」ボタンをクリックすると、 オートシェイプで配置した◎や○が表示されるようにしたいです。 VBAを以下のように作成してみたのですが、 ◎はつくのですが、 ○をつけるVBAが動きません。 どのように修正するべきでしょうか? ご教授ください! Private Sub CommandButton1_Click() '○で囲むVBA Dim c For Each c In Range("U103:Y103") If InStr(c.Value, "1") > 0 Then ActiveSheet.Shapes("1を囲む○").Visible = True Else ActiveSheet.Shapes("1を囲む○").Visible = False End If If InStr(c.Value, "2") > 0 Then ActiveSheet.Shapes("2を囲む○").Visible = True Else ActiveSheet.Shapes("2を囲む○").Visible = False End If Next c ・ ・ ・ '最も重要なものを◎で囲むVBA If Range("T103").Value = "1" Then ActiveSheet.Shapes("1を囲む◎").Visible = True Else ActiveSheet.Shapes("1を囲む◎").Visible = False End If If Range("T103").Value = "2" Then ActiveSheet.Shapes("2を囲む◎").Visible = True Else ActiveSheet.Shapes("2を囲む◎").Visible = False End If ・ ・ ・ End Sub ちなみに「'○で囲むVBA」のコードだけを残して動作させてみると、 1や2が一番右のセル(Y103)に入力されると、1を囲む○、2を囲む○がそれぞれ表示されるのですが、 それ以外のセル(U103からX103)に1や2を入力しても○は表示されません。 全コードを入力して動作させると、 1や2を一番右のセル(Y103)に入力しても○はどこにも表示されません。 よろしくお願いいたします!

  • エクセル2000VBAでオブジェクトの指定

    エクセル2000VBAでオブジェクトの指定 ワークシート上にボタン、チェックボックス、コンボボックス等のコントロールがあります。(OLEオブジェクトではありません、フォームのオブジェクトです。) そして、それらのすべてが表示されているわけではなく、中にはVisible=False で非表示にされているものもあります。 またフォーム以外にもワードアート、ピクチャー等のオブジェクトも配置されています。 このうち、現在表示されているボタン、チェックボックス、コンボボックス等のコントロールだけを非表示にし、その後再度表示させたいのです。(最初から非表示のものは表示させない) 一応、以下のようなVBAコードで目的は達成されます。 Sub TEST01()   Dim ob As Object   Dim buf As Boolean, myAry As Variant   With ActiveSheet        Application.ScreenUpdating = False '画面更新停止     For Each ob In .DrawingObjects 'Shapesではダメ       If ob.Visible = True Then '可視なら         Select Case TypeName(ob) '以下に該当すれば選択           Case "Button": ob.Select (False)           Case "CheckBox": ob.Select (False)           Case "DropDown": ob.Select (False)           Case "Spinner": ob.Select (False)         End Select       End If     Next ob          If TypeName(Selection) <> "Range" Then '対象があれば       buf = True       Set myAry = Selection       .Range("A1").Select       myAry.Visible = False '非表示に     End If     Application.ScreenUpdating = True '画面更新停止解除          If buf Then       MsgBox "非表示にしました。"       myAry.Visible = True '表示       MsgBox "再度表示しました。"       Set varAry = Nothing     Else       MsgBox "非表示にする対象はありません。"     End If        End With End Sub 質問は2つですが、どちらかへの回答でもかまいません。 1.上記コードでは対象のオブジェクトをSelectしてから Set myAry = Selection で変数を定義しましたが、いちいちSelectしなくともよい方法を知りたいのです。 多分、対象のオブジェクトを配列に取り込めばいいのでしょうが、やり方がわかりません。 2.上記コードではいちいち Case "Button" Case "CheckBox" などと、コントロールの種類を列記していますが、これを列記しないでもコントロールだと識別する方法はないのでしょうか? お知恵をお貸しください。

  • EXCELオプションボタンのグループ線非表示

    Sub test() Dim grp As Variant excel2000 でフォームのオプションボタンを多数設置しており、グループボタンの線をまとめて 非表示にしようと、下記コードでやってみたところ、反応がありません。 どこをどう修正すれば、いいかアドバイスいただけないでしょうか? よろしくお願いいたします。 For Each grp In Workbooks If grp.Name Like "グループ*" Then ActiveSheet.Shapes(grp).Visible = False End If Next grp End Sub

専門家に質問してみよう