プロが教える店舗&オフィスのセキュリティ対策術

Dim rng As Range, txtbox As Shape

Set rng = Range("A1")
Set txtbox = ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, 1, 1, 100, 30)
text.Name = rng + "d"

この場合最後の行で変数 rng は無視されてテキストボックスの名前は「d」となります。

text.Name = Range("A1") + "d"
とか
text.Name = Cells(1,1) + "d"
とすると
名前は「(A1の内容)d」
となります。

この違いってどういうものなのでしょう。Range型変数を用いて「(A1の内容)d」とすることはできないのでしょうか。


もう1点だけ。
変数の型について
https://www.moug.net/tech/exvba/0150065.html
にあるObject型というのは
あらゆる種類のオブジェクトを格納できる、オブジェクトに関してはVariant的な存在なのでしょうか。

A 回答 (4件)

txtbox.name は名前ですから、文字列型 string でないといけません。


rng は range 型ですから、そりゃダメですよ。
ところで、あなた + って書いてるけど & の間違い?


object 型は、変数の型の一種ですが、variant 型と違って、もっと厳密です。
テキストボックスや、チェックボックスや、グラフ、グラフの軸のような、実体を持った何かがオブジェクトであって、その固有 id が object 型の定数変数になります。例えば、あるグラフの id を、関数の引数として渡してあげたいような時に object 型の変数を使います。
    • good
    • 0
この回答へのお礼

text.Name = rng.value & "d"
としても無視される、なぜだ、これなら文字列の結合のはず
と思ったら
&が+になっていたというミスも重なっていたのですね。

先が思いやられる。


では例えばShape型はObject型より扱えるオブジェクトが限られているということですね。
どうもありがとうございました。

お礼日時:2019/04/19 00:02

こんにちは



既回答の通りなのですが、理解なさっていないようですので・・・

>text.Name = rng + "d"
多分、text ← txtbox、 + ← & の間違えと想定します。

まず、変数rngはRangeオブジェクトです。

>これなら文字列の結合のはず
オブジェクトなので、厳密に言えば文字列ではありません。
ただし、処理中にVBAのエンジンが値の文字列を参照してくれる場合があるので、誤解を生じているものと思われます。

例えば、ご提示のテキストボックス(txtbox)はshapeオブジェクトであって、内容のテキスト(文字列)と等価ではありませんよね?
オブジェクトの属性の一つとしてテキストの文字列を持ってはいますが、
 msgbox txtbox
として、内容の文字列が表示されるのを期待しても、エラーになるだけです。
 txtbox.Text
などとすることで、始めてそのテキストを参照することができます。

Rangeオブジェクトも同様で、内容の値は勿論、セル範囲・位置、表示書式、連結の状態等々の様々な情報を有しています。(なぜならRange「オブジェクト」だから)
ですので、値を参照したい時には、エンジンまかせにせずに、きちんと
 Range.Value
などのように明示的に記述するようにしておけば、間違えは少なくなることでしょう。


>オブジェクトに関してはVariant的な存在なのでしょうか。
オブジェクトはあくまでもオブジェクトです。
(オブジェクト型に数値等は代入できませんが、Variantは可能です。)
その意味では、Variantは型をあまり意識しなくても良いように作成された「お便利型」の変数と言えるかも知れません。(これが却って不便になるケースも存在すると思いますが)
https://docs.microsoft.com/ja-jp/office/vba/lang …
    • good
    • 1
この回答へのお礼

少し理解が進みました。
どうもありがとうございました。
でも

Dim rng As Range, txt As Shape
Set shp = ActiveSheet.Shapes("Picture 1")

Set rng = Range("A2")

txt.DrawingObject.Formula = "=A2"  ←この行

は動作
=がなくとも動作

text.DrawingObject.Formula = "=rng"
は動作せず

Integer型 i = 2として
text.DrawingObject.Formula = "A" & i
これも動作

text.DrawingObject.Formula = "=" & rng
これは動作せず

text.DrawingObject.Formula = rng
ついでにこれも動作せず

A2とrngは参照という点で等価な気がしますが、難しい。

お礼日時:2019/04/20 00:05

もしかしたら、親オブジェクト(モジュール)についてミスしているかもしれません。



① Set rng = Range("A1")
② Set txtbox = ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, 1, 1, 100, 30)
片方には、ActiveSheet を入れて、もう片方には入れていません。
それで、同じ所を指しているだろうか、ということです。もしかしたら、違う所を指しているのではないか、と思います。これが成立するのは標準モジュールのみです。

