【スキマ学習】ガチ初心者と一緒に、Excelでnoteのタグ解析ができるツールを作ってみよう《3》
お待たせ致しました。前回の続きです。
今回もできるだけ専門用語を少なくするよう努めますが、VBAを触る上で避けては通れない「オブジェクト」と「プロパティ」という2つのワードだけは覚えて帰って頂きたいと思います。
・会社にいてもちょっとしたスキマ時間に実践できるよう、一回の分量をなるべく少なくしてお送りします。
・特別な準備は要りません。オフィスのPCにだいたい入ってるエクセルとGoogleクロームだけを使って作ります。記事も無料です。
前回の記事はこちら
今回の内容はこんな感じです↓
おさらい
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = Range("A1")
Dim message As String
message = "こんにちは"
rg.Value = message
End Sub
エクセルのA1セルに「こんにちは」と入力するこちらのプログラム。前回は大まかにどんな構造なっているのかをご説明しました。
前回確認したこと
・プログラムには全部の操作を丁寧に教えてあげる必要があること。
・コードは人間が読みやすいよう、きれいに整列させて書くこと。
・Sub~Endで大きな命令のまとまりを作ること。
・操作するものをあらかじめ変数で宣言してあげること。
Dim...変数の宣言(名前, 形)
Set...変数を設定(意味)
細かいことはまだ覚えなくてもよいのですが、最低限、VBAのコードを読むためには、こういう構造になっていることを知っておく必要があります。
どんなんだっけな...という方は、まだまだ全然焦る時間ではないので、一つ前の記事に戻ってみてください。
Setが要る、要らない問題
さて、操作したいエクセルのシート、セルまでは指定できたのですが、肝心の表示したいメッセージを定義するときに、困ったことが起こりました。
Dim message As String
message = "こんにちは"
これまで、Dimで変数の名前と形を宣言し、Setで意味を定義するという流れでやって来たのに、messageではSetが付いていません。
もちろんこれで合っているからプログラムが動くのですが、こういう風にルールにバリエーションを持たされると、覚える方はたまったものではありません。今日はこの違いについて解説してみたいと思います。
オブジェクト=操作する対象
プログラムにエクセルを操作させる命令を書く際、操作したいものが何なのかを、一つずつ変数で宣言して、機械に教えてあげる必要があることは、前回までで確認しました。
では、ここまでのコードで使った変数について、もう一度詳しく見てみることにしましょう。
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = Range("A1")
Dim message As String
message = "こんにちは"
rg.Value = message
End Sub
さすがに見慣れてきたと思いますが、このコードでは全部で3つの変数が宣言されていました。
ws...エクセルのアクティブなワークシート
rg...アクティブなシートのA1セル
message…"こんにちは"
さて、こう並べてみると、wsやrgはシートやセルといった、エクセル上で「操作できるもの」であるのに対して、messageだけはただの文字であることに気付きます。
例えば、エクセルを少しでも触ったことがあれば、セルにはいろいろな設定ができる事はご存じでしょう。入力されている文字にはじまり、縦横の幅や罫線の種類や色、塗りつぶしの色など、様々な項目があります。
このように移動やサイズ・カラーの変更、値などが操作できるもの、操作される対象のことを「オブジェクト」と呼びます(Object…英語、目的や対象のこと)。Setを付けるか付けないかは、だいたいこの一点だけで説明できます。
オブジェクトを変数に紐づける際は、目印としてSetが必要です。
一方で、オブジェクトではないもの、文字列や数字なんかのただのデータは、そのまま変数にイコールでくっつけます。
オブジェクトとそうでないものの分類については追い追いお伝えしていきますが、まずは先に進むためにこのルールだけ確認しておいて下さい。
書き方:オブジェクト変数
Dim 変数名 As オブジェクトの型
Set 変数名 = オブジェクト
書き方:オブジェクト以外の変数
Dim 変数名 As データの型
変数名 = データ
プロパティ=設定できる項目
さて、少し遠回りしましたが、いよいよ Sub test() の最後の行を読み解く時がきました。実はここを正しく理解するために、オブジェクトの概念は非常に重要なのです。
rg.Value = message
先ほど、オブジェクト=操作する対象とお伝えしましたが、操作されるということは、オブジェクトの中に変更される何かがあるということです。
それが、先ほど例に挙げたセルの色やサイズといった設定項目で、これをプログラミングの世界では「プロパティ」と呼びます(パソコンでも設定のことをプロパティと言ったりしますね)。
もちろん、A1のセルに入力される値、つまり、”こんにちは”という文字列を設定する項目も、このプロパティの一種です(Valueプロパティと呼ばれます)。
プロパティを呼び出すには、オブジェクトに続けて「.(ドット)」を付けて記述します。
書き方:プロパティの呼び出し
オブジェクト.プロパティ = 変更後の値
つまり上の最後のコードは、セルに「こんにちは」という値を設定しなさいという命令だったわけです。細かく説明すると下のように言うことができるのではないでしょうか。
まずA1のセルをrgという変数にセットしました。
「rgという変数をセルの領域(Rangeオブジェクト)の形で使うよ」
「rgは、アクティブなシートのA1というRangeオブジェクトだよ」
次に表示したい「こんにちは」をmessageという変数にセットしました。
「messageという変数を文字列の形で使うよ」
「messageは、”こんにちは”だよ」
最後に、rgの値(Valueプロパティ)に、変数messageを代入します。
rg.Value = message
rg(オブジェクト)のValue(プロパティ)はmessage(”こんにちは”)だよ。
あらためて読んでみる
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = ws.Range("A1")
Dim message As String
message = "こんにちは"
rg.Value = message
End Sub
では、最後に改めて上のコードを読んでみましょう。つかえず意味を読み取ることができるでしょうか?
「testという手続きの内容は以下の通り」
「ws という変数を ワークシートの形で宣言」
「ws は アクティブなシート」
「rg という変数を セル範囲の形で宣言」
「rg は A1のセル」
「message という変数を 文字列の形で宣言」
「message は ”こんにちは”」
「rgの Valueプロパティの値は message」
「以上」
こんな感じの意味で読めていたらだいたい正解です。
もしお時間があれば、ここを見ながら上の内容をもう一度見直して頂けると、より理解が進むと思います。
ちょっとついて来れていません!という方はお気軽にコメント欄か下のURL一覧からご質問下さい。もちろんnoteの会員さんでなくても大歓迎です。よりよいコンテンツにできるよう、ご協力宜しくお願い致します。
まとめ
お疲れ様でした。どうでしょう、プログラムがただの意味不明な呪文に見えていた頃とは、だいぶ世界が変わってきたのではないでしょうか。
どんな言語もそうですが、読んでだいたいの意味が分かるということは、教えてもらったコードやGoogleで検索してきたコードをコピペして、自分風にアレンジできる可能性があるということです。
Microsoft Excelは世界中で使われているソフトですから、そのリソースはこの記事に限らずWeb上に膨大に存在します。日本では比較的手ごろな値段でVBAの入門書も手に入ります。
とりあえず簡単なコードを読むことができた。とりあえず今は、その事実を噛み締めてください。
次回は一旦話を大きく戻して、私たちが作ろうとしているものは一体何なのかを考えていきます。ツールの全体像を把握して、道筋を立てていきましょう。
今回も長々とお付き合いいただきありがとうございました。
ご読了ありがとうございました。
こんなやまびこですが、人生の時間をほんのちょっとだけ分けてあげてもいいよという方は、フォローを頂けると大変喜びます。
【だいたい平日18時頃に更新中】
Twitter:
https://twitter.com/echoyamabiko
@echoyamabiko
note:
https://note.com/echo_yamabiko
はてなブログ:
https://echo-yamabiko.hatenablog.com/
※内容は基本的に同じなので、一番身近なアカウントでのフォローをお勧め致します。
【匿名での質問や感想はこちらが便利です】
やまびこへの質問箱:
https://peing.net/ja/echo_yamabiko?event=0
ちなみに
こんなところまで読んでいただいてありがとうございます。こちらは本編ではお伝えし切れなかった部分をメモ的に書いていく部分です。
よりシンプルで素早い理解のために端折ってしまった内容ですが、もしかしたら気になってしまう方もいらっしゃるかと思うので、ここに残しておくことにしました。
ちょっと高度なことをだらだらと書いているので、ここまでの内容でおなか一杯!という方は見ない方が良いかもしれません。
質問やコメントをいただければ随時こちらに補足を追加していく予定です。
なんでSubなの?Mainは?
多くの場合、VBAの手続きはSub(サブルーチン)で記述されます。実はVBA以外の言語ではメインとなるルーチンを中心に、サブルーチンで補助するようにプログラムを構築するものがあるようなのですが、VBAにはルーチン間の優劣を付けるオプションがありません。
優劣がないので全部サブというのは気持ち悪いのですが、Mainと打っても動作しないので仕方ありませんね。
え、ws使ってなくない?
結論から言うと、今回はあえてwsを使わずにできる事をしましたが、変数とオブジェクトの説明を簡潔にするためには仕方がなかったと言わせてください。
実は、操作するセルを定義するために使用した「Range("A1")」は、シートオブジェクトのプロパティだったのです。
え?ですから、”Range”はWorksheetオブジェクトのRangeプロパティです。
...
ちょっと混乱しますよね。今回はその混乱を避けるために、あえてwsを使わない方法を選びました。せっかくなのでご説明します。
オブジェクトのプロパティで呼び出せるものが、必ずしもただのデータであるとは限りません。だって、シートオブジェクトの中にはセルというオブジェクトが無数に存在するわけですから。
つまりA1のセルとは、正しくは下のように書くこともできるわけです。
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = ws.Range("A1")
「ws という変数を Worksheetオブジェクトの形で宣言」
「ws は アクティブなシート」
「rg という変数を Rangeオブジェクトの形で宣言」
「rg は wsの中にあるRangeオブジェクトのうち”A1”であるもの」
これでもしっかり元の通り動きます。
ただ、RangeオブジェクトはVBAでコードを組んでいると頻繁に使用するので、「突然Rangeと言われたら当然アクティブなシート内のことだ」とExcelが判断してくれていた、という仕掛けです。
複数のシート間でデータをやりとりする際なんかは、初心者のうちはこの辺を知らなかったりして、Rangeと書いているのに別のシートが操作されてしまう!なんてことがしばしばあるようです。
え、じゃあもしかしてシートもプロパティ??
そうです。ActiveSheetだって突然どこかかから湧いてくるわけではありません。Excelというアプリケーションの中の1シートオブジェクトであるというだけのことです。
これもExcelが「突然ActiveSheetと言われたら当然エクセルのことだ」と判断してくれているから成り立っていました。
エクセルアプリの中の、アクティブなシートの中の、A1セルの中の、値。
この構造を理解していると、あえて今回のコードを変数wsを用いずに書くことだってできます。試しに下のコードをコピペして実行してみてください。
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = ws.Range("A1")
Dim message As String
message = "こんにちは"
rg.Value = message
Set rg = Application.ActiveSheet.Range("A2")
message = "こんばんは"
rg.Value = message
End Sub
A2のセルに、変数wsを使わずに「こんばんは」と入れることができました。
プロパティの呼び出しでオブジェクトが返ってくる場合は、このように連続で更に下のプロパティを呼び出すこともできます。
また、Dimの行とSetの行が続いていなくとも、問題なく動作します。プログラムは上から順番に読まれるという決まりなので、必ずDimを先にする必要がありますが、間に別のことが書いてあっても読みに行くことができるのです。
もちろん、人間の目に優しいのがどちらかは言うまでもありませんが。
さて、そうは言っても、wsを使わなくとも値を入力できることは本編で実証済みでした。せっかくなので、変数rgもmessageも使わずに1行で書く方法も紹介しておきましょう。
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rg As Range
Set rg = ws.Range("A1")
Dim message As String
message = "こんにちは"
rg.Value = message
Set rg = Application.ActiveSheet.Range("A2")
message = "こんばんは"
rg.Value = message
Application.ActiveSheet.Range("A3").Value = "ずっとさようなら"
End Sub
今度はA3セルに「ずっとさようなら」と記入してみます。
ほかの行を全て削除してもA3セルの処理については問題なく動作するので、これでオブジェクトとプロパティの関係がなんとなく掴めてもらえるのではないかと思います。
Sub test()
Application.ActiveSheet.Range("A3").Value = "ずっとさようなら"
End Sub
処理の内容:
①Applicationオブジェクト(エクセルのこと)からActiveSheetプロパティでアクティブなworksheetオブジェクトを呼び出す。
②そのworksheetオブジェクトからRangeプロパティで”A3”という名前のRangeオブジェクトを呼び出す。
③そのRangeオブジェクトからValueプロパティでセルの値データを呼び出す。
④アクセスした値に”ずっとさようなら”という文字列を代入する。
1行で書けるからといって、こっちの方が便利ということはほとんどありません。Excel上の作業を自動化するということは、多くの場合で単純作業の反復を含みます。
この処理を例えば100セル分記述しますとなったら、変数を用いる場合とそうでない場合、どちらがより簡単で読みやすいかはご想像の通りです。
ほどほどに
マトリョーシカのように入れ子構造になったオブジェクト群に対して、自分が操作したいプロパティに正しくアクセスしていくことができれば、Excel上のだいたいの操作は自動化することが叶います。
とはいえ、この構造を正しくつかむ必要があるのは、あくまで複数の同列なオブジェクトを区別して扱う場合です。今回までの内容ではそこまでの理解は必要ないと判断して削ることにしました。
すっきりして頂けた方も、もやもやが増大した方も、とりあえず今はそれほど重要なことではないので、後々いっしょに確認できればと思います。
お疲れ様でした。また次回お会いしましょう。
記事は基本無料公開にしようと思うので、やまびこの明日のコーヒー代くらいは恵んでやってもいいぜという方は、お気軽にご支援ください。気長にお待ちしております。