エクセルVBAオートシェイプの条件分岐

このQ&Aのポイント
  • エクセルVBAの初心者が、セルに文字が入っておらずオートシェイプがない場合にアクションを起こす方法を知りたいです。
  • 質問者はIFを使った条件分岐が難しいため、SELECTCASEを使おうと思っています。
  • ケース2の条件として「オートシェイプがあったら」という条件をどのように書けばいいのか分かりません。
回答を見る
  • ベストアンサー

エクセルVBAオートシェイプがあったら、の書き方

皆さんこんにちは。 エクセルVBAの初心者です。 IFを使った条件分岐が私には難しかったので SELECTCASEを用いてみようと思うのですが条件の書き方が分かりません。 やりたい事は セルA1が「文字が入っていない且つオートシェイプが入っていない場合」のみ アクション(オートシェイプ☆を貼る)を起こしたい、です。 イメージ的にこうなるかな?と思いコードを作成しましたが ケース2の「オートシェイプがあったら」という条件の書き方が分かりません。 Sub オートシェイプ貼り付け()   With ThisWorkbook.Worksheets("Sheet1")   Select Case True     Case .Range("A1").Value <> ""     Exit Sub     Case オートシェイプがあったら     Exit Sub     Case Else       オートシェイプ☆を貼る   End Select End Sub オートシェイプの有無を条件にするにはどのような書き方をすれば良いでしょうか?

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

  • ベストアンサー
回答No.1

こんにちは。 > SELECTCASEを用いてみようと思うのですが条件の書き方が分かりません。 > ケース2の「オートシェイプがあったら」という条件の書き方が分かりません。 'オートシェイプ'が厳に'オートシェイプ'を指しているとすれば、 Shapes コレクションの Shape オブジェクトを総当たりでループして、 shape.Type プロパティが msoAutoShape であるものの有無をチェック することになります。 こういう場合は関数にしておいた方が簡単でしょうね。 ' ' /// Shapes に'オートシェイプ'が含まれるならTrue Function HasAutoShape(oShapes As Shapes) As Boolean   Dim oS As Shape   For Each oS In oShapes     If oS.Type = msoAutoShape Then       HasAutoShape = True       Exit For     End If   Next End Function ' ' /// 本題への答として、この関数と組み合わせて     Case HasAutoShape(.Shapes)       Exit Sub     Case Else のように書くことができます。 'オートシェイプ'とは言ってみたものの実は'シェイプ'のことだった場合は、 関数などなくともシンプルに     Case .Shapes.Count > 0       Exit Sub     Case Else のような書き方で済みます。 一般に、'オートシェイプ'は[図形]の[挿入]で得られる'シェイプ'のこと、 また、'シェイプ'には、チャート、各種コントロール、セルのコメント、 等々、シート上に配置したセル以外のものは殆ど'シェイプ'に含まれます。 > IFを使った条件分岐が私には難しかったので ... ... > オートシェイプの有無を条件にするにはどのような書き方をすれば良いでしょうか? コツさえ掴んでしまえば、If ... Then ステートメント の方が 簡単であっさりしたものになります。 今回の場合は、If ... を用いるのが標準的かな、とは思います。 勿論、両方扱える方がいいですよね。 ' ' /// 'オートシェイプ' Sub オートシェイプ貼り付け2()   With ThisWorkbook.Worksheets("Sheet1")     If .Range("A1").Value <> "" Then Exit Sub     If HasAutoShape(.Shapes) Then Exit Sub     ' オートシェイプ☆を貼る   End With End Sub ' ' /// ' ' /// 'シェイプ' Sub オートシェイプ貼り付け2()   With ThisWorkbook.Worksheets("Sheet1")     If .Range("A1").Value <> "" Then Exit Sub     If .Shapes.Count > 0 Then Exit Sub     ' オートシェイプ☆を貼る   End With End Sub ' ' /// 「○○があるかどうか」というのは、 コレクションオブジェクト(この場合はShapes)のプロパティで、  collection.Count 等で、オブジェクトの数を取得して、0 より大きいか、 という判別することになるものが多いです。 'シェイプ'にはコレクションがあり、.Count プロパティで、 「'シェイプ'があるかどうか」を簡単に調べられますが、 残念ながら'オートシェイプ'にはコレクションがありませんので、 「'オートシェイプ'があるかどうか」を調べる為には、 オブジェクトを総当たりで調べて、見つかったらループを抜ける、 というやり方になります。こういう扱い方をするオブジェクトも 結構たくさんありますから、For Each ... Next ループと Exit For の構文はいずれ必要な場面に出くわすこともあるでしょう。 > ' オートシェイプ☆を貼る この部分は、こちらでは書けている、省略している、という理解でいます。 以上です。