>この場合最後の行で変数 rng は無視されてテキストボックスの名前は「d」となります。

text.Name = rng + "d"
これは、成立しています。無視されていません。

A1に値が入っていなければ、"d" になりますね。ところが、A1の親オブジェクトがわかっていないと、無視されているように思うかもしれません。そのコードは、まず「標準モジュール」に書くべきものだということです。

つまり、Rng の親は、ActiveSheet でなくてはならないけれども、そのモジュールをシートモジュールに書いてしまうと、Worksheets("Sheet1").Range("A1") とでもしないと、その書いたモジュールの親を示してしまいます。

厳密には、Excel.ThisWorkbook.Sheets("Sheet1").Range ("A1") とでもいうのですが、いくつか省略が可能だということです。[全部を書くのをコンテナー型といいます。それはいくつかは省略できるわけです。]

text.Name = rng + "d"
のプラス(+)については、VB6/VBAでは、「+」を文字結合に使ってはいけないという「暗黙のルール」があります。そうしないと、数値+数値の時は、計算してしまって、文字の時は、文字の連結ではややこしくてしょうがないからです。

また、Object型というのはのは、設計の段階で、いろんな要素(オブジェクト・プロパティ)を設けることです。それをまとめて、一体として存在を表しているものです。今回は、オブジェクトは、Shape を示しています。

オートシェイプのTextBox では、直接、TextやValueのプロパティがありません。VBAの入門でいきなり、そこで思うようにしたいと言っても、古いオブジェクトで、インテリセンスに出てこないプロパティについては、テキストをみるなり、改めて相談してください。

言い換えれば、TxtBox.Text も TxtBox.Value も、この場合はエラーになります。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。勉強になりました。

rng.valueが無視されていると思ったのは参照先のセルが空白だったからでした。
VBEとにらめっこしすぎてワークシートがお留守になっていました。お騒がせしました。

テキストボックスのプロパティが追加されてもいい気がしますね。

お礼日時:2019/04/20 00:03

No2です。



>A2とrngは参照という点で等価な気がしますが、難しい。
一方はオブジェクト、他方はセル位置を示す文字情報ですので、等価ではありません。
「Rangeはオブジェクトである」ということを忘れないでください。


>text.DrawingObject.Formula = "=rng" は動作せず
>text.DrawingObject.Formula = "=" & rng これは動作せず
>text.DrawingObject.Formula = rng ついでにこれも動作せず

いずれも関数式を設定するセンテンスで、右辺は関数式を意味する「文字列」である必要があります。
上記のうち、"=rng"は文字列ではありますが、そのまま "=rng"という意味になるので、関数式として理解されない可能性が高いです。
(エクセルはrngという名前の定義を探しますが、定義が見つからなければエラーになります)
その他は、オブジェクトを文字列であるかのように勘違いをしていると思われる記述になっていて、機械には解釈できない記述になっています。

なさりたいことは、Rangeオブジェクトが有しているセル位置の情報を文字列化した「A2」($A$2)を右辺に設定することではないでしょうか?
ですので、右辺を
 "=" & rng.Address
等とすることで、動作するようになると思います。
(rngオブジェクトが保持しているセル位置属性を明示的に示している)
    • good
    • 0
この回答へのお礼

>「Rangeはオブジェクトである」ということを忘れないでください。

ありがとうございます。
Range型の変数は他のオブジェクトと異なって、Range型を宣言した時点でセル参照のみを示している
つまりAddressプロパティなしでrng.Addressが持つ情報と同じものだと誤解していました。

前にも(それまでよりは)理解が進んだと記しましたが、No.2にて頂いたご回答の意味がまた少し理解できてきました。
ただ依然どこかに誤解が解消されていない気もします。1か所だけならまだしも複数潜在していると、試行錯誤でうまく動作するパターンを見つけて学習するという作業が飛躍的に難しくなってしまうのですよね。
こういう場合は外部が示す基礎基本に忠実に則った学習が効果を生むはずですが、理解できていないことを認識できていないと独学の重点的なターゲットになりにくいというのがネックです。
誤解している部分が多すぎて今後も学習が進みづらい予感がします。

そんな中にあって理解の深い方からのアドバイス、非常に助かりました。重ねてお礼申し上げます。

お礼日時:2019/04/21 08:08

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!