★★★★★★★★★★★★★★★★Access2000VBA・Excel2000VBA独学~★超重要!!「なかなかVBAが上達しない・応用ができない・応用が利かない・思いどおりのものが作れない理由」。5個以上。~ExcelVBA独学のコツ?ポイント?~とりあえず20個くらい~
※まだ書きかけです。すみません。
※間違ってたらすみません。
※メモ書きなので、自分でも意味不明な箇所も多いです。ごめんなさい。
目次
★ はじめに
★ 「ExcelVBA独学・上達のコツ?ポイント?」の一例
▼ (01)VBAはオブジェクト指向もどきらしい。
▼ (02)動かすのは(操作するのは)一般変数とオブジェクト変数の2つだけ。
▼ (03)一般変数に代入する生データは一般データです(文字ベースのデータ。文字列・数値・日付・論理値など)。
▼ (04)オブジェクト変数に代入する、「生データに相当するものは」、オブジェクトです。
▼ (05)オブジェクトは「Excelという工場で働くミニミニロボット」
▼ (06)オブジェクトは大別して「単一オブジェクト」と「コレクション」の2種類しかありません。
▼ (07)オブジェクトの中には、「プロパティ、メソッド、イベント」、という3つの機能が内包されています。
▼ (08)ローカルウィンドウやTypeName関数+Parentプロパティ、オブジェクトブラウザ、ヘルプ、ウォッチ式、
などが扱えてその意義がわからないと、なかなか、まったく上達しません。
▼ (09)一般変数(配列も)を動かす・操作するには、変数の外側からいろんな命令を使う
▼ (10)オブジェクト(単一・コレクションともに)を動かす・操作するには、内側から「プロパティ・メソッド
・イベント」という命令を引き出しながら・・・、と同時に、外側からも色んな命令を使う
▼ (11)★★最重要!!!「オブジェクト変数、値やオブジェクトを返す自作関数の作成、配列」、を覚えないと、
なかなか上達しません。
▼ (12)名前付き引数は「メソッド」だけではなく、プロパティ、関数、引数を持つプロシージャのものでもあります
▼ (13)★★2つめに重要!!オブジェクト変数が扱えれば、「諸悪の根源のひとつ」の「With」=「Withの生オブジェクトので安易な使用」が要らない場面が増える
▼ (14)「オブジェクト式」ついては、階層構造の省略をしていると、なかなか上達しない。
▼ (15)本当に「変数なんか全部Variant型でいい」と思うならやってみればいいと思います。
永遠に上達しません。なぜなら自作関数が作れないからです。
▼ (16)「複雑な条件での定型的な集計やリストアップ」に限っては、「SQL」を使わないと
「質が低い」のまま・「超非効率」のまま。(特に他の人にも使ってもらうプログラムの場合)
▼ (17)Excelの「ユーザーフォーム」は使い勝手が悪すぎて非効率です。
▼ (18)オブジェクトを取得する方法・7つ
▼ (19)小数を扱うときは気を付ける。正常に動かないことがたまにあるので。
▼ (20)同名のプロパティやメソッドでも、親というか、オブジェクトが変わると、まったく異なる動作となります。
※Shift+TABキー、もしくは、Homeキー、Homeキー+TAB数回、を押すと、目次付近に戻れます。
★ はじめに
※この記事の前身の記事
★★★★★★Access2000VBA・Excel2000VBA独学~用語:「ExcelVBAプログラミング」とは?~
僕も1年くらい前からExcrelVBAを独学し始めたところで、初心者ですが、ExcelVBA独学のコツ?ポイント?は、どうやら 以降に挙げた(01)~(19)のような感じっぽいです。
ただし、僕はまだExcelVBAを独学しはじめたところで初心者だから、テキトーに書いてます。間違ってるところもあると思うので、全部うのみにはしないでご自分でも調べてください。
なお、ご自分で、「なかなか上達しないのは自分のせい」と悩んでおられる方もいらっしゃるかもしれませんが、それは間違いです。
今のExcelVBA教育業界の教え方が、20年前から、ダメな教え方からほとんど変わっていない、むしろ悪くなっている、というのが原因です。
僕もダマされていました。
だからみなさんも気にしないでください。
それよりも、以降に挙げたことを、しっかり学習してみてください。
先生や同僚や後輩、わが子に、「何百回でも」、質問してみてください。
また、もし習いに行くなら、必ず以下の質問を講師の方にしてください。
「自分のような初心者にもわかるように、ヘルプとオブジェクトブラウザの読み方を教えてもらえますか?」
と。
「もちろんです!今すぐやりましょう!それこそが本当の基礎なの!それを聞いてくれてうれしい!きっと上達が早いよ!?」と言ってくれる、「初心者だからと言って・難しいからおいおいね」と「逃げない」、「はじめからちゃんと準備してくれる」先生に習いましょう。
必ず、習ったお金を早期に回収できるくらい上達できると思います。
ちなみにですが、「ヘルプとオブジェクトブラウザの読み方」は、ExcelVBA 一年生の僕でも、(下手くそかもしれませんが・でも)教えられると思います。
単に「変な省略」をやめるだけですから。
特に講師じゃなくても誰でも教えられます。
特に、
・「Excel2000~2003ヘルプのオブジェクトモデル一覧図が分かる」、かつ、
・「オブジェクトを返す自作関数」が思い通りに作れて、かつ、
・「プロパティもメソッドもイベントもオブジェクトの中に内包される命令or機能」と分かっている、かつ、
・「プロパティもメソッドもそういう自作関数と同じ仕組みで動いている」、ということが体で理解できている、
そういうかたなら、ド素人でも・誰でも・余裕で教えられると思います。
では以降、ExcelVBA独学・上達のコツ?ポイント?を僕なりの答えですけど、ご提示します。(ご自分でもこういうの、作ってくださいね?)
以降にあげたことを学習したことがないと、基本、100%、挫折してしまうか、「初心者本を終わった時点から一向に上達できない」となってしまいます。
逆に言うと、「初心者本を終わった時点以降は以下のことについて学習するとかなり上達できる可能性が高まる」ということでもあります。
このなかに、もしかしたら、みなさんが「上達できない理由」、もあるかもしれません。
(多くの方が、少なくとも、最低3個はあると思います。)
そして、以下のことは全部、「講師・先生・先輩・同僚」に、「わかるまで」「何百回でも」質問して、わかるようにならなければならないこと・・・でもあると思います。
いうなれば「脱・初心者」のための、「本当のポイント」・・・、のうちのひとつ(=一つの例)、だと思います。(繰り返しますが、ご自分でもこういうの、作ってくださいね?)
▼ (02)動かすのは(操作するのは)一般変数とオブジェクト変数の2つだけ。
「プログラミング」というものにおいて、「動かす対象」は、どんなプログラミング言語でも「基本は」「変数」。
本当は、「最終的な操作の対象」は「変数」に代入した、「生データ」のほう、が、「動かす対象・加工等々をする対象」ですが、いきなりそこまで突っ込んでいってしまうと、複雑になりすぎてしまうので、あえて「変数どまり」にさせて理解していきます。
実際、プログラム内では「生のまま」データを扱うことは少なく、最初に変数に代入してから、変数のほうを操作することが多いので、その意味からも、ここでは「操作の対象は変数」と「あえて」言ってしまっています。
そしてVBAの場合は、変数の種類は大きく分けて、一般変数とオブジェクト変数の2つしかない。です。
一般変数には、一般データ(文字ベースのデータ)を代入することで、また、
オブジェクト変数には、オブジェクト(=オブジェクト式)を代入することで、
操作が可能となります。
(「代入」が完了してはじめて、各種の操作が「開始」「できる」・・・、というイメージです。)
※オブジェクト=3D的なパーツ・部品
=プログラムコードとしては、オブジェクトは「オブジェクト式」のこと。
オブジェクト式=3D的なパーツや部品を、
(「プログラム=文字」として扱えるように)文字に置き換えたもの。
「階層構造」をなした状態で。
※★★超重要!!な補足
VBAの場合は、オブジェクト変数にオブジェクト(=オブジェクト式)を代入しなくても、「オブジェクト式」のままでも操作できてしまうので、ある意味「タチが悪い」。です。
(他の言語でもそうなのかもしれませんけど・・・)
そのため、ほどんどの初心者が「オブジェクト変数の勉強をしない」という悲惨な状況です。
(マシンパワーのある今ではそれほど重要でもない)「Withなどを多用」し、当然、オブジェクト変数を使わないです。
といいますか「使えない」。です。
大変残念なことなのですが、巷にはちゃんとしてない講師や書籍やサイトが多くて、ちゃんと「オブジェクト変数の重要性を教えないから」、結果、「勉強させてもらえない」から、「使えない」、のです。(習う側に罪はないです。教える側は大罪です。)
だから、「初級の下のプログラミングセンスと知識のまま、一向に中級以上に上がれない」ですし、「ほとんどの人が挫折してしまう。」のです。
(「動かす対象・操作対象」の「変数(特にオブジェクト変数)」勉強を「あえて放棄」して、「やらない」わけだから、「挫折して当然」の結果となります。)
「お金を払って習いに行ったとしても」、オブジェクト変数の重要性を理解できねば、「結局、値やオブジェクトを返す自作関数」の自作もできず、そのせいでプロパティやメソッドの理解もできないので、これまた「初級の下のプログラミングセンスと知識のまま、一向に中級以上に上がれない。」ですし、「挫折する可能性もそうは低くならない。」です。
たぶん、楽しくはならないと思います・・・、VBAが・・・。
基本、「オブジェクト変数や、値とオブジェクトを返す関数、階層構造」、の勉強をしないなら、「習いに行った」としても、いずれ、100%挫折してしまいますので、厳しい言い方かもしれませんが、それなら(挫折すると分かり切っているのですから)、最初からVBAに取り組まないほうが無難です。
でないと、お金はもちろん、それよりも貴重な「あなたの」「時間」までもを、「ドブに捨ててしまう」からです。
そのようなことにならないように、どうか、どうか、ご注意ください。
また、VBAの学習を始めるなら慎重に・・・。
そうなるくらいなら、学生さんなどに「安く外注する」ほうが絶対にコスパがいいです。
▼ (03)一般変数に代入する生データは一般データです(文字ベースのデータ。文字列・数値・日付・論理値など)。
▼ (04)オブジェクト変数に代入する、「生データに相当するものは」、オブジェクトです。
ただし、プログラムコード上に限っては「オブジェクト」は「オブジェクト式」のことを意味します。
もっと言うと、「階層構造を省略していないオブジェクト式」のことを指します。
※階層構造を省略するオブジェクト式の書き方ばっかりを教えている本を読む・買ってしまうと、言葉が悪くて申し訳ございませんが、「ある意味VBA的にはバカ」にさせられてしまいますし、エラーが増えるうえに自力解決なんてほとんど無理です。またQ&Aサイトで聞いてみたところで回答の意味を理解できません。
基本、ほとんどの市販書籍が、但し書きもせずに、あたりまえのように、「省略しまくったオブジェクト式の書き方しか教えない本」ばっかりです。
逆に階層構造を省略しないオブジェクト式の書き方を覚えると、常に階層構造やオブジェクト構造のことが「絵的に」思い浮かんでいるため、エラーの少ないコードをどんどんと書けるようになりますし、エラーの自力の解決もできるようになる、そういう方向に行けやすくなる・・・、と思います。
なお、「オブジェクト式」とは、「3D的・立体的なイメージの “ オブジェクト “ を文字に直したもの・変換したもの」のことです。
プログラム上に、3D的・立体的な「オブジェクトの絵」をペッタンコと貼付けても、全く持ってプログラムは書けないので、「オブジェクトを文字に直したオブジェクト式」の方を使います。
▼ (05)オブジェクトは「Excelという工場で働くミニミニロボット」
オブジェクトは「細かい機能の集合体」、「複数の機能を有したモノ(=複合機能体)」、「文字データと違い、3D的なユニットな感じ」、あるいは、「Excelという工場で働くミニミニロボット」とか「パーツ」「部品」というイメージでいいと思います。
ただ、「大きいもの・小さいもの・目に見えるもの・見えないもの」があります。
具体的には、目に見えるものとしては「ブック」、「シート」、「セル」、「グラフ」、「図形(オートシェイプ)」「ピボットテーブル」、「Microsoft Query (あるいはQueryTableオブジェクト)」、「テーブル機能(ListObject)」、「オートフィルター」「セルのコメント機能」「(旧Excelなら)コマンドバーや右クリックメニュー」などがあります。
目に見えないもの・見えにくいもの(意識しづらいもの)には、「オブジェクトの内側管理機能(Interiorオブジェクト)」「エラー管理機能」「VBE管理機能」「各種コレクション」「ADO/DAO」などがあります。
※「ADO/DAO」は、Excelからは独立した機能ですが、オブジェクトを動かす形態の機能です。
「全国のATM ” 網 ” 」を「1つの大きなオブジェクト」と捉えると、ATM機1機1機が「目に見えるオブジェクト」で、それを裏方でつないだり動かしたりする「壁や地下に埋まっている」「ケーブルや管理システム」が、「目に見えないオブジェクト」というイメージになります。
で、ATM機の「最後の実行」が「お金を出す」という「メソッド」というイメージです。
実行するまでの各種のこまごまとした設定(口座番号を打ち込むなど)が「プロパティ」というイメージです。
キャッシュカードや通帳は「引数」・・・というイメージです。
人が立たないと「自動的にスリープモード」に移行し、人が前に立つと、「自動的にスリープを解除して画面起動する」そういう機能が「イベント(自動実行機能・あるいは自動実行タイミング・自動実行信号)」というイメージです。
「ATM機」をオブジェクトのひとつとして捉えた場合は、次のような感じです。
「引数」がキャッシュカードや預金通帳
「メソッド」が
振込む(お振込)
通帳記入する(通帳記入)
引き出す(お引き出し) など。
「あらかじめ決められた動作」
あるいは、
「あらかじめ決められた動作」を「実行」する、そういう機能。
「プロパティ」が
タッチパネル画面で行う各種の設定。
振込時なら相手の口座番号設定や金額設定
引き出しなら暗証番号の入力や金額設定 など。
「あらかじめ決められた各種設定項目」
あるいは、
「あらかじめ決められた各種設定項目」の「設定」を「実行」する、そういう機能。
「イベント」が自動スリープや自動スリープ解除・自動画面起動
「目に見えないオブジェクト」は、通帳の印字ユニットや、内蔵のデータの通信ユニット(チップや記憶装置)など。
「目に見えるオブジェクト」はタッチパネルや、お札を取り出す部分の「自動開閉お札カウント排出ユニット」、など。
上記は、すべて、「ATM機」という「オブジェクト」の中に入っている、内包されている「機能」、です。
特にプロパティやメソッドに相当するものは「内包されている」「命令」というイメージでも行けると思います。
VBAのオブジェクトの場合も「プロパティやメソッドはある意味・命令」というイメージは同じです。
もっというとATM網全体は、○○○○銀行という親オブジェクトがあり、階層構造に組み込まれている、
とか、
ATM機は○○○○支店の第1フロアが親オブジェクトの時もある・・・、
あるいは、
135台めのATM機は○○○○支店の第1フロアが親オブジェクト・・・、
169台めのATM機は×××××支店の第3フロアが親オブジェクト・・・、
みたいなイメージです。
▼ (06)オブジェクトは大別して「単一オブジェクト」と「コレクション」の2種類しかありません。
オブジェクトには大別して、「単一オブジェクト」と呼ばれるモノと「コレクション」と呼ばれるモノの2種類があります。(2種類しかありません。)※ヘルプに「単一オブジェクト」と書いてあります。
コレクションは、「コレクションオブジェクト」とも言います。
どちらかというと、単一オブジェクトとの区別を明確にするために、「コレクションオブジェクト」と呼ぶ方がいいと思います。区別を明確にするほうが、階層構造を理解しやすいので・・・。
「コレクションオブジェクト」は、複数の単一オブジェクトを個別管理及び一括管理する「ユニット・ミニミニロボット」です。
同じ種類、似た種類の、複数の単一オブジェクトたちを個別管理及び一括管理する機能です。
例えば「単一のオブジェクトが複数ある」場合は、「Item」という名前のプロパティ、あるいはメソッドを使って、そのうちの、単一オブジェクトを特定する機能をコレクションオブジェクトは持っています。
ちなみにですが、「Item」という名前のプロパティ、あるいはメソッドの学習をすっ飛ばしてしまうと、「致命的」となります。ヘルプやオブジェクトブラウザが読めなくなってしまいますので。
また、複数の同類のオブジェクトの一括印刷、一括削除、一括コピー、etc、などの「一括××××××」という操作もできます。
(ただし、やれる一括処理は、各コレクションで異なります。)
ちなみにですが、例えば「Sheet1」という名前の「単一のシート」の場合は、「Item」という名前のプロパティを使って、以下のようなオブジェクト式となります。(以下は「省略しない書き方」です。)
「Application.Workbooks.Item("book1.xlsx").Worksheets.Item("Sheet1")」
まずは、(コレクションを経由して)このような形で、単一のシート、つまり、Sheet1を取得(=選択・指定)ができます。
ただ、「Item」は、プロパティもメソッドも省略されることがほとんどなので、実際には以下のように省略して書かれることがほとんどです。
「Application.Workbooks("book1.xlsx").Worksheets("Sheet1")」
(オブジェクトモデル・階層構造としては、「Workbooks.Item("book1.xlsx")」で1階層分を「単一オブジェクト」として使っていて、また、「Worksheets.Item("Sheet1")」でもう1階層分を、これまた「単一オブジェクト」として使っている・・・、というイメージになります。
あと、基本、コレクションオブジェクトは単一オブジェクトの「上位」ではありません。横に居てくれているイメージ、同じフロアに居てくれて・かつ・単一オブジェクトたちを管理してくれてるイメージ、です。
また、基本、単一オブジェクトの上位のオブジェクトも下位のオブジェクトも、両方とも、コレクションではなく「単一オブジェクト」です。
よく「コレクションは単一オブジェクトの親オブジェクト」「単一オブジェクトはコレクションオブジェクトの1階層下に属する」という風に間違えやすいのですが違います。(そういう図をマイクロソフト自身が描いて出してしまってもいるため、よけいに、そう誤解するかもしれません。Excel2000のヘルプの図はそんな風には描かれていないのですがWebのものがそういう形態で描かれてしまっているものがあります。)
コレクションの親オブジェクトと単一オブジェクトの親は、1階層上の同じ単一オブジェクトです。
TypeName関数+Parentプロパティで(イミディエイトウィンドウにて)調べると分かります。
たとえば、
「Worksheetsコレクションオブジェクト」の親も、
「WorkSheets("Sheet1")単一オブジェクト」の親も、
どちらの親も、「Workbook単一オブジェクト」という単一オブジェクトであることが、わかります。(Workbooksコレクションじゃあ、ありません。)
調べ方は、以下です。
イミディエイトにて、
? TypeName(Worksheets.Parent)
と書いてEnterしても、
? TypeName(Worksheets("Sheet1").Parent)
とやっても、返ってくるオブジェクトの名前は
Workbook
です。
2つとも同じですし、また、「Workbooks」(コレクション)でもありません。
(※基本、「Worksheets」と、何も付加させずに1単語だけを書くと、同じ階層に居るコレクションオブジェクトのほうを指定したことになり、「Worksheets("Sheet1")」とシート名やインデックス番号付加してカッコで囲んで書くと、同じ階層に居る単一オブジェクトを指定したことになります。これは他のどんなコレクションでも同じルールです。)
なお、「Application.Workbooks.Item("book1.xlsx").」は、もしもそのブックが今現在アクティブな状態なら、色々省いて「ActiveWorkbook.」と1語で書くこともできます。
つまり、ActiveWorkbook.Worksheets("Sheet1")
と書けます。
さらにはそれすら省略して、
Worksheets("Sheet1")
と書くこともできます。
でもこの「Worksheets("Sheet1")」とか「ActiveWorkbook.Worksheets("Sheet1")」のような「省略しまくったオブジェクト式の書き方」ばっかりを使っていると、学習が進むにつれてエラーだらけになります。
そして言葉が悪くて申し訳ございませんが、「ある意味VBA的にはバカ」にさせられてしまいます。
そして、階層構造のことを教えてもらえていないため、なかなか素早く「正しく直す・正しく書き換える」「メンテや引継ぎがしやすくなるように直す」「将来を見越して直す」ということができません。
エラーも増える一方です。
以上のようなことは、その他のたくさんのコレクションオブジェクトでも同じ感じです。
(個別管理と複数一括管理の両方ができますし、また、オブジェクト式にて省略ばかりしていると、ミスやエラーが増える上に自分で治せないという2重苦・3重苦になってしまいます。)
それから、「Item」というプロパティやメソッドのことを学ぶことは、オブジェクトモデル(階層構造)の学習に必須なので、絶対に理解しておきます。
なお、なんで、同じ「Item」という名前なのに「プロパティ」と「メソッド」に分かれているのかは僕は知りません。VBAレジェンドの人にでも聞いてみてください。
あと、コレクションオブジェクトと(たしか)Variant型の配列には、「For Each 文」が使えるので、「すべての単一オブジェクトへのループ処理」ができます。
セル(Rangeオブジェクト)のセル範囲や名前定義した範囲などにも「For Each 文」が使えます。(なので、Rangeオブジェクトは若干コレクションめいた性格を持っているようです。単一セルを複数同時に扱える、みたいな。)
そのため「For Each 文」を使えば、「Cellsプロパティ+カウンタ変数」を使わなくても、一応、Rangeオブジェクトだけでも、一応、「横方向のループ処理」が可能です(いいか悪いかは別として)。
「For Each 文」の1行目で、プログラム実行の対象範囲として、横方向のセル範囲を指定すればいいので。
僕は、「速度的な問題が発生しない・ちいさめの表」の処理だったり、特別「ダメな理由」が無い状況のときは、使うことは悪くないのでは?と思います。
実際、セル範囲や名前定義の名前で、セルの一括処理ができるため、コードが読みやすくなってメンテも引き継ぎもラクだし。
もちろん「Cellsプロパティ+カウンタ変数」にも慣れたほうがいい(慣れるべき)と思いますけど、今のところ、複雑な条件での集計やリストアップにはSQLやMicrosoftQuery、QueryTableオブジェクト、ピボット、たまにピボットのVBA操作、を使うので、「Cellsプロパティ+カウンタ変数」とか、ループ処理そのものを使うシーンがほとんど無いです・・・。
▼ (07)オブジェクトの中には、「プロパティ、メソッド、イベント」、という3つの機能が内包されています。
オブジェクトの中には、大分類として、「プロパティ、メソッド、イベント」、という3つの機能が内包されています。その3つは、オブジェクトの「メンバー」と呼ばれています。全部オブジェクトとセットです。
そして、その3つのうち、「プロパティとメソッド」はある意味、「特定のオブジェクトに紐ついて内包されている専属命令」とか、「そのオブジェクト独自の命令」という感じで理解してもOKです。
そして・・・、
「プロパティ」は「各種設定系」の命令・機能で、
「メソッド」は「コピーする、印刷する、開く、新規作成する」などの、
「動作系(動作開始系)」の命令・機能
・・・というイメージです。
※↓詳しくはこちらですが、こちらも必ずお読みください。
『★★★★★★★★★★★★★★★★Access2000VBA・Excel2000VBA独学~★超重要!!機能として見た場合のプロパティとメソッドの違い~』
『★★★★★★★★★★★★Access2000VBA・Excel2000VBA独学~用語:新:プロパティ、メソッド、の新しい説明~今までの「プロパティ=性質」「メソッド=動作」のような説明だと結局わからない。理解できない。「もれなく」「挫折する」ので。~』
なお、「プロパティ」も「メソッド」も、コマンドバー(あるいはリボン)や、右クリックメニューの中の、「設定項目や動作開始項目(実行項目)などとして「一応」「形として」目にも見える」ものがそこそこあります。(逆に目には見えないものも多いですが。むしろそっちのほうが多いかも。)
「プロパティ」は「×××を設定する」系のメニュー、
「メソッド」は「×××を実行する」系のメニュー、となって見えてきていることが多いと思います。
それぞれに対して、「列挙(Enum)」や「組込み定数」もメニューとして目に見えることがあります。
(もちろん、それらは一部であって全部ではないので、目に見えないそれらも多いです。
以下、その例の図です。(クリックで拡大できます。)
↑この例では右クリックしたものがセルなので、下図のようなプロパティやメソッドの内容になりますが、右クリックしたものが異なると、例えば同じ「コピー」でも親オブジェクトが変わるので、意味が変わってきます。
図形と文字列のコピーでは性格が異なる・・・みたいな感じです。
基本、『 プロパティ=性質で、メソッド=動作 』と理解するだけの、市販の初心者本にありがちな「浅い理解・質の低い理解の仕方」だと、オブジェクトブラウザやヘルプが自力で読めないまま、なかなかVBAが上達できません。
逆に、「プロパティもメソッドも自作関数の仕組みに似た命令・あるいは機能」と考えるほうが、上達が早まると思います。
(色んなことを、「リンクさせて」考えやすくなるため。)
引数も持っているし、値を返したり、オブジェクトを返したり、名前付き引数が使えたり、逆に何も返さずに何らかの動きをするだけだったりと、「プロパティもメソッドも自作関数も」全部動きが似ています。
もう少し言うと、プロパティもメソッドも・・・、
「値やオブジェクトを返す自作関数」
「何らかの動きをしつつ・同時に値やオブジェクトを返す自作関数」
「値を読めるだけで設定(書き換え)はできない自作関数」
「値を読めて・かつ・設定(書き換え)もできる自作関数」
「値を引数にとる自作関数」
「オブジェクトを引数にとる自作関数」
・・・といった関数たちに仕組みが似ている、ということです。
なお、「プロパティとメソッド」は、「命令なのか?機能なのか?」という区別については、独学の最初のうちはつけなくても大丈夫です。学習が進むにつれて、もし区別が必要ならすればOKです。僕はどっちでもいいと思っています。
前後の文脈で訳し変えています。
基本、「プロパティとメソッド」は名前付き引数も使えたりして「関数」の仕組みと似ているので、結果・「命令」ととらえればいいとは思いますが、でも、一方で、オブジェクト目線でヘルプで「メンバー一覧」を読むと、「機能」と呼んでも差し支えないものばかりなので、「機能」でもいいのじゃないかと思います。
それにヘルプの「オブジェクトメンバー一覧」が読めて・その内容が正しく意味が理解でき、正しい意味あいでコードが書けるなら、「命令でも機能でもどちらでもいい。」とも思います。
どうしても白黒つけたかったら、プロの人に聞いてください。
「イベント」は
「オーブンレンジの扉を開けた瞬間にあたためが自動でストップする」とか
「ATMやコピー複合機の前に立つとスリープが自動解除されて自動起動する」みたいな、
「何かの瞬間」に「自動動作する機能」「プログラムを自動実行する機能」です。
あと、(多分ですが)全ての単一オブジェクトと(再度・多分)全てのコレクションオブジェクトは、「階層構造を成して」「つながっている」ので、その「つながり」「経路」を利用して(伝っていき)、「下位や上位のオブジェクトのプロパティやメソッド」にアクセス(=流用)できる機能もあります。(単一、コレクション、両方の上下で。)
僕はそれを勝手に、「階層構造上下自由往来機能」とか、「上下階層オブジェクトの機能の流用機能」などと勝手に名付けして呼んでいます。これができることで、「上下の階層の単一オブジェクトのプロパティやメソッドをほんの少し・一瞬だけ、使いたいとき」は、オブジェクト変数をいちいち宣言しなくても、あるいは、最上階層から全部の階層をたどってこなくても、それらを使うことができます。その他のメリットも多分あると思います。
そして、その階層構造やつながりの構造・経路は、ローカルウィンドウやTypeName関数+Parentプロパティ、オブジェクトブラウザなどで確認できます。
ただ、一部のコレクションオブジェクトは、「階層構造に組み込まれていることは間違いないのだが、でも、どこに位置しているかよく分からない」というモノがあります。(例えばSheetsコレクションオブジェクトとか。)
そこは少し注意が必要です。
最後に、単一オブジェクトもコレクションオブジェクトも「プロパティ」は100%内包しています。
また、100%、階層構造にも組み込まれています。(位置がよくわからないコレクションオブジェクトなども存在はしますが、一応、それも、階層構造に組み込まれています。)
が、「メソッドとイベント」は、内包してない単一オブジェクトやコレクションオブジェクトがあります。
▼ (08)ローカルウィンドウやTypeName関数+Parentプロパティ、オブジェクトブラウザ、ヘルプ、ウォッチ式、などが扱えてその意義がわからないと、基本、まったく上達しません。
「初心者」の「下」のスキルのまま、セルやフィルタの操作などがちょこっとできるだけでいいのなら何の問題もありませんが・・・。ただ、そのレベルですと、「マクロの記録でやったほうが早くない?そもそもVBAなんてこれ以上要る?」という状況に陥りかねません。
超重要な参考記事
★★★★★★★★★★★★★★★★Access2000VBA・Excel2000VBA独学~★超重要!!オブジェクトブラウザの使用目的・使用意義~
▼ (09)一般変数(配列も)を動かす・操作するには、変数の外側からいろんな命令を使う
一般変数(配列も)を動かす・操作するには、変数の外側から、定数?、演算子(記号めいた命令。四則演算の記号や&など)、ステートメント(繰り返し文や条件分岐文、その他色々)、VBA関数、といった命令などを使って動かすイメージ。
▼ (10)オブジェクト(単一・コレクションともに)を動かす・操作するには、内側から「プロパティ・メソッド・イベント」という命令を引き出しながら・・・、と同時に、外側からも色んな命令を使う
オブジェクト(単一・コレクションともに)を動かす・操作するには、「プロパティ・メソッド・イベント」という「内包される各種命令や機能」を内側から引き出して使いながら・・・、と同時に、外側からは、演算子(記号めいた命令・Likeなど)、ステートメント(繰り返し文や条件分岐文、その他色々)、列挙(Enum=各種動作設定)、組込定数(列挙の設定値など)、といった命令などを使って動かす、というイメージです。
※「VBA関数」でオブジェクトを動かすこともあるのですが、「VBA関数」は文字ベースの一般データを動かす(加工などする)ことのほうが多いので、そのようにご理解ください。
※ステートメントは「ストップ、ゴー、繰り返し、条件分岐、変数設定、エラー処理、開く、閉じる」などの「OS的な・共通的な」、ある意味、「命令」です。
なので、(09)にも(10)にも共通に両方に使われます。
なお、「ステートメントも、演算子も、関数も、プロパティもメソッドもイベントも、列挙、組込定数、も、」、全部、「命令みたいなもの」「命令の一種」とざくっと覚えてしまっても、最初のうちは大丈夫だと思います。
「変数を動かすための」道具、命令、というイメージです。
より学習が進んだら、その都度その都度で、「どんな性格の・どんなモノなのか」を、しっかり理解し分ければ・区別をつけていけば、いいと思います。
なお、一般的には、(09)と(10)は1つのプログラムの中に「混在」します。
(09)と(10)が共存するプログラムのほうが多いです。
(09)はプロパティの値の設定や、計算、文字系データの加工(オブジェクトを動かすための条件の条件値の設定等々)、などに使われ、(10)は文字通り、オブジェクトの操作に使われます。
▼ (11)★★最重要!!!「オブジェクト変数、値やオブジェクトを返す自作関数の作成、配列」、を覚えないと、基本・まったく上達しません。
「オブジェクト変数、値やオブジェクトを返す自作関数の作成、配列(通常のものとVariant型のもの)」、を覚えないと、基本・まったく上達しません。
「一応VBAを扱えるけど、長期間・初級の下のレベルを脱出できない。Q&Aサイトの回答すら理解できない。」というレベルのままです。それでいいなら別に問題ありませんけど・・・。
特に、「値やオブジェクトを返す自作関数の作成」が重要です。
これが分からなければ、VBAは「永遠に」「理解など」「不可能」です。
この「値やオブジェクトを返す自作関数の作成」というものをもとに、
「何らかの(時には特に何の関係もない)動作をしつつ、同時に、値やオブジェクトを返すもの」や
「値を読むだけでなく設定もできる関数」なども自作できることが大切です。
そのためには、「オブジェクト変数」・・・・、特に「Object」型とか、「Variant」型、以外の、「Worksheet型」「Workbook型」、「Range型」など、個別のちゃんとしたオブジェクト変数の型を覚えなくてはいけません。
(なので、関連して、「変数なんて全部Variantでいい」なんて言っている人は「愚か」の極みです。そんなことは愚かなひとしか言いません。汚い言葉で本当にすみませんが「トチ狂ってます」と言ってしまってもいいくらいです。
「値やオブジェクトを返す自作関数の作成」がわからなかったらVBAなんて永遠に理解できないっていうのに・・・。。絶対に言うこと聞かないようにしましょう。
何度も言いますが、「穴だらけのエラーも自力で治せないプログラミング」でいいなら、学ぶ必要はありませんけど、他人が使うプログラムをちょっとでも作りたい、とか、「知ったかぶりの愚か者になりたくない」「知ったかぶりして恥をかきたくない」という場合は必須です。)
もし面接で、「VBAの実力」を調べたい時、その人のVBAの実力を調べるのは簡単です。
30秒でわかります。
『 オブジェクトブラウザとヘルプが自力で読めて、「何らかの(時には特に何の関係もない)動作をしつつ、同時に、値をオブジェクトを返すもの」や「値を読むだけでなく設定もできる関数」がささっと作れますか?名前付き引数をメソッド以外でも使えますか? また、ExcelでSQLが使える場所を・2か所以上・教えてください。』
と聞くだけです。
「???」な顔をしたり、「うっ」という顔をしたら、もうダメです。
その人は、VBAを作る人としては「即戦力」には「死んでも」「なりません。」
「できます」とウソを言う人も居るかもしれませんのでその場合は、ExcelでSQLが使える場所を2か所以上・その場で・実際に言ってもらってください。あるいは、さらに、「オブジェクトブラウザの利用意義を教えてください」と聞けば大抵はOKでしょう。オブジェクトブラウザの利用意義はオブジェクトブラウザを普段から使っている人にしか絶対にわかりませんから。そして、そういう方はWebのサンプルのコピペだけしかしないということは絶対にありませんので。
ちなみにですが、「ExcelでSQLが使える場所を・2か所以上・言えない人」は「100%」、「本来書かなくていい無駄なVBAコードを、結構な量、絶対に書きます。」
いつもどおり、話が逸れてすみません・・・。
結局、「オブジェクト変数、値やオブジェクトを返す自作関数の作成、配列」が覚えられなければ・・・・、
(a)オブジェクト式なんてまったく覚えられない。結果、応用がきかない。
(b)オブジェクトブラウザも扱えない。
(c)ヘルプも自力で読めない。当然、エラーのスピーディな解決も自力でできません。
(d)Q&Aサイトで質問しても回答者の回答の意味すらわからない。
・・・・でしょう。
理由は、プロパティもメソッドも前述しましたとおり、「値やオブジェクトを返す自作関数」と似たような動きをするからです。
プロパティやメソッドのしっかりした理解無くして、「オブジェクト操作自体」が理解・イメージできようはずもありません。
また、「名前付き引数」についても同様です。
「名前付き引数」は、メソッドのみならず「プロパティ」にも使えます。
もっと言うと、「引数をもつプロシージャ・組み込み関数・自作関数」なら、基本、「使えます」。
「名前付き引数」についての正しい理解無くしても、これまた「オブジェクト操作自体」が理解・イメージできようはずもありません。(「名前付き引数」はもともとは、プロパティやメソッドのものではなく、「関数」「自作関数」あるいは「プロシージャ」のもののようです。ヘルプにそう書いてあります。)
そして「引数をもつプロシージャ・関数・自作関数」が作れない人が、プログラムの効率化・データ管理の効率化ができる、ということは「永遠に」「ありません。」
「値を返す関数すら」も作れませんので。
※配列(特にVariant型のもの)は、表データを一括で扱うときや速度アップなどのときに使ったりするそうです。僕はSQLやMicrosoftQuery、QueryTableオブジェクトを使うことが多いので、速度的に困ったことがなく、まだ使ったことがありません。また、配列の仕組みとコレクションの仕組みは、少し似ていますのでその意味でも配列という仕組みを早い段階で学習し・すぐに使えるようにしておくことは重要です。
▼ (12)名前付き引数は「メソッド」だけではなく、プロパティ、関数、引数を持つプロシージャ、のものでもあります
名前付き引数は「メソッド」だけものではありません。
そもそも、「関数(あるいは「引数を持つプロシージャ」)」のものです。
ヘルプにそう書いてあります。
例えば2010のVBEヘルプなら、「名前付き引数と省略可能な引数の概要」とか、「名前付き引数」、「名前付き引数は使えません。」、「その名前付き引数は、既に指定されています。」、といったトピックを読むとわかると思います。
なお、名前付き引数は「メソッド」だけものではないわけなので、結局のところ、「プロパティ」や「引数を持つ自作関数」、あるいは「引数を持つプロシージャ」でも使えます。
例えば「プロパティ」の場合・・・、
「セル(=Rangeオブジェクト)」を取得したいときは、Worksheet.Range プロパティを使って、
「Range("A1")」と書くことが多いですが、これを名前付き引数を使って、
「Range(cell1:="A1")」と書くこともできます。
セル範囲を指定する場合は、
「Range(cell1:="A1", _
cell2:="C3")」
のように「 _ 」(アンダーバー)を使って複数行で書くこともできます。
小さなプロシージャを作って、
Debug.Print Range(cell1:="A1", _
cell2:="C3").Count
と書いてEnterしたら、イミディエイトウィンドウに、「9」という形で、セル範囲のセルの個数が返ってきます。
Rangeの場合は、引数の数が少ないのでかえって、読みにくくなってしまいますが、引数の数が多いプロパティの場合は、多少使えるかもしれません。
同様に、「引数を持つ自作関数」「引数を持つプロシージャ」でも名前付き引数は使えます。
逆に、
名前付き引数が、「メソッド」でも「プロパティ」でも使えて、かつ、
「名前付き引数自体は関数や引数を持つプロシージャのもの」ということであるなら、
「メソッド」や「プロパティ」っていうのは、
「名前付き引数を使えるわけだから、たぶん、関数や引数を持つプロシージャと似た仕組みなんだ・・・・」、
という推測・仮説が立つと思います。
でも実際、そう考えると、オブジェクトブラウザの説明ペインに、
「Property Application As Application」みたいに書かれているのもなんとなく納得できる気がしますし、そう考えてしまった方が、逆にオブジェクト構造の全体が分かりやすくなると思います。
▼ (13)★★2つめに重要!!オブジェクト変数が扱えれば、「諸悪の根源のひとつ」の「With」=「Withの生オブジェクトので安易な使用」が要らない場面が増える
オブジェクト変数が扱えれば、「With」という命令めいたものは速度的な問題やその他の「どうしてもWithを使わんとあかん」、というケースが無い限り、あまり要らないと思います。好みの問題もあるでしょうけど・・・。
僕はバカだからWithを使うとコードが読みにくくて、エラーを起こしちゃいやすいので、また、作り変えがしにくいので、ほとんど使いません。
マクロの自動記録で自動記録されたコードでWithが使ってあったら、基本、直します。
(コスパ的に)直す必要がないときは、そのままにしてますけど・・・。
・・・・といいますか・・・・最初から「With」を覚えてしまうと「VBA的」に、「バカにさせられてしまう」とさえ思ってしまいます。
巷には、「生オブジェクト式のまま」「オブジェクト変数に代入しないまま」、自慢げに、「Withを使おう!」なんて書いてある書籍・サイト・雑誌記事などがほとんどですが、「それこそが諸悪の根源」でして、「この方々はダメなひとたちばっかりだわ!あなた方のようなダメなひとたちは、雑誌記事や書籍を書かないで!!」とさえ思ってしまいます。
そもそも「With」は「生の」「オブジェクト式」をオブジェクト変数に代入してからでも「そのオブジェクト変数に対しても」使えます。
ですので、
「初心者のうちは」
「オブジェクトの階層構造・オブジェクト式・オブジェクト変数・オブジェクト変数のデータ型」をしっかり覚えるために、
また、同時に、
「オブジェクトの階層構造がらみのエラー」や「型がらみのエラー」などを「回避」するために、
「Withは」、
「面倒でも」「それを承知の上で」「生オブジェクト式をオブジェクト変数に代入してから」、
使うべき
だと思います。
「この方々はダメなひとたちばっかりだわ!あなた方のようなダメなひとたちは、雑誌記事や書籍を書かないで!!」という悲惨な状況になっているのは・・・・、多分・・・ですが・・・・、推測・・・ですが・・・、
「マクロの記録」をやると、「生オブジェクト式のままWithを使う」、「そういうコードが自動生成されるから」だと思います。
カッコつけて、(今となっては)大して速くもならない・かつ・大して大きな意味なんてない「With」なんか別に使わなくてもいいから、「そんなことする前に」、「オブジェクト変数」と、「オブジェクト変数への代入」、をしっかり体で覚えて、自分の実にすることこそが、「VBAの上達を早めます」。
どうか、ご注意ください。
「With」は、メチャクチャデータ量が多くて、「どうしても遅い」という時や、そのほか、「Withを使わないと問題が解決できない」という時だけ、使用を検討すればOKです。
それ以外は、オブジェクト変数を使うやり方でまったく大丈夫です。
しかも「初心者を脱して、中級の中以上になってから」でもぜんっぜん遅くないです。
そもそも「オブジェクト変数」がわからない、
「オブジェクト変数へのオブジェクト式の代入」、が理解できてない、
ということのほうが「致命的」な、大問題、です。
例えば、シート2(Sheet2)からシート1(Sheet1)へのデータ転記のコードで以下のようなWithを使ったコードがあったとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
' ' Sub test01() Sheets("Sheet1").Cells.ClearContents Sheets("Sheet1").Activate With Sheets("Sheet2") Range("B2") = .Range("B2") Range("B3") = .Range("B3") Range("B4") = .Range("B4") Range("D2:E5").Value = .Range("D2:E5").Value '範囲の転記は「Value」の省略不可?。 End With End Sub ' ' |
これを、シート1とシート2をオブジェクト変数に代入して、「Withを取る」と、以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
' ' Sub test02() Dim WS_Src As Worksheet '「Src」=「ソース」=情報源、の略 Dim WS_Trg As Worksheet '「Trg」=「ターゲット」の略 '各種設定部 Set WS_Src = ActiveWorkbook.Worksheets("Sheet2") 'データの転記元=情報源となるシートの設定 Set WS_Trg = ActiveWorkbook.Worksheets("Sheet1") 'データの転記先となるシートの設定 '実働部。事前準備部分。 WS_Trg.Cells.ClearContents WS_Trg.Activate '実働部の中核。実際の転記処理。 WS_Trg.Range("B2") = WS_Src.Range("B2") WS_Trg.Range("B3") = WS_Src.Range("B3") WS_Trg.Range("B4") = WS_Src.Range("B4") WS_Trg.Range("D2:E5").Value = WS_Src.Range("D2:E5").Value '範囲の転記は「Value」の省略不可?。 End Sub ' ' |
そんなに見づらくはないと思います。
「WS_Src」、つまり、転記「元」のシートが「シート2」、
「WS_Trg」、つまり、転記「先」のシートが「シート1」、ということもわかりやすいですし、
「WS_Trg(=ターゲット)」のセルへ、「WS_Src(=ソース)」のセルの値を代入していることもチェックしやすいです。
記述が「表のような感じに目に映る」ため、「かえって見やすい」という人も居るでしょう。
また、プログラムを
「設定部」と
「実働部」にわけることで、
書き換え・作り変えもラクにしています。
逆に言うと、「書き換え・作り変えを視野にいれることができ」ます。
「WS_Src.」や「WS_Trg.」という記述は基本、Dim・・・・の宣言のところの単語(変数)をコピペで「縦にだだだーっと」やるだけなので、記述間違いも起こりませんし、「面倒」ということもさほどありません。
そして、重要なのは・・・・
(a)操作するシートを変更したい時、「設定部」の Set のところでシート名を変えれば、
あとは何も変える必要がない。
「どこを書き換えればいいかを探す」、だけでもラクちん。速く済む。
さらにはブックを変更したときも同様。=複数のブックのシート間の操作で
エラーが出なくなる。修正箇所を探しやすく変更もしやすい。
Setでオブジェクト式の階層(ブック)の省略もしていないので、よりそうなる。
(b)自作関数化も、あっという間にできる。
Setでオブジェクト式の階層(ブック)の省略もしていないので、よりそうなる。
なんでも「省略しない」ほうが「自作関数化」がラクになる。
「値やオブジェクトを返す自作関数化」が。
ということです。
そしてさらに重要なのは、Withを「安易に生のオブジェクト式のまま」使ってしまうと、(b)の自作関数化がしづらくなる・それで悩むことになる・・・ということです。
そしてそもそも、(b)の「自作関数化」というモノは・・・、
「それを覚えないと、VBAの上達は下の下どまりで、それ以上は、100%上達しない。教室に習いに行っていたとしても、値やオブジェクトを返す自作関数の作り方とオブジェクト変数の扱いがわからなければ、VBAの上達なんか100%ありえない。あるわけない。」
かつ、
「Withなんか知らなくても、そちらができれば、100%、” 上達が早まる可能性 ” が上がる。」
・・・というモノです。
はっきり言って、「超重要」です。
「オブジェクト変数」よりも「Withから先に」、しかも、「安易に生のオブジェクト式のまま」覚えてしまうと、その超重要な(b)の「自作関数化」というモノを「初学者の最初の目標」に非常にしにくくなります。
(「これで動くからこれでいいや」、となってしまって。)
「With」を「安易に生のオブジェクト式のまま」覚えてしまう・使ってしまう、一番大きな弊害が、それです。
なお、オブジェクト変数を「しらないあいだに」「初心者に自然に使わせる」「導く」ということは、さほど難しいことでなないと思います。
だって最初から
「プログラミングはどんな言語であっても、変数を操作して自動化を実現する作業。」
「操作の対象は変数。本当はそれに格納した生データだけど、とりあえず変数。」
「そしてVBAでは、変数には大きくは、一般変数とオブジェクト変数の2種類しかない。」
「オブジェクト変数にとっての生データに相当するものはオブジェクト式。」
「オブジェクト式をオブジェクト変数に代入するときはSetを使うだけ。」
「それを階層構造を省略せずに書くだけ」
「オブジェクト式に短い名前がついて、見やすくなると考えるだけでもメリットがある」
などと「最初から」教えるだけですので。
深いことは、それをしながら、そのルールを教えながら、徐々に深く教えていけばいいのです。
階層構造も良く使う部分だけ、「そういうもんなんだ」と、最初から「省略せずに」教えるだけでも、大抵の人は「そういうもんなんだ」と意味がよくわからなくてもそうしてくれます。
「深いこと」は、それをしながら、そのルールを教えながら、徐々に深く教えていけばいいのです。
「形だけ」でも、まずは整えてあげて。
そのあとに、少しずつ、「なぜそういう形にするのか?」をお教えすればいいだけです。
では、次に、「安易に生のオブジェクト式のまま」Withを使わず、いったんオブジェクト変数を使ってからWithを使う例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
' ' Sub test03() Dim WS_Src As Worksheet '「Src」=「ソース」=情報源、の略 Dim WS_Trg As Worksheet '「Trg」=「ターゲット」の略 Set WS_Src = ActiveWorkbook.Worksheets("Sheet2") 'データの転記元=情報源となるシートの設定 Set WS_Trg = ActiveWorkbook.Worksheets("Sheet1") 'データの転記先となるシートの設定 WS_Trg.Cells.ClearContents WS_Trg.Activate With WS_Src WS_Trg.Range("B2") = .Range("B2") WS_Trg.Range("B3") = .Range("B3") WS_Trg.Range("B4") = .Range("B4") WS_Trg.Range("D2:E5").Value = .Range("D2:E5").Value '範囲の転記は「Value」の省略不可?。 End With End Sub ' ' |
前項の「test02」プロシージャよりも少し見やすくはなりました。
Withのとなりに長ったらしい記述がないほうが確かにすっきりするといえあばすっきりするかも・・・です。
(僕はそうは思いませんけど・・・。ドットの左側に何もないのは読みづらいです。With使うと読みにくくなるので、長ったらしくても表のように目に映るほうがラクです。)
いずれにしましても、Withを使った場合、「Withのとなりに長ったらしい記述がない」というのは、「Microsoft QueryやピボットのVBAでの自動化にとってはすごくラクになる考え方」です。
で、「MicrosoftQueryやピボットのVBAでの自動化」ができると、できない場合よりも、2倍~100倍の、時間とお金を節約できると思います。
話が逸れてすみません。
また「WS_Trg」を追記することで、「どのターゲットに転記しているか」も明確になります。
これであれば・・・・、
「どうしても、無意味でもWithが使いたい」
「自作関数化なんてしやすくなくてもいい!自作関数化なんてそんなことどーでもいい!!どんだけ無駄なコードを何回書いてもかまわない!!オレはWithが大好きなんだ!Withがコードの中に無いと死んじゃうんだ!」
・・・・というかたも納得させられます。
まあ、僕の書いたコードがいいものなわけもないんですが(まだ、If文とFor文しか知らないしSELECTもあんまり分からない)、でも、「With無意味大好き人間とつきあってオブジェクト変数の学習をサボっていると、VBA的にはバカにさせられてしまう」ことも事実です。
▼ (14)「オブジェクト式」ついては、階層構造の省略をしていると、なかなか上達しない。
「オブジェクト式」ついては、階層構造の省略をしていると、基本・まったく上達しません。
(特に「Item」という名前のプロパティやメソッド。)
基本、「階層構造」の全体像や良くつかうオブジェクト(特にコレクション)がどの位置に居るかなども理解しないと、ExcelVBAはまったく上達できません。
で、そのことを説明しない講師が多すぎます。
「一応VBAを扱えるけど、長期間・初級の上を脱出できない・・・」とか。
特にグラフを扱ったり、シュミレーションやシステム構築などをしたいときに上達できません。
セルとシート、フィルタあたりをほんの少し動かすとか、多少の転記程度なら問題ありませんが・・・。
でも、「そんなレベルでいいのならマクロの記録で良いのでは?」と言われることも無きにしもあらず・・・です。
▼ (15)本当に「変数なんか全部Variant型でいい」と思うならやってみればいいと思います。永遠に上達しません。なぜなら自作関数が作れないからです。
最近、「変数なんか全部Variant型でいい」とする書籍やサイト(質の悪い講師・市販書籍の著者やライター、編集者)がすごく増えていますが、ハマります。
理由は、それだと値やオブジェクトを返す自作関数がちゃんと作れないからです。
「値やオブジェクトを返す自作関数」たちがちゃんと作れなければ、前述したようにVBAの上達は「100%」「ありえません」。
初級の「下」のレベルのままです。
ただ、初級の「下」のレベルのままなことが許される職場で、「エラー解決要員」が別にいて、自分がエラー解決しなくてもいいならぜんぜんそれでもいいのですけど・・・。
ただ、それで他人のファイルやコードは触ってはいけないと思います。
普通の人のコードは、「全部Variant型なんてことは」「ありえません」ので。
▼ (16)「複雑な条件での定型的な集計やリストアップ」に限っては、「SQL」を使わないと「質が低い」まま・「超非効率」のまま。(特に他の人にも使ってもらうプログラムの場合)
「複雑な条件での定型的な集計やリストアップ」に限っては、ループ処理をできる限り使わずに、代わりにSQLを使うほうがいいです。
逆に、SQLを知らないと、ループ処理を中心に「無駄なコード」を「死ぬほど書く羽目」になります。場合によっては動作速度が「メチャ遅くなる」ようなケースも・・・。
特に、複数の社員が共同で使うシステムめいたものや、あるいは、「集計ツール的なモノ」をつくりたいときは、アホみたいに無駄なコードが増えます。(というか、多分ですが、基本、そもそもExcelで同時アクセスのできるシステムなんて作りませんけど。ただ、集計ツールは、作りますよね?)
SQLは、Microsoft Query、QueryTableオブジェクト、PivotChacheオブジェクト(だったかしら?)、ADO・DAO、などで使えます。
また、Microsoft QueryやピボットテーブルのVBAでの自動操作を知らないと、その場合も同上です。
Excelで数字の集計とかしないなら(ゲームとか作るなら)要らないですけど。
SQLを使うと、「SQL自体が、もともとループ処理を使わなくても複雑な集計やリストアップができる仕組み」なので、「無駄なループ処理が減らせます」し、そのほか、「数式がセルに埋め込まれない=結果だけが表示されるので、データ量が死ぬほど多い時でも多分高速に動く」などのメリットがあります。
ExcelVBAとの相性も悪くないため、Excelの2010以降?の「パワーピボット」「パワークエリ」などよりもラクちんな場合も少なくないと思います。
(もちろん、メリットばかりではありませんが、でもメリットも相当あります。なのに、ほとんどのExcel講師(VBAだけでなく一般操作の講師も)は、SQLのことを絶対に教えてくれません。大変残念ながら、SQLのことを知らない講師さんすら居ます。SQLは高校の商業科でも習うことがある「データ管理の基礎」なのに、大人になると誰も教えてくれません。おかしな話です。)
SQLを使うには、「MicrosoftQuery、QueryTableオブジェクト、ピボットのVBA操作、名前の定義、ADO/DAO」などもセットで使うといいと思います。
SQLを知っていると、『「システムや機能を設計する」ことも早くなる 』、とか『 Accessや他のデータベースソフトに多少なりとも、早く慣れることができる 』というメリットがあります。
▼ (17)Excelの「ユーザーフォーム」は使い勝手が悪すぎて非効率です。
Excelの「ユーザーフォーム」は無駄なコードが増えますし、サブフォームも使えません。
Accessのように連結フォームも作れません。
同時アクセスできるフォームも作りにくいです。
クエリをフォームの「書き換え可能なソース」にすることもできません。
フォームビューのままフィルタをかけられる機能も非常に作りづらいです。
これだけ使い勝手が悪いと、基本、シートをフォーム替わりにした方がいいような気がします(並べ替えもフィルタも使えますので)。名前定義したセルやセル範囲も併用して。
というか、そちらのほうが扱いやすい気がします。
あるいは、Accessのフォームを使ってExcelとオートメーションで連携するほうが50倍はコスパがいい気がします。(あくまで事務系の定型的なフォームが中心ですが)
▼ (18)オブジェクトを取得する方法・7つ
オブジェクトを操作するには、「Set」という命令を使って、オブジェクト(=オブジェクト式)オブジェクト変数に代入するのがプログラムを管理しやすいですが、代入する前に「オブジェクトの取得」という操作をします。
オブジェクトの取得とは、操作したいオブジェクトを「1つ選択する・決める」、というようなイメージです。
オブジェクトを取得する(=1つ選択する)には以下のような方法があります。
一番多いのは、(a)と(b)です。
(a)取得したいオブジェクトの上位の単一オブジェクトの、各種の「プロパティ」を使う。
基本、「プロパティ」は、『 オブジェクトの性質を決める各種設定の設定値を読んだり書き換えたりするもの 』がメインですが、それとは別に、「オブジェクトを取得することだけに特化したプロパティ」も結構たくさん存在します。
それには、「下位のオブジェクトを取得するもの」や、「上位のオブジェクトを取得するもの」があります。
上位のオブジェクトを取得するモノは、「Parentプロパティ」で取得することが多いかも?
なお、Worksheet.Application プロパティとか、QueryTable.ListObject プロパティ(も?) といった感じで、そのようなプロパティでも上位のオブジェクトを取得できます。
Parentは、「1階層上=親オブジェクト」しか取得できませんが、Application プロパティなどは、数段階層をすっとばして、最上階層のオブジェクトを取得できます。
(b)同上の、各種の「メソッド」を使う。
これも、プロパティと同様に、「メソッド」は、『 オブジェクトにあらかじめ備え付けられた「動作(あるいは動作を開始するもの)」』がメインですが、それとは別に、「オブジェクトを取得することだけに特化したメソッド」も意外と存在します。
Worksheet.PivotTables メソッドとか。
(c)コレクションの「Item」という名前のプロパティかメソッドを使う。
※これは「省略可」で、逆に書かれるほうがめずらしいのですが、知っとかないと上達できません。
(d)Excel専属のオブジェクトではなく、Office共通のオブジェクトのメソッド?やプロパティ?を使う。
(e)コレクションのその他のメソッドを使う。(AddやOpenなど)
※多くのコレクションオブジェクトが保持・内包する「Add」や「Open」などのメソッドは、「何かを新規作成したり開いたりしながら、でもそれと同時に」、オブジェクトを投げ返してもくれます。なのでユーザーが側はそれを取得できます。
これは、「何らかの動きをしながらオブジェクトを返す自作関数」と動きが似ています。
(f)関数を使う(CreateObject関数やGetObject関数)など
WordやAccessなどからExcelを操作したり、その逆をしたいとき、などによく使います。
(g)イベントプロシージャの引数を使う
▼ (19)小数を扱うときは気を付ける。正常に動かないことがたまにあるので。
とくにSingle型の変数を使ったときに計算ミスが起きることがあるので。
Variant型に入れたときなどもちょっと注意が必要かもしれません。
★★★ Access2000VBA・Excel2000VBA独学~初心者の方や独学者の方へ:パソコンで小数計算をするということの重要性~関連して「変数の型は覚えなくていい」とか「変数は全部Variant型でいい」 、という最低で腐った教え方には、絶対に騙されないようにしてください。ベストセラーの「教科書」を名乗る本も真似していてとっても危険・かつ・迷惑です。~
▼ (20)同名のプロパティやメソッドでも、親というか、オブジェクトが変わると、まったく異なる動作となります。
※親オブジェクト=プロパティやメソッド目線の場合は、「それらを保持・所有・内包しているオブジェクトのこと。」だとイメージすればいいと思います。
オブジェクトの階層構造の話であれば「1階層上の単一オブジェクトのこと。」とイメージすればOKだと思います。
たとえば「Worksheet.Rangeプロパティ」と「Range.Rangeプロパティ」は、おなじ「Rangeプロパティ」でも、(親が異なるので)やれることが異なります。
このほか、たとえば、「Application.Value プロパティ」と「Range.Value プロパティ」とか、
「Range.Copy メソッド」「Worksheet.Copy メソッド」「Worksheets.Copy メソッド」「Shape.Copy メソッド」なども同様です。
「異なる」と言う意味では、「え?こっちのプロパティはこんなこともできちゃうの!?」という嬉しい場合もあれば、「え?あっちではこれができたのに、なんでこっちではできないの?うぎいーーーー!!」となってしまう悲しい場合もあります。
特に後者だとメゲることもあります。
片方ではエラーにならないのに、もう片方ではエラーになったりすることもあるからです。
で、「同じ名前だからできることが同じ」という決めつけや思い込みが抜けないため、「もとからできないからエラーになっているのに」、それが分からず、「何日も」アホみたいに悩むことになります。
ヘルプとオブジェクトブラウザが扱えれば、それで「あれ?ちゃうんかな?」とさっとそれらで調べれば」「3分で解決できる」のですけど・・・。
(※「親オブジェクトがどうのこうのなのでエラーになって当然・・・」、といったような情報はWebで検索してもほぼ、出てきません。Q&Aサイトで聞いてもいいですけど回答が必ずもらえるわけでもないし、何日も待たないといけないかもしれません。結局、ヘルプとオブジェクトブラウザが扱て、まずはそれらを見るのが一番早道です。)