- ベストアンサー
エクセルVBAでShapeRangeについて
すみません、教えてください。 以下のマクロは正常に動きます。 Sub TEST() With ActiveSheet For Each s In .Shapes If s.AutoShapeType = msoShape5pointStar Then s.Delete Next .Cells.Interior.ColorIndex = 1 Set AA = .Shapes.AddShape(msoShape5pointStar, 55, 22, 25#, 25#) AA.Fill.Visible = msoTrue AA.Fill.Solid AA.Fill.ForeColor.SchemeColor = 13 AA.Fill.Transparency = 0# AA.line.Weight = 0.75 AA.line.DashStyle = msoLineSolid AA.line.Style = msoLineSingle AA.line.Transparency = 0# AA.line.Visible = msoTrue AA.line.ForeColor.SchemeColor = 64 ' AA.Copy '(1) ' .Paste '(1) ' Set AB = Selection '(1) ' .Range("A1").Select'(1) Set AB = AA.Duplicate '(2) AB.Top = 44 AB.Left = 110 ' AB.ShapeRange.Fill.ForeColor.SchemeColor = 10'(1)の2 AB.Fill.ForeColor.SchemeColor = 10 '(2)の2 End With End Sub ところが、 Set AB = AA.Duplicate '(2)の部分を、コメントアウトしている '(1)の記述に変えると、 AB.Fill.ForeColor.SchemeColor = 10 '(2)の2 の部分も ' AB.ShapeRange.Fill.ForeColor.SchemeColor = 10'(1)の2 に変えないとエラーになります。 ' AA.Copy '(1) ' .Paste '(1) ' Set AB = Selection '(1) も Set AB = AA.Duplicate '(2) も、同じことのように思えるのですが、この違いで、ShapeRangeというのを入れたり消したりしなければならないのはどうしてでしょうか? エクセルは2000です。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
要は、 変数への格納の仕方、 Objectの指定の仕方が違う、 という話です。 Sub try4() Dim A As Object Dim B As Object With ActiveSheet With .Shapes.AddShape(msoShape5pointStar, 100, 100, 100, 100) .Duplicate.Select Set A = Selection 'Duplicateしたもの .Copy End With .Paste Set B = .Shapes(.Shapes.Count) 'Copyしたもの End With MsgBox "A: " & TypeName(A) & vbLf & "B: " & TypeName(B) Stop Set A = Nothing Set B = Nothing End Sub Sub try5() Dim A As Object With ActiveSheet .Shapes.AddShape msoShape5pointStar, 100, 100, 100, 100 Set A = .DrawingObjects(.DrawingObjects.Count) MsgBox A.ShapeRange.Name End With Stop Set A = Nothing End Sub
その他の回答 (5)
- kobouzu_su
- ベストアンサー率45% (24/53)
今日は暇なのでまた登場。 今回はこれで終わりにしまする。(^^;;; >う~っ、結果としてそうなったShapeの下にShapeRangeが無く、Rectangleの下にはまずShapeRangeがきて、その下にFillがくるという構造になっているということなんでしょうね。わかったようでわからないような・・・・ VBAのプロになるのであればなんですが、 こんな小難しいことは考えなくてもいいのではないのですか? 何回も言ってるように ●選択された図形●を扱う場合は、ShapeRangeコレクションを使う、 と覚えておけばいいと思いますよ。 Selection.ShapeRange.Fill。。。。。。 なお、当方の回答は、あくまでも 質問のタイトルにある、「エクセルVBAでShapeRangeについて」です。 で、今回の質問については当方の回答は終了ということで。
お礼
大師さま、何度もお手間を取らせすみませんでした。 ●選択された図形●を扱う場合は、Rectangle型になっているのでShapeRangeコレクションを使う。 選択しなくともRectangle型として変数に入れたオブジェクトもShapeRangeコレクションを使うということですね。 覚えます、有難うございました。
- kobouzu_su
- ベストアンサー率45% (24/53)
またまた登場、、、(^^;;; >わたしも選択しているか否かのせいではないかと思いました。 >それで .Range("A1").Select'(1) をわざと書き加えたのです。 >これでA1セルが選択されて図形の選択が解除されていますよね? Range("A1").Selectしたら図形選択は当然解除されますが、コードをよく見てください。 1。 AA.Copy 2。 .Paste 3。 Set AB = Selection 4。 .Range("A1").Select 2でコピーされた図形は選択された状態になり、 3でその選択された図形をABへセットしてますから この3で、ShapeRangeコレクションにAddされるわけです その後、4でセル選択して図形選択を解除しても それは画面上で解除されただけで、ShapeRangeには選択された図形として入っていることになりませんか? なりますよね。 4のセル選択は意味がないことになります。 なので、 >選択か否かではなくTypeNameがShapeかRectangleかの違いなのではないでしょうか? これは、先ず、選択したか否かがあり、 結果としてShapeかRectangleがあるわけですから 結論は選択したか否か、ということになるのではありませんか? そして、 >もっともDuplicateすればShapeのままで、CopyしてPasteしたらRectangleに変わるというのもなぜかわからないのですが・・・・ これについては、なぜか? という問いには誰も答えられないと思われます。 強いていうなら、Copyしたらではなくて、Selectionオブジェクトの仕様としか言いようがないですね。 ということで、今回の問題は、選択したか否か、ということです。 これでもう、ShapeRangeコレクションの使い方は分かりましたね?(^^;;; 以上です。
お礼
> 結果としてShapeかRectangleがあるわけですから > 結論は選択したか否か、ということになるのではありませんか? ここまではやっとわかりました。 > これでもう、ShapeRangeコレクションの使い方は分かりましたね?(^^;;; う~っ、結果としてそうなったShapeの下にShapeRangeが無く、Rectangleの下にはまずShapeRangeがきて、その下にFillがくるという構造になっているということなんでしょうね。わかったようでわからないような・・・・ φ( ̄_ ̄;) でも、そのように覚えておきます。
- pauNed
- ベストアンサー率74% (129/173)
ちょっとごちゃごちゃ書きすぎて、解り難かったようです。ごめんなさい。 『Copyで作成された』から『Typeが違う』のではありません。 Sub try1()だけ実行してください。 Selectせずに変数に格納したら型がShapeであり、 SelectしてSelectionを変数に格納したら型がRectangleになります。 >Stop時、VBEのローカルウィンドウを表示し、変数A,Bに格納されたObjectの型を確認してください。 これは、確認してみられましたか? さらに、A,Bそれぞれを展開してみてください。(左の田をクリック) Objectは階層構造になっています。 Aの直下にFillプロパティがあります。 Bにはありません。 ただ、Bの直下にShapeRangeプロパティがあります。 これは ShapeRange コレクションを返します。 このShapeRangeをさらに展開してください。最後に Item1 があります。 これがAと同じものです。 >AB.ShapeRange.Fill.ForeColor.SchemeColor = 10 は AB.ShapeRange.Item(1).Fill.ForeColor.SchemeColor = 10 と同じ事をしています。 >Selectメソッドで選択したObjectと、Selectionの内容は異なる事があります。 Shapeを選択しても、SelectionはShapeではない、という事です。
お礼
> Selectせずに変数に格納したら型がShapeであり、 > SelectしてSelectionを変数に格納したら型がRectangleになります。 CopyとDuplucateの違いではなかったのですね。わかりました。 > さらに、A,Bそれぞれを展開してみてください。(左の田をクリック) こういうところがあるとは存じませんでした。 初体験です。 > Objectは階層構造になっています。 > Aの直下にFillプロパティがあります。 > Bにはありません。 なるほど、こういう違いがあるんですねえ。 有難うございました。
- kobouzu_su
- ベストアンサー率45% (24/53)
エキスパートさん、こんにちは。 寒くなりましたがいかがお過ごしでしょうか。 と、余計なご挨拶は置いといて。。。 質問の件はヘルプをみてもなかなか分かりづらいところがありますが、 簡単に言うと、その図形が選択されてるかどうか、です。 選択された図形はShapeRangeコレクションの中に入るので その図形を扱うときはShapeRangeを使わないといけないということです。 但し、これは、今回のような【書式プロパティ】についてですが。 ------------------------------------------------- AA.Copy '(1) .Paste '(1) Set AB = Selection '(1) このABは【選択された状態】ですから、ShapeRangeでないとダメ --------------------------------------------------------- Set AB = AA.Duplicate このABは、【選択されてない状態】であり、 Set AB = Activesheet.Shapes(2) と同じなので、ShapeRangeは使わないでもよい ------------------------------------------------------ それから、 >AB.ShapeRange.Fill.ForeColor.SchemeColor = 10'(1)の2 >AB.Fill.ForeColor.SchemeColor = 10 '(2)の2 ActiveSheet.Shapes(AB.Name).Fill.ForeColor.SchemeColor = 10 とすれば問題はおこりませんが、コードがちょと綺麗じゃない?! 【結論】 選択された図形の書式プロパティを扱うときは、ShapeRangeコレクションを使う と単純に覚える。 以上です。
お礼
大師さま、お久しゅうございます。 わたしも選択しているか否かのせいではないかと思いました。 それで .Range("A1").Select'(1) をわざと書き加えたのです。 これでA1セルが選択されて図形の選択が解除されていますよね? ですから、選択か否かではなくTypeNameがShapeかRectangleかの違いなのではないでしょうか?もっともDuplicateすればShapeのままで、CopyしてPasteしたらRectangleに変わるというのもなぜかわからないのですが・・・・。
- pauNed
- ベストアンサー率74% (129/173)
こんにちは。 Selectメソッドで選択したObjectと、Selectionの内容は異なる事があります。 Sub try1() Dim A Dim B Set A = ActiveSheet.Shapes.AddShape(msoShape5pointStar, 100, 100, 100, 100) A.Select Set B = Selection MsgBox "A: " & TypeName(A) & vbLf & "B: " & TypeName(B) Stop Set A = Nothing Set B = Nothing End Sub Stop時、VBEのローカルウィンドウを表示し、変数A,Bに格納されたObjectの型を確認してください。 また、Selectionではなくとも、隠しObjectを使う事でも再現します。 (隠しObject...95以前のバージョンとの互換性を保持するためのもの) Sub try2() Dim A Dim B Set A = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 100, 100, 100, 100) Set B = ActiveSheet.Rectangles.Add(200, 200, 100, 100) MsgBox "A: " & TypeName(A) & vbLf & "B: " & TypeName(B) Stop Set A = Nothing Set B = Nothing End Sub 変数にVariant型を用いている事も要因のひとつです。 個人的には、きちんと変数宣言し明示して、Objectの型を意識したほうが良いと思います。 ただ、Selectionを用いると、型違いエラーが発生する事もあります。 Sub try3() Dim A As Object Dim B As Rectangle Dim C As Shape Set A = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 100, 100, 100, 100) A.Select Set B = Selection On Error Resume Next Set C = Selection 'エラー Stop Set C = A Stop Set A = Nothing Set B = Nothing Set C = Nothing End Sub Selection のような状況依存しないといけない時には..As Object を使う事もあります。 (上記例の Dim B As Rectangle...などは、あまり使わないとは思います)
お礼
有難うございます。 最初に生成された星型AAはTypeNameがShapeでした。 Duplicateで複製した星型ABは、オリジナルと同じくTypeNameがShapeでしたが、Copyで作成された星型ABはTypeNameがRectangleと、Typeが違うんですね! ここまでは理解できました。 では、ABが"Shape"であれば AB.Fill.ForeColor.SchemeColor = 10 でOKなのに ABが"Rectangle"なら AB.ShapeRange.Fill.ForeColor.SchemeColor = 10 と、"ShapeRange"というのを入れなければならないのはどうしてなのでしょうか? (実はShapeRangeというのが何なのか良くわかってないのです。)
お礼
> 変数への格納の仕方、 > Objectの指定の仕方が違う、 なるほど、同じ物でも Set A = .DrawingObjects(.DrawingObjects.Count) とすれば型はRectangleだし、 Set A = .Shapes(.Shapes.Count) とすれば型はShapeになりますね。 有難うございます。