★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0030:ついでに、ウォッチウィンドウの「一般的に、普通に使う使い方」も少し-13。(エラー回避の基礎14)★ ウォッチウィンドウで「ActiveSheet.UsedRange」のセル範囲やオブジェクト変数「rrr」のセル範囲、マウスで選択したセル範囲を調べる方法と、それによって「何がわかるか?」「わかること」~その2。
バックナンバー目次ページは→こちらです。
まぐまぐのページは以下です。
https://www.mag2.com/m/0001691660.html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
Vol.0030
タイトル:ついでに、ウォッチウィンドウの「一般的に、普通に使う使い方」も少し-13。(エラー回避の基礎14)
★ ウォッチウィンドウで「ActiveSheet.UsedRange」のセル範囲やオブジェクト変数「rrr」のセル範囲、マウスで選択したセル範囲を調べる方法と、それによって「何がわかるか?」「わかること」。~その2
バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
今回も前回の続きです。
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01-26
における、
の図の状態にしておいてください。
「Let ggg = ActiveSheet.UsedRange」と、
「Set rrr = ActiveSheet.UsedRange」の2行が
追記された状態となります。
もちろん、
「Sheet1」には、AとBの列に、
下図のようにセルに値が入っているようにしておいてください。
そして、F5キーを押して、
Stop
の行が黄色くなった状態にしておいてください。
で、前回は、
「Activesheet.UsedRange」をいちいち配列変数に代入しなくても、
また、
「Activesheet.UsedRange」をオブジェクト変数に代入したり、
逆に、何もしなかったりでも、
「Activesheet.UsedRange」という「式」のまま、
「Activesheet.UsedRange」という「記述」だけを使って、
セル範囲のセル番地(アドレス)をイミディエイトウィンドウで「直接的に」確認できる(その他諸々も確認可能)・・・
・・・ということについてやりました。
今回は
同じく「Activesheet.UsedRange」を配列変数に代入しなくても、
また、
オブジェクト変数に代入しても/しなくても、
「Activesheet.UsedRange」という「式」のまま、
「Activesheet.UsedRange」という「記述」だけを使って、
セル範囲の実際の「セルの入力値」を、
『 ウォッチウィンドウ(ローカルウィンドウも同じ)のほうでも 』
確認できる(その他諸々も確認)・・・
というコトのほうをやりたいと思います。
そしてそれによって、セル範囲のセル番地を「間接的に」推定する(割り出す)・・・、
ということをやります。
前回は、
(01)「Activesheet.UsedRange」のセル範囲を、イミディエイトウィンドウにて、
「セル範囲のアドレスを出力する(=表示させる)」
ということで、
「Activesheet.UsedRange」などのセル範囲が
・実際に(=現実には)どのような範囲になっているのか?
・ちゃんと巷で言われているとおりに(=ヘルプや市販書籍やWeb情報通りに)なっているか?
などなど・・・
ということを「直接的に」調べました。
そして、(あくまでも「一例として」ですが)、
例えば、「Range.CurrentRegion」についても同じやり方で調べられる・・・ということもやりました。
今回は、
(02)「Activesheet.UsedRange」を、ウォッチウィンドウにて、
「その ”実際の入力値 ”を確認する(=表示させる)」・・・、
ということによって、
「Activesheet.UsedRange」のセル範囲が
・実際に(=現実には)どのような範囲になっているのか?
・ちゃんと巷で言われているとおりに(=ヘルプや市販書籍やWeb情報通りに)なっているか?
などなど・・・
ということを「間接的に」「推定する」、「調べる」・・・、
・・・・そういう実験してみたいと思います。
これは今回の「Activesheet.UsedRange」(つまりは「Worksheet.UsedRangeプロパティ」)という文言で直接調べるやりかた以外にも・・・、
Setステートメントで「Activesheet.UsedRange」をオブジェクト変数に代入した時の、その「オブジェクト変数」の側(=左辺)でも同じ方法で調べられます。
(ウォッチウィンドウかローカルウィンドウのいずれかで調べられます。)
ですので、今回のことも、ぜひ覚えておいてほしいと思います。
※参考
以下の図も参考にしてみてください。
例えば Rangeオブジェクトの取得の場合、どういったプロパティなどが使われるか、の「イメージ」の図です。
あくまでも「イメージ」ですが、下図の「正規ルート」と「ワープルート」の違いなどを良く見てみてください。
「正規ルート」では普通の原則的なセル範囲(A1形式のセル範囲)が取得でき、
「ワープルート」では、「少し便利なかたち(性格が異なったかたち。R1C1形式や使用された部分のみ、数個ずらした、等々)でのセル範囲が取得できます。
(※「ワープルート」=下の図で言うと、オレンジの点線矢印でのRangeオブジェクトのゲット=アクセスのルートのことです。)
※各コレクションオブジェクトの「Item」という名前のプロパティやメソッドは基本、省略されることがほとんどです。(後述)
ただ、「VBAは省略しない方が上達します」。
あと、一口に、例えば「Cells」プロパティと言っても、Application.Cellsもあれば、Worksheet.CellsやRange.Cellsもあって、「それぞれに「微妙に動きが異なる」ので、「親となるオブジェクトとセットで」、「どのCells」オブジェクトなのか、を明確に指定する必要があります。それは「Cells」に限らず、他のプロパティでも同じことが言えます。
(例えば上図だと「Application.Selection」や「Window.Selection」、各種「Item」がそれにあたります。)
なので上図では、その意味で、「親となるオブジェクト」の名前もくっつけた状態で説明してあります。
「ヘルプ(特に2007以降)」や「オブジェクトブラウザ」もこの形式を守っていますので、逆に、このことを知らないと、「ヘルプ」や「オブジェクトブラウザ」が読めません。
ご注意ください。
ではまず結論から言いますと・・・、
「ある1つのオブジェクトについて、その何かを ”ウォッチウィンドウ ”で調べる際は」、
「+」マークを展開してツリー状になった、そのオブジェクトの「各種プロパティたち」で、
調べることが可能です。
(※プログラムが終了するまでの間なら=F8キーでのステップ実行中の間なら、調べられます。)
今回は、指定したセル範囲(今回の例なら「Activesheet.UsedRange」というオブジェクト)の「実際の入力値」を調べますので、そのオブジェクトの「入力値」に関係する「各種プロパティたち」によって、
・このオブジェクトは、実際には(=現実には)どのような入力値やセルの並びになってるんだろう?
ひいてはどんなセル範囲になってるんだろう・・・?
とか、
・あ!ちゃんとヘルプや市販書籍やWeb情報の言う通りになってたわ!
といったことなどが分かります。
※補足
なお(前号にも書きましたが)、「セル範囲」というオブジェクトの何かを調べる場合、イミディエイトウィンドウでは、例えば「セル番地」を調べるのには便利です。
ローカルウィンドウやウォッチウィンドウではセル番地は「直接的には」調べられないのですが、イミディエイトは「直接的に」ラクに調べられます。
ただし、確かに、セル番地(セル範囲のセルアドレス)を調べる場合はイミディエイトが便利なのですが、逆に、セル範囲の「実際の入力値」を調べるには、これまでにお示ししてきたような感じで、ローカル、ウォッチ、のほうがわかりやすいです(イミディエイトでも一応調べられますがかなり手間・面倒くさいです。特に一覧形式で調べたいときは、いちいち専用のループプログラムを作らないと調べられなかったりします)。
総じてVBEの画面で「何かを調べるとき」には、、イミディエイト、ローカル、ウォッチ、のどれがいいかは、調べるモノによって替わります。
なお、ウォッチウィンドウにてセル範囲を調べたいときに、
直接セル範囲を調べるかわりに、いちいち
『 指定したセル範囲の「実際の入力値」を調べる 』理由は、
「ウォッチウィンドウでは、イミディエイトウィンドウのように、セル番地を直接調べることができないから」、
です。(詳しいことは後述。)
なぜウォッチウィンドウで、
「セル番地を直接調べることができない」かというと、
ウォッチウィンドウの場合、
「+」マークを展開しても、
セル番地を表す「Address プロパティ」そのものが「表示されない」から、です。
本当は「表示されないといけない」はずなのに、表示されません。
(「Address プロパティ」が「引数」というものを持ってしまっているためです。)
だからです。(もっと詳しい理由は、この号のさらに巻末で後述します。)
ただ、
「入力値がシート上にどのように入力されているか?」、とか、
「その実際の値と、値が入力されたすべてのセルの並びの状態」だけ、は、
ウォッチウィンドウでもわかります。
なので、それを調べることで、「セル範囲」を調べる「代用」とするわけです。
基本的にはほとんどのケースで、イミディエイトウィンドウにて、
「? Activesheet.UsedRange.Address」と書いてEnterしちゃったほうが早いです。
なんですが、
ただ、
「アドレス(セル番地)だけじゃなくて、
実際の入力値やその他のこと(配列になった場合その要素番号など)も調べたい」
というときは、
イミディエイトだと「一覧ができずにかえって不便」なため、
ウォッチウィンドウを使うこともあります。
ウォッチウィンドウではセルの入力値と並びの「一覧」ができますので・・・。
(ローカルウィンドウでも「ひと手間」はかかりますが、同じように「一覧」が可能です。)
その際、セル範囲も「疑似的・代用的にわかる」ので、
またそこからも
「ヒントをもらえる」とか、
「エラーが速く解決できる場合もある」
というわけです。
なので、セル範囲を調べる方法としては、
「イミディエイトで調べる方法だけじゃなくて」、
ウォッチウィンドウで(疑似的に)セル範囲を調べる方法も
知っておくといいと思います。
これは、「セル範囲以外のこと」でも同様です。
イミディエイトとウォッチウィンドウ、両方で調べられるとVBAの腕が上がりやすいです。
では、早速、見ていきましょう。
まず、
ウォッチウィンドウの「Activesheet.UsedRange」の「+」マークをクリックして、ツリーを展開します。下図のようになります。
とりあえずセルの入力値、といえば・・・・
普通は「Range.Value プロパティ」なので、この「Activesheet.UsedRange」のツリーを下にスクロールして「Value」というモノを探します。
でも・・・
あれ・・・・?
無いですね。
「Value」プロパティ。
無きゃいけないはずなのに・・・・。
(「Value2」って、「2」が付いたヤツはありますけど・・・)
「U」の次は
「V」なので、その「V」の最初の方に「Value」が無いとおかしいんですが・・・
これはですね・・・
もしかしたら、これまでにも何度か書いてきたので、理由はお分かりの方もいらっしゃるかもしれませんね。
これは、
『 ウォッチウィンドウの「+」のツリーの中には、
「引数を持つプロパティは表示されない」 』
という決まりがあるからです。
(※そのほかの決まりもあるかも?です。ウォッチウィンドウの「+」のツリーの中に表示されないモノの ”決まり ”は コレだけじゃないかもしれません。)
そして「Range.Value」プロパティは「引数を持つプロパティ」なのです。
なので、「Value」が見当たらないのです。
(「Value2」プロパティは「引数」と呼ばれるモノを持ってないので表示されています。)
まず、「引数」とは、言ってみれば「 ”設定値 ”みたいなもの」です。
で、実は「Value」プロパティには、その「引数と呼ばれる設定値みたいなもの」が存在します。
ヘルプを見ると書いてあるんですが、「Value」プロパティの「引数」は、
「RangeValueDataType 列挙」
というヤツです。
で、
「RangeValueDataType 列挙」の中には、
・「xlRangeValueDefault」と
・「xlRangeValueMSPersistXML」と
・「xlRangeValueXMLSpreadsheet」という
3つの引数の値、が含まれています。
(※列挙の中に含まれる各値たちを、「定数」とか「組込定数」などと呼びます。)
本来ならその「引数」というモノ(この場合は上記の3つのどれか)も、コードを書くときは必要=書かねばならん・・・、なのですが、
Valueプロパティの引数の場合は、
「省略オッケーだよ!」
ということになっているので、一般的には書きません。
(※このほか、多くのプロパティで「省略オッケー」になっています。悪しき慣習です。でも確かに書くの面倒くさいので、もしエラーが出たときは「引数が省略されてないか?」を先に調べたほうが速く解決できる場合もあります。その際は「ヘルプ」じゃないと分からない場合が多いです。)
ちなみにですが、Valueプロパティの場合は、
引数の「RangeValueDataType 列挙」を省略しない場合であれば、
例えば『 アクティブシートのA1セル 』を表すコードは、
例えば、以下のようなコードの書き方になります。
ActiveSheet.Range("A1").Value(xlRangeValueDefault)
※ちなみにですが、引数を省略すると、「この既定の値の xlRangeValueDefault が指定された」と自動的にみなされます。
そのような、「省略しても自動的にピックアップ+使用される引数の値」を、「引数の既定値」、などと呼んだりします。
「Value」プロパティの場合は、「xlRangeValueDefault」が「既定値」ということになります。
今回の事例の場合、実際のワークシートの「A1セル」には「a」という値が入力されているので
イミディエイトにて、
? ActiveSheet.Range("A1").Value(xlRangeValueDefault)
って書いてEnterすると、
「a」
という答えが返ってきます。
? ActiveSheet.Range("A1").Value
とか
? ActiveSheet.Range("A1")
って書いてEnterしたときと同じですね。
で、さらにちなみにですが、
同じくイミディエイトにて、Value プロパティの引数に、今度は
「xlRangeValueDefault」ではなくて、
「xlRangeValueXMLSpreadsheet」を指定して、
? ActiveSheet.Range("A1").Value(xlRangeValueXMLSpreadsheet)
と書いてEnterすると、以下のような複数行のXMLタグ入りの答えが返ってきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
' ' <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="Yu Gothic" x:CharSet="128" x:Family="Modern" ss:Size="11" ss:Color="#000000"/> <Interior/> <NumberFormat/> <Protection/> </Style> </Styles> <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="18.75"> <Row> <Cell><Data ss:Type="String">a</Data></Cell> </Row> </Table> </Worksheet> </Workbook> ' ' |
※ ↑ちなみにこれをテキストファイルにコピペして、「.xml」という拡張子を付けて開くと、
Excelが起動して、A1セルに「a」と入力された状態で開きます。
(Windows10+Excel2019の場合)
この量!
ビックリ!
「a」とは程遠いですね。単純な値ではありませんね。
よ~く見てみると、下の方の
『
というところに、入力値の「a」と「型」? のことが書かれていますね。
ワークシート(シート名など)のことなども書いてあるし・・・。
すごく詳しい情報・・・。
いずれにしましても、とにかくこのように、
「Value」プロパティには「引数」というものが存在します。
だから、
ウォッチウィンドウの「+」のツリーの中には、
「Value」という名前のプロパティが見えなくなってしまっています。
『 ウォッチウィンドウの「+」のツリーの中には「引数を持つプロパティは表示されない」』、
という決まりがあるわけですから。
(※繰り返しますが「Value2」プロパティには引数はありません。)
なお、プロパティに「引数」が存在するかどうか?は、ヘルプを見ると一番よく分かります。
引数の値のことまで書いてあります。
そのほか、プロパティのあとに、「(」(カッコ)を書くと、その瞬間に、引数名がポップアップされる場合もあります。(ただし、絶対にポップアップされるというわけではありません。なので、ヘルプの方が確実ではあります。)
ちなみに、メソッドの「引数」場合は、オブジェクトブラウザでも引数の「有無」が分かります。
プロパティの「引数」の場合はオブジェクトブラウザでは「有無」は分かりません。
※★★★
『 でも、じゃあさ、なんで「引数を持っているプロパティ」は、
ウォッチウィンドウの「+」のツリーの中に出てこなくなっちゃうの?
その理由は何? 』
ということについては、この号の最後・巻末で少しお話させて頂きます。
・・・・というわけで、いきなり前置きが長くなってすみません。
なら、
一番頼りにしたい「Value」プロパティで「Activesheet.UsedRange」の入力値が調べられないなら、
ウォッチウィンドウでは、それをどのプロパティで調べたらよいのでしょうか?
その答は・・・・。
もうあとは一気に、「僕の知ってるだけ」ですみませんけど、なるべく多く、答えを言いますね。
ウォッチウィンドウでは、以下のプロパティで、現在のセル範囲の入力値を調べられます。
(実際に「+」のツリーの中を調べるときは下記の「Range」は省いて各プロパティを探してください。)
「Range.Value2 プロパティ」
「Range.Formula プロパティ」
「Range.FormulaLocal プロパティ」
「Range.FormulaR1C1 プロパティ」
「Range.FormulaR1C1Local プロパティ」
以上は「複数セル」のセル範囲の場合、ですが、単一のセルとしてのセル範囲の場合なら、
「Range.Text プロパティ」
もそうです。
あと、
「Range.CurrentRegion プロパティ」の「+」を展開した中の、上記のプロパティすべて。
も、そうです。
他にもまだまだあるかもしれませんが、パッと目につくところはそのあたりです。
※補足
「Range.Value2」は日付セルの「シリアル値」というものをゲットするのに便利です。
(また、数式が入っているセルでも数式ではなく「答えの数値」が分かります。)
「Text」プロパティはセルの入力値を「数値として」ではなく、セル書式設定(\マークや/記号やカンマ記号など)が反映された「テキスト表示のまま」としてゲットするのに便利です。
日付セルの「シリアル値」は、「Range.Value」プロパティの値に「×1」してもいいのですが、「Range.Value2」プロパティのほうがそんなことしなくても「直接取得」できるので便利です。多分ほんのほんの少し・動作も速い気がしますし。
また、セル書式設定(\マークや/記号やカンマ記号など)が反映された「テキスト表示」を直接ゲットしたいときは、「Text」プロパティが便利です。なぜか「セル範囲」のときはウォッチウィンドウに出てきませんけど。表示が遅くなっちゃうからヤメ、ということなのかしら?
わかんないですけど。単一のセルの時はウォッチウィンドウに表示されます。
では、実際に、上記の各種プロパティで、入力値とセルの並びを見ていきましょう。
まずは「Range.Value2 プロパティ」です。
まずは「Activesheet.UsedRange」の「+」マークをクリックして展開します。(下図)
そのあと、それをした方~にスクロールして、「Value2」という箇所を探します。
見つかったらそこの「+」マークも展開します。(下図赤枠)
あれ?・・・・?
するとこれ・・・・
どっかで見た感じと同じですね・・・・。
そうです。
以前の
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01-27
の号の、
の図とそっくりじゃありませんか?
「Value2」と「ggg」が違うだけで・・・。
以前の号のときは、「ggg」というオブジェクト変数に「Activesheet.UsedRange」を代入したモノ、つまり、左辺の、変数の「ggg」の「中身」を見ていました。
そして、あのときは最終的にすべての「+」を展開すると以下のようになりました。(下図)
さらに、実際のシートと見比べてみると、以下のようになっていました。
あの時ととても似ているのかもしれません。
早速、今回の「Value2」プロパティのすべての「+」を展開してみましょう。下図のようになります。
繰り返しになりますが、「Value2」と「ggg」が違うだけで、実際の値の列については
値の列にも「a」や「b」など、列名の部分の入力値 が並んでいます。
値の並びについても「1、4」「2、5」「3、6」と同じです。
ということは・・・・・
あの時はVariant型の配列変数「ggg」に、セル範囲をムリヤリ代入したら、
勝手に「配列変数」に変身したんでした。
ということは、この「Value2」も「Variant型の配列なのかな?」と、なんとなく想像がつきませんか?
まずは、「Value2」のヘルプを読んでみると・・・
『 セルの値を設定します。値の取得および設定が可能です。バリアント型 (Variant) の値を使用します。 』
と書いてあります。
『 バリアント型 (Variant) の値を使用します。 』
と書かれていることから、
「あ!やっぱりVariant型の配列なのかな!?」と、「推測」に少し確信めいたものが加わります。
で、
「Value2」の「+」マークの右のほう、「型」の列を見ると、
Variant/Variant(1 to 4, 1 to 2)
と表示されています。
「ggg」の時と同じですね。
「ggg」の時も、「型」の列に
Variant/Variant(1 to 4, 1 to 2)
と表示されていました。
ここで、ウォッチウィンドウに表示されている
『 Variant/Variant(1 to 4, 1 to 2) 』とは、
『 Variant型の変数で、内部的にはVariant型の4行×2列の配列変数に自動変換してあります 』
というような意味ですので、
ヘルプに書いてある、
『 バリアント型 (Variant) の値を使用します。 』
は、納得できます。
以上のことから、「Value2」も「Variant型の配列」ということで間違いなさそうです。
(あくまでも「2つ以上のセルを持った」「セル範囲」の場合のみ。1つだけのセルについて調べた場合は、また話は別になります。配列にはなりません。)
※補足
『 もしかしたら、Variant型の変数の「ggg」には、「Value2」プロパティの値が代入されたのかもしれない・・・ 』と思ってしまうかもしれませんが、それは違うかも?です。
ActiveSheet.UsedRangeに限らず、セル範囲が単一のセルじゃなくて「複数のセルが集まったモノ」のときは、通常の「Value」プロパティのほうも配列になるようですので。
その確認は、イミディエイトで「 ? TypeName(ActiveSheet.UsedRange.Value) と書いてEnterすると、「 Variant() 」と「カッコ」が余計にくっついて出てくるので、それで確認できます。
「TypeName関数」の戻り値に、カッコが余計にくっつくのは「配列だ」という意味になりますので。
今回も、
「Stop」の行の2行前で、
「Let ggg = ActiveSheet.UsedRange」
を実行していますので、
「ggg」にはすでに、「Activesheet.UsedRange」のセル範囲の値たちが代入されています。
いろいろと確認してみるといいと思います。
ちなみにですが、イミディエイトにて「Value2」ではなくて、「Value」を使って、また、プロパティの引数を既定の引数じゃないものに変えて、
? Activesheet.UsedRange.Value(xlRangeValueXMLSpreadsheet)
と書いてEnterしたら、その戻り値の終りの方に、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
' ' <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="4" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="18.75"> <Row> <Cell><Data ss:Type="String">a</Data></Cell> <Cell><Data ss:Type="String">b</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">1</Data></Cell> <Cell><Data ss:Type="Number">4</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">2</Data></Cell> <Cell><Data ss:Type="Number">5</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">3</Data></Cell> <Cell><Data ss:Type="Number">6</Data></Cell> </Row> </Table> </Worksheet> ' ' |
と出て返ってきます。
コレでも、配列の内容と各値の型ががわかりますね。
(せまいセル範囲なら、ですが。「ss:Type=」のところが「型」のようです。)
以前のどこかの号のイミディエイトのところの説明で、これを忘れてました。
すみません。
※補足:↑上記のXMLコードのカットした部分を、カットせずにテキストファイルにコピぺしたのち、
「.xml」拡張子を付けて開くと、Excelが起動して、
A1セル~B4セルがこれらの値で埋まった状態で開きます。 (Windows10+Excel2019の場合)
★ それで、「Activesheet.UsedRange.Value」が、単一のセルじゃなくても、
「複数のセルが集まった表構造であっても」、
「確実に」その表の内容・構造、がわかります。
つまり、「Value」プロパティの中身が、「Excelファイルになって表現される」ので
「超・明確」になります。
逆に言うと、
「×××.Value(xlRangeValueXMLSpreadsheet)」の結果を
クリップボードに送る仕組みを作れば、
結構大きな表であっても、その表のセル番地や値が、
「Valueプロパティの中身」として、
「Excelファイルで表現・確認・一目瞭然に」できると思います。
以上のことから、
「Value2」にて「 Activesheet.UsedRange 」の内容のセル範囲が、
イミディエイトを実行しなくてもウォッチウィンドウだけでも、
ウォッチウィンドウの『「型」の列の Variant/Variant(1 to 4, 1 to 2) という表示その他』などによって、
「行が4行、列が2行」
あるいは
「行は1~4行目まで、列は1~2列目まで」
のセル範囲に、値が入力されていることがわかりました。
結果、
A1セル ~ B4セルまで、
つまり「A1:B4」というセル範囲なのだな、ということが分かります。
なお、列番号について、数字によって列のアルファベットを調べたいときは、イミディエイトウィンドウで
? Cells(1, 列の数字).Address
と書いてEnterすると、アルファベットがわかります。
(どのシートでやっても一緒なので、「Activesheet.」は付けなくても一応OKです。
それに「Activesheet.」を省略しても、自動的に「Activesheet.扱い」になる決まりに
なっているため。)
※なお、ここでイミディエイトを使うのは今回の「ウォッチウィンドウだけで」
という目的からすると「反則」のような気もしますが、、、
でもまあ、
『 Variant/Variant(1 to 4, 1 to 2) 』
によって
「2列目まで使ってる」ということが「ウォッチウィンドウだけで」でも
確定したので、
=分かったので、「まあいっか!」ということでお許しください。
例えば今回の事例なら、
『 Variant/Variant(1 to 4, 1 to 2) 』ということですので、
『 行は4行目まで、列は2列目まで 』ということですから、
「 ? Cells(1, 列の数字).Address 」
の
「列の数字」の部分に「2」を書きます。
なので、イミディエイトには
? Cells(1, 2).Address
と書いてEnterします。
結果、「$B$1」と返ってきますので、「あ、B列だな」とわかります。
※「 1 to 2」の「1」は「A列の事をさします。
結果、
『 Variant/Variant(1 to 4, 1 to 2) 』
は
『 Variant/Variant(1行目 から 4 行目まで, A列 から B列まで) 』
という意味になる・・・・
ということがわかります。
「Value2」プロパティとウォッチウィンドウだけでのセル範囲の「セル番地」の調査は、以上でおわりです。
ゴチャゴチャ書きすぎて、「逆に意味がわからん!」とお怒りの方もいらっしゃるとは思いますが、もしそうならごめんなさい。
でも、部分部分に切り取って、読んでみても何らかのヒントくらいにはなると思いますので、どうかお許しください。
では次に「Range.Formula プロパティ」とウォッチウィンドウだけで、セル範囲を調査してみたいと思います。
・・・・と、思いましたが、ここで、
「長い補足」をしたいので、
これは次回に持ち越したいと思います。
すみません。
補足は、
『 市販書籍やWeb記事では、イミディエイトウィンドウの事ばっかり解説して「ウォッチウィンドウを解説しない(実際にはイミディエイトすらもほんの少し)。これも初心者がいつまでたっても上達できない仕組みのひとつ。』
ということと、
『 じゃあ、なんで、「引数を持っているプロパティ」は、
ウォッチウィンドウの「+」のツリーの中に出てこないの?
その理由は何? 』
ということについて補足します。(両方ともほとんど愚痴ですけど・・・)
今のVBA教育業界の悪習や、VBAの構造的なことでの重要なヒントにもなると思いますので、(意味不明かもしれませんが)、是非、お読みになってください。
意味不明でも、
「いかにVBA教育業界が”肝心なこと”を教えてくれないかの気づきのヒント」
「上達のためのヒント」
にはなると思います。
==============================
==============================
●『 市販書籍やWeb記事では、イミディエイトウィンドウの事ばっかり解説して「ウォッチウィンドウを解説しない(実際にはイミディエイトすらもほんの少し)。これも初心者がいつまでたっても上達できない仕組みのひとつ。』
初心者の方々の腕が上がらない、中級に行けない、必ず初級で挫折する、
その理由に、「イミディエイトの事しか教えない」、ということがあります。
(現実には、イミディエイトのことさえ教えてませんが・・・。)
市販書籍やWeb記事では、デバッグ(エラー回避)の方法について、
イミディエイトウィンドウの事ばっかり解説していて、
「ウォッチウィンドウのことをこれっぽっちもやりません」。
でも、逆に言うと、
「ウォッチウィンドウをまったく解説しない」から、
『 初心者がいつまでたっても腕が上がらない 』
のです。
本当に即物的な教え方しかしないダメ教習といいますか・・・
そもそも「ウォッチウィンドウを解説しない」ということは、
「式」や「ステートメント」や「評価」「返す」「型」「式と評価と値と型の関係」などの意味、
つまり、「VBAにおいて重要な基礎のこと」の説明すらしてないはずですから、
それで
「初心者は自動的にバカになる」
という悲しい結果になってしまいます。
もっと言うと、
「初心者をバカにさせてる(=核心を隠したほうが長くカモれるからカモってる)」と
疑われる可能性も低くないです。
そういうつもりは無かったとしても、そう疑われても言い返せないと思います。
「20年以上」、
「誰も」、
「ウォッチウィンドウやヘルプやオブジェクトブラウザのちゃんとした読み方の本」を、
「一冊も出版してこなかった」、
そういう業界ですから・・・。
そして、未だに、
イミディエイトのことすら解説しない市販書籍、あるいは、
「ぜったいにやっとけ」という風に「道筋を示すことすらもしない」市販書籍も、
メッチャ多いので呆れますが・・・。
Exxcelに限らず、すべてのOfficeソフトのVBAにおいて、
『 Webや市販書籍に書いてないことでも、自分で調べてコードが書ける書けないか? 』は、
あきらかに、
「 オブジェクトモデルの階層構造一覧図 」の理解と
「 ウォッチウィンドウ 」の使用頻度
に
「正比例」
します。
その2つこそが、「ヘルプやオブジェクトブラウザの解読・理解」にもとても役に立つからです。
ただ、本当の「真実」は少し違ってて、
「Exxcelに限らず、すべてのOfficeソフトのVBAにおいて」、
『 Webや市販書籍に書いてないことでも、自分で調べてコードが書ける書けないか? 』は、
あきらかに、
「 オブジェクトモデルの階層構造一覧図 」の理解と
「 ★ クラスモジュールの理解とその自作の頻度 」
に
「正比例」
します・・・・・です。
VBAは、ExcelVBAだろうが、AccessやWordのVBAだろうが、
「 ★ クラスモジュール 」が理解できていなければ、
「 VBAの本当のこと・本当のところ 」はまるで理解できません。
「オブジェクトモデル(階層構造の一覧図)とクラスモジュール こそが 」、
VBAの「本当の基礎」です。
でも、初心者にはいきなり
「 ★ クラスモジュールの理解と自作の頻度を増やす 」
ということはムリなので、
そうなれるまでに、その代替として、
「 オブジェクトモデルの階層構造一覧図 」の理解と
「 ウォッチウィンドウ 」の使用頻度
を頑張ると、
VBAの腕が上がりやすいです。
「 ★ クラスモジュールの理解 」の段階にも、少しでも早く進みやすいですし、その段階に入ってからも、「自力で」色々とやれる場面も増えてきます。
結果、
「 オブジェクトモデルの階層構造一覧図の理解 」と
「 ウォッチウィンドウの使用頻度を増やして色々調べること 」
を繰り返しやれば(少なくとも1000回以上は)、
いつかなからず
『 Webや市販書籍に書いてないことでも、自分で調べてコードが書ける 』時が来ると思いますが、
それをやらなければ、
『 Webや市販書籍に書かれていないことでも、自分で調べてコードが書ける 』
という状態には、
「いつまでたっても」
「なれない」
と思います。
「あ、なるほど!」
「そういうことだったのか!」と、
「ハラ落ちする」・・・、
そういう瞬間は、
「永遠にやって来ない」、
と思います。
なのに、
「 オブジェクトモデルの階層構造一覧図の解説本 」や
「 ウォッチウィンドウの解説本 」なんて
「皆無」
ですよね。
どう見ても、初心者が無知なのをいいことに、「カモッている」としか見えません。
しかも「 オブジェクトモデルの階層構造一覧図の解説 」や「 ウォッチウィンドウの操作と解説 」といった基本をわざと教えないでおけば、表面的、即物的なことだけを教えておけばよくなり、
「永遠にカモり続ける」
ことができます。
ヒドイ業界ですよね~。
Excelが出た20年以上も前から、まるで変わっていません。
低レベルな基礎ばかり教えて、というか、それしか教えなくせに、お金を取る業界です。
そしてオブジェクトブラウザやウォッチウィンドウを扱えない生徒さんを量産して、
「応用ができない」「Webサンプルのコピペしかできない」
「Webに書いてないことだと全くわからなくなる・自分でヘルプで調べて自力でやれない」
という生徒さんを量産しています。
20年以上も前から、ExcelVBAがほぼ完成された形で「ある」のですから、
少なくとも今は、
「 VBAの本当の基礎とは、クラスモジュールである 」という教室が「ほとんど」というか、
「常識」
でなければいけなかったはずなのです。
でもそうなっていません。
ExcelVBA教育業界の怠慢、悪習、だと思います。
そのため、Excelは結局「活用」されていません。
何やってたんだ?あんたら?20年以上も?という感じです。
僕も今もまだExcel初心者ですが、騙されてました。
(Vlookup関数なんてほとんど使ったことがないです。)
最近、VBAの基本がわかってきたので、
本当のことがわかってくると、
「何やってたんだ?あんたら?20年以上も?」という思いがすごく強くなってきます。
ああ、また話が逸れてしまいました。
ごめんなさい。
==============================
==============================
●ウォッチウィンドウにて、
『 じゃあ、なんで、「引数を持っているプロパティ」は、
ウォッチウィンドウの「+」のツリーの中に出てこないの?
その理由は何? 』
本文で
『「引数を持っているプロパティ」はウォッチウィンドウの「+」マークを展開した中には表示されない決まり 』
と書きました。
ここでは、
『 じゃあ、なんで、「引数を持っているプロパティ」は、
ウォッチウィンドウの「+」のツリーの中に出てこないの?
その理由は何? 』
ということについて、僕の「推測」をお話ししたいと思います。
ヒントは、
『 引数を指定したときに返される「値」にある・・・ 』
と僕は勝手にそう思っています。
例えば今号でも扱った「Value」プロパティが持つ引数の場合で考えてみます・・・・、
例えばシートの「A1」セルに「a」と入力してから、イミディエイトで、
? ActiveSheet.Range("A1").Value
って引数を省略して書くか、あるいは
? ActiveSheet.Range("A1").Value(xlRangeValueDefault)
と、デフォルト=既定の引数を省略せずに書いてEnterすれば、
「a」という『 セルの入力値 』が戻り値になります。
が、
? ActiveSheet.Range("A1").Value(xlRangeValueXMLSpreadsheet)
と、既定の引数じゃない、「別の引数」を指定してEnterした場合は、以下のように
『 長―い「XML」タグが含まれてた複数行の答え 』が戻り値になってしまいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
' ' <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="Yu Gothic" x:CharSet="128" x:Family="Modern" ss:Size="11" ss:Color="#000000"/> <Interior/> <NumberFormat/> <Protection/> </Style> </Styles> <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="18.75"> <Row> <Cell><Data ss:Type="String">a</Data></Cell> </Row> </Table> </Worksheet> </Workbook> ' ' |
↑ちなみにこれをテキストファイルにコピペして、xmlという拡張子を付けて開くと、Excelが起動して、A1セルに「a」と入力された状態で開きます。(Windows10+Excel2019の場合)
と、それがヒントになっています。
そのことから、僕は次のように勝手に解釈しています。
「ウィッチウィンドウ」を擬人化して、その目線・立場になって考えてみれば・・・、
「あんたValueプロパティの引数を指定してくれんからさぁ~、
単純にA1セルの入力値を返したらいいのか、
それとも上記のようなXMLの答えを返したらいいのか、
俺にはわからんのだけど。
どーせ、はっきりしてくれんだろうから最初ッから何も返さないよ!
それに、どーせ、ウォッチウィンドウの狭いスペースじゃ、
”値”の列に、複数行の答えなんか表示できんしね!
もしXMLの内容が100万文字とかになったら俺自身がぶっ壊れちまう!」
・・・という風に言いたいだろうな・・・そりゃ言いたくもなるわなぁ・・・と、
そんな感じでしょうか。
これはつまり、
「引数が在るプロパティの場合」は、
「引数を指定してくれないと」、
「値の返しようが無いよね?」
ということだと思います。
「ウィッチウィンドウ」を擬人化して、その目線・立場になって考えてみれば。
「もちろん、引数の各値に対応したValueの戻り値を確定・表示することも不可能ではないけれども」
「でもそこまでやると膨大な量のデータを扱わないといけなくなるので、ウォッチウィンドウではもうそこまではやんない」
「どうしてもそこまで詳しく知りたい・調べたいならイミディエイト使って!」
ということもあるのかもしれません。
(イミディエイトでなら 引数の細かい値を設定しても、ちゃんと戻り値が確定し、返ってくるわけですから。100万文字はムリでも、1万文字くらいなら返してもらっても全然問題ないでしょうし。)
わかりませんが・・・。
「推測」なので・・・・。
ちょっとうまく説明できませんけど、でもまあ、そういうイメージ(解釈)でいいと思っています。
以上のような理由から、
以上のような感じだから、
だから
ウォッチウィンドウの「+」のツリーの中には、
ウォッチウィンドウの「+」のツリーの中に出てこない、
ということになるんだと思います。
ウォッチウィンドウの「+」のツリーの中に出しようがない
「値を」
「返しようが無い」
ということなんだと思います。
戻り値の「型」自体は、引数を指定してもしなくても(今回の「a」の場合は)「String」型なんだろうけど、
でも引数を指定しないと、「a」を返せばいいのか、それとも「XMLの長文」を返せばいいのか、とにかく「値が決まらない」というわけです。
すこし形式的??にまとめますと・・・、
(イ)「引数を持つプロパティ」の戻り値は、
「型」は決まるけれども、「値」が前述のように特定できなくて、
「ノドまで出かかってはいる」ような状況ではあるけれど、
でも最終的な「評価・断定ができない」。
(ロ)だから、Value プロパティはツリーの中に、最初から表示しない。
(ハ)Value プロパティだけでなく、その他の「引数を持つプロパティ」も同じ。
・・・ということのなんだと推測します。
((イ)~(ハ)については、その他のパターンもあるかもしれないですけど。
「確定されない」という意味においては。)
クラスモジュールをバンバン作れるようになれば「それは違う」ということになるのかもしれませんが、でも、僕たち初心者は、習い始めは(クラスモジュールをバンバン作れるようになるまでは)、(イ)~(ハ)のような考え方でも全然問題ないと思います。
すくなくとも
・ウィッチウィンドウ、
・ローカルウィンドウ、
・オブジェクトブラウザ、
・イミディエイトウィンドウ
・ヘルプ
は、それである程度までは結構 読めます。(後述)
それにしても・・・
「普段から、多くのプロパティの記述方法では、引数はもちろん、
とにかく省略だらけの方法しか教わってない」、
「まともに教えてもらってない」、
ということに気がつかないと、
「僕らVBAの初心者」は、こういうことにはなかなか気づけません。
これも、
「省略だらけで、ウソを教えられて、隠されて、VBAが上達しない、その理由の一つ」
「VBA教育業界の悪習で20年前から治ってない」
みたいな感じですね~。
ちょっと難しい話 & またまた脱線になってしまいますが・・・、
そもそもですが・・・
基本的に、
ウォッチウィンドウはもちろん、
ローカルウィンドウもオブジェクトブラウザも、
「 ”値と型 ”が確定させられないモノ」=「評価ができないモノ」は、はっきりとした表示がなされません。
ウォッチウィンドウはもちろん、
ローカルウィンドウもオブジェクトブラウザも、
「 ”値と型 ”が確定させられないモノ」=「評価ができないモノ」の場合は、
(A)何も表示されない、か、
(B)逆に、何にでも対応できる総称的(=汎用的)な何らかの文言・単語が表示される、
・・・という格好になるようです。
(僕もExcelVBA初心者だから自信なし。でも、それらの動きを見ていると、おおむねそうであるっぽいです。)
例えば
複数の型を臨機応変に扱える「Variant型」のモノ、例えば「Variant型の戻り値」、や、
複数のオブジェクトを扱える「Object型」のモノ、例えば「Object型の戻り値」、などは、
ウォッチウィンドウはもちろん、
ローカルウィンドウもオブジェクトブラウザも、
(A)何も表示されない、か、
(B)逆に、何にでも対応できる総称的(=汎用的)な何らかの文言・単語が表示される、
・・・という格好になります。
同じように、「引数」というものを持つモノも、「具体的な値と型が定まらない」ということで、
ウォッチウィンドウはもちろん、
ローカルウィンドウもオブジェクトブラウザも、
(A)何も表示されない、か、
(B)逆に、何にでも対応できる総称的(=汎用的)な何らかの文言・単語が表示される、
・・・という格好になります
ただし、イミディエイトウィンドウは、
「引数の既定値」を「自動的に使ってくれる」っぽいので、
値や型を調べることができます。(面倒くさい手順をふまないと調べられないケースも多々ありますが。)
であるなら、
ウォッチウィンドウはもちろん、
ローカルウィンドウもオブジェクトブラウザも、
「引数の既定値」を「自動的に使ってくれればいいのに」、と思うんですが、
なぜかそうなってません(^^)。
なので、
ウォッチウィンドウ、ローカルウィンドウ、オブジェクトブラウザで分からない部分は
イミディエイトウィンドウやヘルプなどで調べることになります。
逆にイミディエイトウィンドウやヘルプなどで分からない場合は、
ウォッチウィンドウ、ローカルウィンドウ、オブジェクトブラウザなどで調べることになります。
特に、
(A)何も表示されない、
という場合は、
今調査に使っているツール以外のもので調べることが必要、ということになります。
例えば、
「オブジェクトブラウザ」には、プロパティやメソッドの「戻り値の」「型」が、
原則的には「説明ペイン」に表示されますが、それは明確な型が決まっている場合だけです。
Variant型の何かが返ってくるときなどは、つまり、明確な固有の型が決まらない場合は(絶対ではありませんが、でも、)、
「AS ×××」とは表示されない場合も少なくなく、つまり、「何も返ってこない」と錯覚させられます。
(=「何も返ってこない」と騙されます。)
でも実際には「何らかの値と型」が返ってくる場合が意外とあります。
その場合は、ヘルプを読むか、ウォッチウィンドウで調べると、
「本当のところどうなのか?」
「実際にはどうなのか?」
「なんだよ~!?、本当は何かの値が返ってくるんじゃねーかよ~!」
ということが分かります。
逆にヘルプに書いてなくて、「オブジェクトブラウザ」やウォッチウィンドウで分かるケースもあります。(ウォッチウィンドウは割と確実性が高いです。もちろんカンペキではありませんが。)
結局のところ・・・、
・ウォッチウィンドウ、
・ローカルウィンドウ、
・イミディエイトウィンドウ、
・オブジェクトブラウザ、
・ヘルプ、
「それらは」「すべて」
「それぞれが」
「完ぺきではない」
です。
なので、
「いつ何時も完璧な答えを返してくれるわけではないので」
「特に、引数その他の設定値が ”あいまいなとき ”には、答えを返してくれないので」
なので、
「それらは、全部が必要」
「エラーなどの際に 何かを調べるには、それら全部が必要」
・・・ということになります。
いつもどおり、脱線すみませんでした。
最後に、なんども「ちなみに」で申し訳ありませんが、
今回の実験で使っている、「A1:B4」の内容で、
? Activesheet.UsedRange.Value(xlRangeValueXMLSpreadsheet)
と、既定の引数じゃない引数を指定してEnterした場合は、以下のような
長~い「XML」タグが含まれてた複数行の結果が返ってきますが、
これも、テキストファイルにコピペして、xmlという拡張子を付けて開くと、
Excelが起動して、A1セル~B4セルが埋まった状態で開きます。
(Windows10+Excel2019の場合)
(※「? ActiveSheet.Range("A1").Value(xlRangeValueXMLSpreadsheet)」ではないので注意。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
' ' <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="Yu Gothic" x:CharSet="128" x:Family="Modern" ss:Size="11" ss:Color="#000000"/> <Interior/> <NumberFormat/> <Protection/> </Style> <Style ss:ID="s17"> <NumberFormat ss:Format="Short Date"/> </Style> </Styles> <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="6" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="18.75"> <Column ss:Width="61.5"/> <Row> <Cell><Data ss:Type="String">a</Data></Cell> <Cell><Data ss:Type="String">b</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">1</Data></Cell> <Cell><Data ss:Type="Number">4</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">2</Data></Cell> <Cell><Data ss:Type="Number">5</Data></Cell> </Row> <Row> <Cell><Data ss:Type="Number">3</Data></Cell> <Cell><Data ss:Type="Number">6</Data></Cell> </Row> <Row ss:Index="6"> <Cell ss:StyleID="s17"/> </Row> </Table> </Worksheet> </Workbook> ' ' |
★ これで、「Activesheet.UsedRange.Value」が、単一のセルじゃなくても、
「複数のセルが集まった表構造であっても」、
「確実に」その表の内容・構造、がわかります。
つまり、「Value」の中身が、Excelファイルになって表現されるので
「超・明確」になります。
==============================
今回は以上です。
==========================================================================
バックナンバー目次とサンプル号
----------------------------------------------------------------------
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
発行システム:『まぐまぐ!』 http://www.mag2.com/
配信中止はこちら https://www.mag2.com/m/0001691660.html
----------------------------------------------------------------------