韜晦日記

韜晦日記

Rietveldよりもプログラミングメインになりつつある

Rietveld解析初心者による備忘録とつぶやき

VBAについて No.1

RIETAN用のマクロを組むのにVBAを使います。一度も触ったことがないのでその都度調べながら組んでいますが、備忘録としてここに纏めておきます。
疲れたから途中までしか書いていないけど。悪しからず。

何はともあれ書いてみよう。関数の宣言


Sub hello()

 Range("A1")="Hello world"

End Sub

実行してみると、アクティブになっているA1セルに「Hello world」と表示されます。
VBAでプログラムを実行するときに、プログラムを構成する最小単位となるのがSubプロシージャです。プロシージャは[Sub----End Sub]で囲むことで一つの関数となります。
また、文頭の[ Sub ]の後に空白入れ関数名を定義します。このとき、特に理由が無ければ関数名の後ろに[ Sub test() ]と括弧もつけてあげます。この括弧は返り値(引数)を使うか否かを設定する部分です。C言語でいう、
int main()ですよね。

データ型 関数名(データ型 変数, データ型 変数)
int fa(int x, int b){
return 0;
}

みたいな。
関数の範囲指定にC言語では{ }を使いますが、VBAでは[Sub----End Sub]としている。といったところでしょうか。
VBAではSubプロシージャの他にもFunctionプロシージャもありますが、こちらはまた使うときに。まあ、Functionプロシージャは戻り値を返すのでよりC言語に近い気がしますよね。

Dim 変数の宣言


Dim 変数名 as データ型

データ型を宣言しない場合はVariantになる。

データ型名称格納範囲
Integer整数型-32,768 ~ 32,767
Long長整数型-2,147,483,648 ~ 2,147,483,647
Single単精度浮動小数点数-3.402823E38 ~ -1.401298E-45(負の値)
1.401298E-45 ~ 3.402823E38(正の値)
Double倍精度浮動小数点型-1.79769313486232E308 ~ -4.94065645841247E-324(負の値)
4.94065645841247E-324 ~ 1.79769313486232E308(正の値)
Currency通貨型-922,337,203,685,477.5808 ~ 922,337,203,685,477.00
String文字列型最大約20億文字まで
Date日付型西暦100 年1月1日~西暦9999年12月31日までの日付と時刻
Booleanブール型真 (True) または偽 (False)
Objectオブジェクト型オブジェクト
Variantバリアント型すべてのデータ
WorkbookExcelシートファイル名
Rangeセル選択セル範囲

まるで分からない、オブジェクトとプロパティ、そしてメソッド

「オブジェクト名.プロパティ」という解説はウソですよ:エクセルマクロ・Excel VBAの使い方
上記によると、「オブジェクト名.プロパティ」という解説はウソだそうな。
この道理で言ったら「Range("A1").Value」というオブジェクト式の「Range」を、オブジェクトと理解するのは自然であるが、「Range("A1").Value」のRangeは「Rangeオブジェクト」のRangeではないらしい。正しくは、「Rangeプロパティ」のRangeなのです。
よく使うRangeやCellsはプロパティで、コードが実行されたときにどちらもRangeオブジェクトを返す。

いや、どういうことうやねん。そもそもオブジェクトもプロパティも知らないで使っているるんだが。そして、極めつけは「Rangeオブジェクトを返す.」って…もうどういうことよ。

ということで調べた。

オブジェクト

オブジェクトはExcelファイル自身や、Worksheet、セルなど、目に見える対象物を表します。VBAで何かを操作するときの対象ですね。
そしてオブジェクトは階層構造になっており、階層をたどって目的のオブジェクトを取得します。

プロパティ

プロパティは設定情報を表し、そのオブジェクトの何を表したいのかを示します。
例えばこんな感じです。↓

オブジェクト プロパティ 説明
Worksheet Range セルまたはセル範囲を表す
Cells セルを表す
Rows 行を表す
Columns 列を表す
Range Range セルまたはセル範囲を表す
Cells セル方法を表す
Rows 行を表す
Columns 列を表す
EntireRow セル範囲を含む 1 行または複数の行全体
EntireColumn セル範囲を含む 1 列または複数の列全体
Offset オフセットの範囲
Resize サイズを変更
End 領域の終端のセル。Ctrl+方向キーに相当
SpecialCells 指定された条件を満たしているすべてのセル
MergeArea 結合セル範囲を表す
Next 次のセルを表す

ここでRangeオブジェクトにRangeプロパティがあるから、初心者的にはややこしくなっているんんですよね。ほんとにもう。
例えば以下のように書いた場合、


Worksheets("Sheet1").Range("A1").Value ="こんにちは"

RangeプロパティがRangeオブジェクトを返します。
でた、「返します。」だ。コードを書いているときはRangeプロパティとして扱っていますが、実行する際にVBAはRangeがどのオブジェクトに分類されるのか探索します。そしてRangeオブジェクトにRangeプロパティが属する為、Rangeオブジェクトを返しているということなのです。CellsやRange, Rows, Rowとプロパティをコードに書くと、実行の際にBVAが
「ああ、Rangeオブジェクトを参照すればいいんだなあ」と認識するわけです。変数型として宣言する場合のRangeを参照していることになります。この変数型を宣言(Dim)するときのRangeはオブジェクトですね。
そのうえで、このプロパティが働く場所をオブジェクトであるWorksheetで指示してあげる訳です。
そして、そしてプロパティは2種類あるのです。

  • これまで説明してきた、オブジェクトを参照、取得するプロパティ
  • Value, Textの様にデータを取得するプロパティ

ということで、上に書いたコードでは、「こんにちは」という値をRangeプロパティからRnageオブジェクトを参照してセルの指定、さらにWorksheetオブジェクトで入力するSheetを指定した結果として、Sheet1のA1セルに「こんにちは」と入力されるのです。

範囲選択(RangeとCells)

セルに値, 文字を入れる場合


Range("A1").Value="こんにちは"

Cells(1, 1).Value="こんにちは"

Dir関数


Dir[(pathname[,attributes])]

引数pathnameは省略可能。ファイル名やフォルダ名を表す文字列式を指定。
引数attributesは省略可能。取得するファイルの属性を表す数式もしくは定数を指定。

Dir関数の使い方

  1. ファイルの存在のチェック
  2. フォルダの存在のチェック
  3. あるパターンにマッチするファイル名の取得

など


AAA