harumama0430
質問者

お礼

realbeatinさん ご回答ありがとうございます。 IF、あっさり書く事が可能なのですね。 ワークシート関数のみの知識しかないのでVBAではどうやって 「文字がない」AND「図形がない」を条件として書くかばかりを考えてました。 ANDがなくてもIFが2つ並んで良いんですね、衝撃です! また、本でオートシェイプの情報はセルではなく図形本体に持たせられるみたいな事が 書いてあったので更に???になり・・・。 数をかぞえて0より多いという書き方は目からうろこです。 >オートシェイプ☆を貼る  は参考書を読みながら出来ました。  いつもありがとうございます。

関連するQ&A

  • エクセルVBAでの複数のオートシェイプの色塗り方法

    ネットから下記のコードを見つけたのですが、1つのシートに複数のオートシェイプの色塗りを変更する方法を教えてください。 例えばセル"A1"には数値の1と"A2"には数値2を入力したら、 オートシェイプAにはセル"A1"に対応した色塗り『赤色』を オートシェイプBにはセル"A2"に対応した色塗り『黄色』といった感じです。 下記のコードをいくつも繋げれば、複数のオートシェイプの色塗りが出来ると思ったのですが、コードを繋げる方法がわかりません。その他に何か良い方法がありましたら教えてください。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address(0, 0) <> "A1" Then Exit Sub With ActiveSheet.Shapes("ABC").Fill.ForeColor Select Case Target.Value Case Is = "赤" .SchemeColor = 2 Case Is = "黄" .SchemeColor = 5 Case Is = "緑" .SchemeColor = 3 Case Is = "青" .SchemeColor = 4 Case Else .SchemeColor = 1 End Select End With End Sub

  • エクセルVBAで指定範囲内のオートシェープを選択

    エクセル2000です。 仮にワークシートのRange("A1:B5")の範囲の中に貼り付けられたオートシェープの直線をまとめて選択する場合にはどのように書けばいいのでしょうか? Sub TEST() Application.Intersect(Range("A1:B5"), ActiveSheet.Lines).Select End Sub とやってみましたが、エラーでした。 どうぞよろしくお願いします。

  • VBAでオートシェイプの制御?

    エクセルマクロでセルにオートシェイプを張る方法を調べていて、ここで丁度いいのを見つけました。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=808898 見つけた下記のマクロを実際にやってみました。 A1に1を入れるとB2にハートマークが出ます。 しかし、さらに2を入力してもB2のハートは削除されてくれません。 さらに1をいれると、ハートの上にハートが重なってしまいます。 1ならハート、それ以外の入力ならハートが消えるようにするにはどうすればいいのでしょうか? Private Sub Worksheet_Change(ByVal Target As Range) If Target <> Range("A1") Then Exit Sub If Target.Value = 1 Then With ActiveSheet.Range("B2") ActiveSheet.Shapes.AddShape(Type:=msoShapeHeart, _ Left:=.Left, Top:=.Top, Width:=.Width, Height:=.Height).Select End With End If End Sub

  • エクセルVBAで5行目からオートフィルタモードに設定したいたい

    抽出項目が5行目にあり、オートフィルタを5行目から表示させたいのですが、うまくいきません。 Macro1では項目が消えてしまい、▼が1行目に、Macro2では項目は残りますが、▼は同じく1行目になってしまいます。どうしたら5行目にオートシェイプの▼が配置できるでしょうか? Sub Macro1() Range("A5").Select Selection.AutoFilter End Sub Sub Macro2() Range("A5").AutoFilter End Sub

  • エクセルVBA 1つのシートで出来ますか?

    説明が下手で申し訳ございませんが、宜しくお願い致します。 sheet(1)に20個のボタンがあります。 ボタンをクリックすると、別のシートが開きます。 開いたシートにも複数のボタンがあり、そのうちの任意のボタンをクリックすると、そのボタンの値がsheet(1)のそれぞれのボタンに対応したセルに入力される、という動作を実現したいと思っています。 現状、下記のようなコードで目的の動作は実現できてはいるのですが、各ボタンそれぞれにシートを作っているような状況です。(データ自体は全く同じ内容のものが、計20シート) たぶん、もの凄く頭の悪い事をやっているんだろうと思います。 sheet(1)を除いた各シートの入力データ自体は全く同じなので、シート一枚で出来るんじゃないのかなと思い、ネットや本で調べながら色々試してみたのですが、どうも上手く行きません。データが同じでも、sheet(1)のクリックしたボタンによって入力するセルを変えなければならないのが問題です。 sheet(1)のボタンとセルの関連付けや、sheet(1)のどのボタンを押したのかの判別ができればいいのかなと思って調べてみても、初心者にはよく理解できず、もう何週間もチャレンジしているのですがお手上げです。 上級者の方の知恵をお借りできれば幸いです。 Sub sheet2を開く() Worksheets(2).Select End Sub Sub 入力1() Worksheets(1).Range("F8") = "データ1" Worksheets(1).Select End Sub Sub 入力2() Worksheets(1).Range("F8") = "データ2" Worksheets(1).Select End Sub Sub 入力3() Worksheets(1).Range("F8") = "データ3" Worksheets(1).Select End Sub Sub sheet3を開く() Worksheets(3).Select End Sub Sub 入力1() Worksheets(1).Range("H8") = "データ1" Worksheets(1).Select End Sub Sub 入力2() Worksheets(1).Range("H8") = "データ2" Worksheets(1).Select End Sub Sub 入力3() Worksheets(1).Range("H8") = "データ3" Worksheets(1).Select End Sub Sub sheet4を開く() Worksheets(3).Select End Sub Sub 入力1() Worksheets(1).Range("M8") = "データ1" Worksheets(1).Select End Sub Sub 入力2() Worksheets(1).Range("M8") = "データ2" Worksheets(1).Select End Sub Sub 入力3() Worksheets(1).Range("M8") = "データ3" Worksheets(1).Select End Sub    ・    ・    ・    ・    ・

  • 印刷後のVBAの実行 (2)

    Private Sub Workbook_BeforePrint(Cancel As Boolean)   If ActiveSheet.Name = "Sheet1" Then     If Range("D6").Value = "" Then       Cancel = True       MsgBox ("名前を入力してください")       Range("D6").Select       Exit Sub     End If   Else     If ActiveSheet.Name = "Sheet2" Then       If Range("C11").Value = "" Then         Cancel = True         MsgBox ("受付時間を入力してください")         Range("C11").Select         Exit Sub       End If     Else              Exit Sub     End If   End If   ActiveSheet.Range("A70:Y70").Copy   If Worksheets("Sheet3").Range("A1").Value = "" Then     Worksheets("Sheet3").Range("A1").PasteSpecial Paste:=xlPasteValues   Else     Worksheets("Sheet3").Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial _       Paste:=xlPasteValues   End If   Application.CutCopyMode = False   ActiveSheet.Range("A1").Select End Sub 先日、上記のコードを回答者の方から教えてもらい、とても助かっていますが sheet1のD5に「不要」という文字が入っていた場合、 sheet3への貼り付け(23~30行目の作業)をキャンセルして、最後にsheet1のA1を選択するようにはどの様にしたらいいでしょうか?

  • VBAの記述を簡単にする

    下記のようなVBAを作成したいのですが、 Case "1"からCase "1000"まであると書き込みが大変です。 簡単に入力する方法を教えてください。 Sub 貼付() Dim x As Integer x = Worksheets("Sheet1").Range("B7") Select Case Range("A1") Case "1" Worksheets("Sheet2").Range("H2") = x Case "2" Worksheets("Sheet2").Range("H3") = x Case "3" Worksheets("Sheet2").Range("H4") = x Case "4" Worksheets("Sheet2").Range("H5") = x Case "5" Worksheets("Sheet2").Range("H6") = x Case "6" Worksheets("Sheet2").Range("H7") = x ・ ・ ・ Case "1000" Worksheets("Sheet2").Range("H1001") = x End Select End Sub

  • エクセルVBA オートシェイプを操作したいです

    エクセルでセルの入力内容によって楕円をオートシェイプで出現させたいと思います。 http://oshiete1.goo.ne.jp/qa809742.htmlで見つかったものを参考にし、 Private Sub worksheet_Activate() Dim Shp As Shape Set P11 = Range("P11") If P11 Is Nothing Then Exit Sub If P11.Value = 1 Then For Each Shp In ActiveSheet.Shapes If Not Application.Intersect(Shp.TopLeftCell, _ Range("N14:N15")) Is Nothing Then Shp.Delete End If Next Shp With ActiveSheet.Range("N14:N15") ActiveSheet.Shapes.AddShape(Type:=msoShapeOval, _ Left:=.Left,TOP:=.TOP,Width:=.Width,Height:=.Height).Select Selection.ShapeRange.Fill.Visible = msoFalse End With Range("N14").Select Else For Each Shp In ActiveSheet.Shapes If Not Application.Intersect(Shp.TopLeftCell, _ Range("N14:N15")) Is Nothing Then Shp.Delete End If Next Shp End If If P11.Value = 2 Then For Each Shp In ActiveSheet.Shapes If Not Application.Intersect(Shp.TopLeftCell, _ Range("N16")) Is Nothing Then Shp.Delete End If Next Shp With ActiveSheet.Range("N16") ActiveSheet.Shapes.AddShape(Type:=msoShapeOval, _ Left:=.Left, TOP:=.TOP, Width:=.Width, Height:=.Height).Select Selection.ShapeRange.Fill.Visible = msoFalse End With Range("N16").Select Else For Each Shp In ActiveSheet.Shapes If Not Application.Intersect(Shp.TopLeftCell, _ Range("N16")) Is Nothing Then Shp.Delete End If Next Shp End If End Sub とつなげて見ました。 動くには動くのですが、データ元のセルがP11からT30と100セルあり、さらにP11に入力されるデータが1,2,3,4の4種類、AQ11に5,6,7,8,9の5種類などと、ばらばらです。 P11に1が入力されるとN14:N15(結合されています)に円が入り、2が入力されるとN16に円が入る。 Q11に5が入力されるとR13に円が入り、6が入力されるとR14:R15に円が入る・・・・のようにしたいのです。 一生懸命、セルNo.を打ち込んでいたら、 「コンパイルエラー:プロシージャが大きすぎます」とエラーが出てしまいました。 ループさせればよいのだろうと試してみたのですが、元のセルの指定方法や、オートシェイプの出現させるせるの指定方法がわかりません。 どのようにすれば、データー元の範囲を指定して、それに対応したセルにオートシェイプを出現させる事が出来るようになるでしょうか。 お知恵を貸していただけないでしょうか。よろしくお願い致します。

  • Excel VBA グラフチャート名で指定するには

    ExcelのVBAでグラフを作成した後 ActiveChartでアクティブなチャートを指定するのではなく ActiveChart.Nameなどで取得したチャート名で指定するには どのように記述すればよいでしょうか。 例えば、以下のtest()のコードの中の ActiveChart.SetSourceData Source:=Range("Sheet1!A1:B2"), PlotBy:=xlRows ActiveChart.SetElement (msoElementPrimaryCategoryAxisNone) ActiveChart.PlotArea.Select ActiveChart.Parent.Copy の部分をActiveChartを使わずチャート名(chart_nameなど)で指定するには どのように記述すればよいでしょうか。 よろしくお願いします。(Windows7,Excel2016) --------------------------------------- Sub test()  Dim chart_name As String  ThisWorkbook.Worksheets("Sheet1").Select  ThisWorkbook.Worksheets("Sheet1").Range("A1") = "A"  ThisWorkbook.Worksheets("Sheet1").Range("A2") = "B"  ThisWorkbook.Worksheets("Sheet1").Range("B1") = "75"  ThisWorkbook.Worksheets("Sheet1").Range("B2") = "25"  ThisWorkbook.Worksheets("Sheet1").Range("A10").Select  ThisWorkbook.Worksheets("Sheet1").Shapes.AddChart2(297, xlBarStacked100).Select  ThisWorkbook.Worksheets("Sheet1").Select  ActiveChart.SetSourceData Source:=Range("Sheet1!A1:B2"), PlotBy:=xlRows  chart_name = ActiveChart.Name  chart_name = Trim(Right(chart_name, Len(chart_name) - Len(ActiveSheet.Name)))  ThisWorkbook.Worksheets("Sheet1").ChartObjects(chart_name).Activate  ActiveChart.SetElement (msoElementPrimaryCategoryAxisNone)  ActiveChart.PlotArea.Select  ActiveChart.Parent.Copy End Sub

  • エクセルで色付けのVBAを作成してるのですが・・。

    エクセルでレンジ値の大きさにより色付けをする(下の条件)VBAを作りたいのですが うまく走りません。お手数とは思いますがご教授お願いします。 シート "aaa" のレンジ "A3<A2<A1" とだんだん大きくなれば、 シート "bbb" のレンジ "B1" の文字を黄色にして、シート "bbb" のレンジ "C1" の文字を赤色へ シート "aaa" のレンジ "A3<A2<A1" とだんだん大きくなれば、 シート "bbb" のレンジ "B1" の文字を緑色にして、シート "bbb" のレンジ "C1" の文字を赤色へ シート "aaa" のレンジ "A3,A1" が空白の場合、シート "bbb" のレンジ "C1" の文字を赤色へ シート "aaa" のレンジ "A3,A2,A1" が上の条件に合わなければ、 シート "bbb" のレンジ "B1" の文字を黒色にし、シート "bbb" のレンジ "C1" の文字を赤色にして終わる。 というようなプログラムで下記のように作りました。 ("A1,A2,A3"に入る値は50~100まで) ----------------------------------------------- Sub 注意() Dim v506Hi, v506Lo, v506a, v506b As Single v506a = Worksheets("aaa").Range("A3") v506b = Worksheets("aaa").Range("A1") If Worksheets("aaa").Range("A3") <> "" Then GoTo Sub1 ElseIf Worksheets("aaa").Range("A1") <> "" Then GoTo Sub1 Else Worksheets("bbb").Range("B1").Font.Color = RGB(0, 0, 0) GoTo sub2 Sub1: Select Case v506a Case Is < Worksheets("aaa").Range("A2") v506Hi = Worksheets("aaa").Range("A2") v506Lo = 0 Case Is > Worksheets("aaa").Range("A2") v506Lo = Worksheets("aaa").Range("A2") v506Hi = 500 Case Is = Worksheets("aaa").Range("A2") v506Hi = 500 v506Lo = 0 End Select Select Case v506b Case Is > v506Hi Worksheets("bbb").Range("b1").Font.Color = RGB(255, 255, 0)黄色 Case Is < v506Lo Worksheets("bbb").Range("b1").Font.Color = RGB(0, 255, 0)緑 Case Else Worksheets("bbb").Range("b1").Font.Color = RGB(0, 0, 0) End Select sub2: Worksheets("bbb").Range("c1").Font.Color = RGB(255, 0, 0)赤 End If End Sub ----------------------------------------------------------- プログラム初心者で間違いだらけとは思いますが、よろしくお願いいたします。

専門家に質問してみよう