2017年3月23日木曜日

もしも○○の時【If】

今回は【If】について解説していきたいと思います。

前回の答え


がその前に、前回の練習問題の答えは下記のコードになります。
Sub 繰り返し()
Dim s As Integer
For s = 1 To 20 Step 2
    Cells(s, 1).Value = s
Next
End Sub 
少し解説をすると、4行目【Cells(s, 1).Value = s】の部分では、セルのs行目の1列目=1行目の1列目のセルにsの値=1を入力します
2回目の繰り返しでは、sの値をプラス2ずつ進んでいきますので、2回目の繰り返しは3行目の1列目=A3のセルにsの値=3を入力します。
最後にsの値が20を超えたら繰り返しが終わりますので、Stepで2ずつプラスで進んでいると最後のsの値は19になりますので、19行目で処理を終了します。

この繰り返しについてはマクロの基本の動作として役に立ちますので、ぜひ覚えてくださいね。

If~End If


では【If】の解説に入りたいと思います。
まず【If】とは英語で「もしも」という意味を持っているそのままの意味でVBAでも使われます。
Excelの関数をやってる人はわかりやすいですよね。

例)If a.Value = "正解" Then
   MsgBox "正解"
  End If

上記の例を見ていきましょう。
まず【If a.Value = "正解" Then】の部分です。
これは日本語に訳すと「もしも:aの値が:正解:の時」という訳になります。
:で区切ってる位置をそのままIfの分に当てはめてあげるとわかると思います。

次の【MsgBox "正解"】はメッセージボックスに正解の文字を表示するだけになります。

最後の【End If】の部分に関してはEndの意味の通り、Ifステートメントの終わりを表します。

このIfに関してはよく使われますが、簡単なので多分すぐにクリアできると思います。

If~ElseIf~Else~End If

ただ、上記の例だとTrue(真)の場合しかかかれてないですよね?
ExcelのIf関数でも一緒ですが、False(偽)の場合はどう書くかというと

例)If a.Value = "正解" Then
    MsgBox "真"
  ElseIf a.Value = "不正解" Then
    MsgBox "真"
  Else
    MsgBox "偽"
  End If

上記の例の様に【Else】を使います。
まず【If a.Value = "正解" Then】の部分に関しては最初の解説と一緒なので省きます。

次の【ElseIf a.Value = "不正解" Then】ではIfがElseIfになっています。
「1行目のIf文がTrue(真)じゃなかった時:aの値が不正解:だったら」という順番になります。

最後の【Else】ですが、これはIfのある文で「Trueが一つもなかった時=False(偽)だった時」を表します。
なので上記の例だと「変数aの値が正解、もしくは不正解の時=Ifの返答がTrueになる時」はメッセージボックスには「真」が表示され、「どちらでもなかった時=Ifの返答がFalseになる」はメッセージボックスには「偽」が表示されます。

練習問題


では最後に練習問題です。
A1~A10までのセルに1~100までの好きな数字を入れてください。
1.セルの値が80以上の場合は「よく出来ました」を表示
2.セルの値が50以上80未満の場合は「あと一歩」を表示
3.セルの値が50未満の場合は「もう少し頑張りましょう」を表示
上記3つの条件をB1~B10までのセルに自動で入力されるマクロを組んでください。
ヒントは前回の繰り返し【For】を使用し、上記のIfの解説を応用すると組めると思います。

このIfステートメントは次回使用しますので、覚えたら次の繰り返し【For Each】へお進みください。

繰り返し【For Each】

今回はForEachについて説明します。
最後に良いお知らせもあるので見てみてくださいね。

前回の答え


では、まずこちらも前回と同様に練習問題の解説から入りたいと思います。
正解のコードは下記になります。
Sub 評価()
Dim s As Integer
For s = 1 To Range("A1").End(xlDown).Row
    If Cells(s, 1).Value >= 80 Then
        Cells(s, 2).Value = "よく出来ました"
    ElseIf Cells(s, 1).Value >= 50 Then
        Cells(s, 2).Value = "あと一歩"
    Else
        Cells(s, 2).Value = "もう少し頑張りましょう"
    End If
Next
End Sub
まず繰り返しの部分ですが、【For s = 1 To Range("A1").End(xlDown).Row】と入力していますが、Range("A1").End(xlDown).Rowの部分は10でも正解です。
以前セルの範囲選択と可変式選択で説明したEnd(xlDown).Rowを使うことで可変式の範囲選択にする事ができますので、もし11行目にも入力していた場合、11行目も処理してくれるようになります。
このようにEnd(xlDown).Rowは自動で処理範囲を変えてくれるので大変便利です。
なのでぜひ覚えて活用してくださいね。

ではIf文の解説に戻って、1つ目の【If Cells(s, 1).Value >= 80 Then】ですが、これは「1列目1行目のセル=A1のセルの値が80以上の場合」という事になり、次の行の【Cells(s, 2).Value = "よく出来ました"】では「IfがTrue(真)の時、2列目1行目のセル=B1のセルによく出来ました」を入力する事になります。

ElseIf Cells(s, 1).Value >= 50 Then】は1つ目と同じで値が50に変わっただけになります。

最後の【Else】ですが、こちらは「上記2つの条件に当てはまらなかった=False(偽)の時」ということで、今回の場合、49以下の時という事になります。
このように最後の条件はElseのみの入力でFalse(偽)を取得する事で処理が出来るなら、コードが短くなりますので、Flase(偽)を活用すればいい時はElseだけの使用にして、コードを短くしてあげましょう。

For Each

では話を戻して【For Each】の解説に入りたいと思います。
まず、For Eachの基本動作として変数宣言したオブジェクト繰り返したい範囲のオブジェクトを代入しながら繰り返しの範囲が終わるまで繰り返すという動作をします。

このFor Eachに関しては、このブログの最終目標であるInternetExplorerの自動操作で確実に使うことになります。
上記の「」の中を理解しないとInternetExplorerの自動操作は出来ないので、確実に理解してください。
文字の色でグループ分けしてますので、解説の色とあわせながら進んでいくとわかりやすくなると思います。
では例題として下記のコードを見てください。

例)Sub オブジェクトの検索()
  Dim a As Object
  For Each a In Range("A:A")
    If a.Value = "ここだよ!" Then
          MsgBox "ここだよ!が入っているのは " & a.Address & " です。"
      End If
  Next
  End Sub

まずは【For Each a In Range("A:A")】から説明したいと思います。
For Eachの基本の形として【For Each オブジェクト変数 In 繰返し範囲のオブジェクト】という表記をします。
上記の例でいうと、オブジェクト変数の部分はDimを使って変数として宣言されている、aが当てはまります。
繰返し範囲のオブジェクトの部分は、「どのオブジェクトを繰り返したいか」になりますので、今回Range("A:A")の範囲を繰り返すようにしています。

次に【If a.Value = "ここだよ!" Then】に関しては、「変数aのオブジェクトに入ってるセルの値が「ここだよ!」の場合」という事になります。

最後に【MsgBox "ここだよ!が入ってるのは " & a.Address & " です。"】です。
こちらはオブジェクトaのセルの位置をメッセージボックスで表示しているだけになります。

上記のまとめとして、For Eachは「緑の文字の範囲を順番に、青の文字に入れて処理をしていく」という事になります。
For EachにIfを組み合わせる事で「aに代入されたオブジェクトが何々の時」という処理を実行できるのです。

実際に上記のコードを実行する場合は、A列の適当な位置に「ここだよ!」を入力してください。
その後、上記のコードを実行すると「ここだよ!」が入ってるセルの位置をメッセージボックスで表示します。


このFor Eachは理解するまでが難しいと思いますが、For Eachを使いこなせるようになる事でVBAの動作の幅が一気に広がりますので、頑張って覚えてくださいね。

練習問題


では最後に練習問題、と言いたいところですが、今回は内容が難しいので上記の解説を少し応用して、「A列をB列に変えてみる」や「列ではなく、行で試してみる」などして徐々に感覚を掴んで欲しいと思います。

因みに、ここまでの3種類のステートメントをマスター出来た方へお知らせです。
実はたった3種類のステートメントしかマスターしてないのに
InternetExplorerの自動操作は出来てしまうんです。
もちろん他の
ステートメントもマスターする事で操作の幅はもっと広がりますが、まずはVBAを楽しいものとして捉えてもらう為にも次回はちょっとしたマクロを作ってみたいと思います。
コピペではなく、自分で打ちながら指で覚えてくださいね。

変数のデータ型

変数宣言【Dim】にもデータ型の表は記載してますが、そのデータ型の説明という事なので、この記事にもデータ型の表を記載しておきますね。

データ型名前消費メモリ格納できるもの
Integer整数型2byte-32,768~32,767まで
Long長整数型4byte-2,147,483,648~2,147,483,647まで
Single単精度浮動小数点数型4byte-3.402823E38~
-1.401298E-45(負の値)
1.401298E-45~
3.402823E38(正の値)
Double倍精度浮動小数点数型8byte-1.79769313486232E308~
-4.94065645841247E-324(負の値)
4.94065645841247E-324~
1.79769313486232E308(正の値)
Currency通貨型8byte-922,337,203,685,477.5808~
922,337,203,685,477.5807
String文字列型2byte指定した文字列
Date日付型8byte日付と時間
Objectオブジェクト型4byteオブジェクト
Variantバリアント型16byteほぼ何でも
Booleanブール型2byteTrueまたはFalse

では上記の表のデータ型についての説明に入ります。

Integer、Long


まず【 IntegerLong 】についてです。
Integerは難しく考える事はなく、単純に整数を入れることができる枠ということになります。
ただし、-32,768~32,767という数字を超えてしまう場合は使えません。
これからマクロを組む時、例えばA1のセルからA100のセルまで1から数字を入れていくとします。
その時繰り返す数は100回なので32,767を超えていませんのでLongより消費メモリが軽いIntegerを使うと最適ですよね?
でも金額の計算をしてる場合、32,767円は簡単に超える可能性が高いと思います。
もし32,767を超えた場合、Integerの箱から溢れてしまいますので、そういう時に使うのがLongになります。
このLongの場合、2,147,483,647まで使えますので20億を超えない限り使えなくなることはありません。
なので莫大な数字を扱う場合以外はInteger、莫大な数字を扱う場合はLongにするといいでしょう。

Single、Double


次に【 SingleDouble 】についてです。
このSingleとDoubleに関しては、パソコンの専門的な知識が必要になりますので詳しい説明は省きます。
簡単に説明するとSingleは整数と小数合わせて7桁、Doubleは整数と小数合わせて16桁まで扱えます。
また、小数点を扱う場合、SingleやDoubleを使わないといけないということはなく、むしろSingleやDoubleを使った方がごくわずかな誤差などが出やすいため、計算などはStringでもできますのでそちらをお勧めします。

Currency


次に【 Currency 】についてです。
こちらもSingleやDoubleと同じで使用する機会が少ないものになり、同じようにパソコンの専門的な知識が必要になりますので詳しい説明を省きます。
Single、Double、Currencyは全て2進数や10進数などが絡んできますので、詳しく知りたい方はネットで調べてみてくださいね。

String


次の【 String 】は一番使う事になってくると思います。
このString型は数字でも記号でも平仮名やカタカナ、漢字まで文字なら何でも入れてくれるのです。
記載方法はダブルクォーテーションで囲みます。
ただし、記号を使う際にダブルクォーテーションを使いたい場合はダブルクォーテーションを2重にします。
例1)ダブルクォーテーションを使わない場合
変数名 = "このサイトわかりやすい?笑" → このサイトわかりやすい?笑
例2)ダブルクォーテーションを使う場合
変数名 = ""ここのサイトわかりやすい?笑"" → "このサイトわかりやすい?笑"

Date


次に【 Date 】についてです。
こちらも人によっては使うことも多いかと思いますが、個人的にはFormatなどの関数を利用することのほうが多いです。
こちらは日付と時間の表記に使うものになります。
日付は西暦100年1月1日 ~ 西暦9999年12月31日まで
時間は0:00 ~ 23:59までを扱う事ができます。

Object


次に【 Object 】についてです。
このObjectはこのサイトのテーマでもあるInternetExplorer(IE)の自動操作では特に一番重要になります。
なのでIEの自動操作がしてみたい方はよく覚えておいてくださいね。
もちろん、Excelの中でも重要になるので出来るだけ覚えておいてください。
Objectとは簡単に言うとパーツです。
例えばExcelのA1とかA2とかのセルもObjectですし、このサイトにある表や今このサイトを見てくださってるブラウザ(IEだったりChromeだったり)もObjectです。
サイトを見ていて文字を打てる部分、検索などのボタンなどもObjectです。
つまり何かを動かそうと思ったらパソコンに「○○というObjectを動かして」と指示をしないといけないのです。
これからVBAを組む中でセルの指定だったりIEを選んだりする際に意識していくとわかりやすいと思います。

Varinat


次に【 Variant 】についてです。
これは特に何も考えることはないです。
単純にVariantを指定してあげたら後はパソコンが自動で適切な型になってくれるので、もしどの型に入れていいかわからない時はVariantを使うといいと思います。
ただし、消費メモリが一番大きいので処理速度は一番遅いです。
なので型がわかる時には出来るだけ適切な型を使ってあげましょう。

Boolean


最後に【 Boolean 】についてです。
これはIfなどのステートメントを使いだすと使用する機会があるかと思いますが、BooleanはTrueもしくはFalseを格納します。
Trueとは日本語では「真」と言い、正しいという意味です。
Falseとは日本語では「偽」と言い、間違っている時です。
この辺りについてはIfステートメントの時にわかるようになると思います。
Booleanについては自分がTrueの値が欲しかった時やFalseの値が欲しかった時に使います。

繰り返し【For】

変数の宣言まで出来たら次は繰り返しの処理を覚えましょう。
以前VBAとは?の記事で実行したセルの色付けのコードを見てください。
For ~ To ~とありますよね?
この時、A1からD1まで繰り返し、A2からD2まで繰り返し・・・・A14からD14まで繰り返しという感じで、横に4回同じ処理を繰り返した後、下に1行下がって、また横に4回同じ処理を繰り返すという動作になっています。
このように繰り返しの作業をする事で手動で1つ1つ進めるより格段に処理が早くなるのです。

For~To~Step~Next

例)For s = 1 To 100 Step 5
    処理内容
  Next

まず【For s = 1】については「これから繰り返しの処理を始めますよ」の合図です。
s = 1の部分に関してはsは変数なのでDimで宣言した変数名を使用し、次の1はスタート位置です。

次の【To 100】については「ここまで繰り返しますよ」の終着点を決める事になります。
上記の例の場合、sの変数に入ってる「1番からToの後の100番目まで処理しますよ」ということになります。

次に【Step 5】については「何個飛ばしで進めますよ」の意味になります。
上記の例では「1番から100番まで5個飛ばしで進めていきますよ」の意味になります。
1番が終わったら5個飛ばして6番、6番が終わったら5個飛ばして11番・・・・となり96番が終わると101番になり、100番を超えたので終了という事で、合計20回の処理になります。

最後に【Next】をつけて「ForからNextまでの間の処理が終わったらForに戻りますよ」の意味になります。
これはForとセットになってるので、Forが付いたら最後にNextと覚えておいてください。

このように繰り返しのステートメントをマスターする事で、今まで同じ処理を毎日繰り返していたのがマクロによって数秒で終わるようになるのです。

練習問題

最後に練習問題です。
下にある画像の様にA1のセルに1をA3のセルに3を、というように19行目まで1つ飛ばしでセルの行数の数字が入るようにVBAを組んでみてください。
上の文章にはヒントだらけなのでわからなければ読み直してみてくださいね。


※答えは次回の記事に載せておきます。

変数の代入

変数宣言【Dim】で変数を宣言したら次にすることは変数の代入です。
変数に値を代入するには【】を使用し、オブジェクトを代入する場合には【Set】を使用します。

例1)Dim sample As String
       sample = "値の代入"
例2)Dim sample As Object
     Set sample = Range("A1")

では上記の例1から説明します。
例1ではsampleというString型の変数を用意し、その変数に「値の代入」という文字列を代入してます。
VBAでは=は等号だけではなく、代入の場合も使うのです。

次に例2ではsampleというObject型の変数を用意し、その変数に「A1のセル」を代入しています。
オブジェクト型の場合、変数の代入には=だけではなくSetも必要になるので注意してください。

また次回以降に出てくるForやForEachのステートメントに変数を使う場合は変数の代入方法が異なりますので、これからの記事ごとの変数の宣言にも注意しながら勉強してくださいね。

VBAの書き始め【Sub】

まず前提として、VBAを実行した際、かならず上から順番に実行していくようになっています。
その為、処理の順番を間違えると結果が変わってきてしまうので注意が必要です。

ではこれからVBAを書いていく際にまず大まかなイメージとしては一つの大きい棚を用意します。
その中に次回以降出てくる変数やステートメントなどの引き出しを作ってあげる事で、VBAは一番上の引き出しから順番に引き出しを開けて中身を処理したら次の引き出しにという感じで処理をしてくれるようになるのです。

ではまずVBAの書き始めに必ず入るプロシージャというものを説明します。
プロシージャは大きく2つに分けられます。
1つ目はタイトルにもある【Subプロシージャ】、2つ目は【Functionプロシージャ】です。
他にも【Eventプロシージャ】などもありますが、まずは【Subプロシージャ】を覚えましょう。

Subプロシージャはこれから自分が作成するマクロの名前にもなります。
この名前は自分がマクロを実行する際にわかりやすい名前をつけましょう。
ただし、数字から始まる場合アンダーバー以外の記号は使うことは出来ませんが、途中や最後に数字を入れることや漢字や平仮名、カタカナは使うことが出来ます。

例)Sub Sample()
    ここに処理を記載
      End Sub

という形でSubで始まり、例ではSampleと書いてある部分に好きな名前をつけ、最後にEnd Subで終わるという流れになります。
()は変数の受け渡しの際に利用しますが、変数の受け渡しに関しては使わない場合もありますので今は空白で大丈夫です。
また変数に関しては変数宣言【Dim】に記載していますのでそこまで頑張って進んでいきましょうね。

Functionプロシージャに関しては次回のVBAの書き始め【Function】で説明します。
なので、今はSubプロシージャというもので棚を作るというところまで覚えて次の記事に進んでください。

2017年3月21日火曜日

VBAの演算子

代入演算子


演算子 意味 使用例
= 左辺に右辺を代入する a = 1

算術演算子


演算子 意味 使用例
+ +の左右の値を足す 1 + 1 = 2
- -の左右の値を引く 1 - 1 = 0
* *の左右の値を掛ける 1 * 1 = 1
/ /の左右の値を割る 7 / 2 = 3.5
¥の左右の値を割り、商を返す 7 ¥ 2 = 3
Mod Modの左右の値を割り、余りを返す 7 Mod 2 = 1
^ ^の左辺を右辺のべき乗する 2 ^ 3 = 8

比較演算子


演算子 意味 使用例
= 等号 1 + 1 = 2
<> 不等号 2 + 2 <> 2
< 左辺より右辺の方が大きい 1 < 2
> 左辺より右辺の方が小さい 2 > 1
<= 右辺は左辺以上 1 <= 2
>= 右辺は左辺以下 2 >= 1
Is Isの左右のオブジェクトが同じオブジェクトか比較 Range("A1") Is Cells(1, 1)
Like 左辺の文字列と右辺の文字パターンを比較 "あいうえお" Like "あいうえお"

Likeの文字パターン


文字パターン 意味 True(真)になる値
* 文字列(ワイルドカード) Like あいう* = あいうえ、あいうえお、あいうえおか
? 1文字 Like あいう? = あいうえ、あいうお、あいうか
# 数字 Like #1 = 01,11,21・・・

文字列連結演算子


演算子 意味 使用例
& &の左右の文字列を連結させる あいう & えお = あいうえお
+ +の左右の文字列を連結させる あいう & えお = あいうえお

論理演算子


演算子 意味 True(真)になる条件
And 左辺、右辺ともにTrue(真)の時 1 < 2 And 2 < 3
Not 条件がFalse(偽)の時 Not 1 > 2
Or Orの左辺、右辺どちらか1つでもTrue(真)の時 1 < 2 Or 2 < 1
1 < 2 Or 2 < 3
Xor Xorの左辺、右辺どちらかがTrue(真)、どちらかがFalse(偽)の時 1 < 2 Xor 2 < 1

繰り返し【Do Until】

今回の記事では、前回の【Do While】と似たもので【Do Until】を紹介したいと思います。

前回の答え


が、まずは前回の練習問題の答えから

練習問題
1.ExcelのA列、どこでもいいので好きな文字を入れてください。
2.自分でDoを使ってA列に入れた文字の上まで何かの文字を入れて繰り返しをしてみてください。


という問題でしたね。

正解のコードはこちらです。
Sub DoWhile()
Dim s As Integer
s = 1
Do While Cells(s, 1).Value <> "↑ここまで↑"
    Cells(s, 1).Value = "まだ?"
    s = s + 1
Loop
End Sub
では解説していきます。

【Dim s As Integer】
【s = 1 】
ここは何度も説明しているのでわかりますよね?
わからない方は変数宣言【Dim】を確認してください。

【Do While Cells(s, 1).Value <> "↑ここまで↑"】
ここがポイントです。
s行目、1列目のセルの値が「↑ここまで↑」ではない間、繰り返しますよ
という事になります。

もしValue <> "↑ここまで↑"をValue = "↑ここまで↑"にしてしまった場合、セルの値が「↑ここまで↑」の間、処理をするということになりますので、「特定の文字が入ったセルまで、何か文字を入れてください」という今回の問題では不正解になります。

【s = s + 1】
これはセルの行数を変更する為、変数の値を変えてあげるという処理になります。

今回の答えはA列に「↑ここまで↑」以外の文字があっても、その文字まで繰り返す、という意味でこういう答えにしましたが、単純に「空白のセルの間」という処理にする場合は下記の様にコードを変えてあげることで処理が出来ます。
Sub DoWhile()
Dim s As Integer
s = 1
Do While Cells(s, 1).Value = ""
    Cells(s, 1).Value = "まだ?"
    s = s + 1
Loop
End Sub
この様に、赤文字の部分を変更してあげる事で「空白の間、処理を実行します」という内容に変わるので、文字が入っていたら繰り返しが終了します。

ここまでは大丈夫でしょうか?
VBAを始めたばかりでは難しいとは思いますが、何度も失敗しながら練習して、マスターしてくださいね。

Do Until


では本題の【Do Until】の解説に入りたいと思います。
まずはコードの例を見てください。

例)
Sub DoUntil()
Dim s As Integer
s = 1
Do Until s > 10
    Cells(s, 1).Value = s
    s = s + 1
Loop
End Sub

【Dim s As Integer】
【s = 1】
ここは上記でも説明したように、何度も説明しているので、変数宣言【Dim】をご覧ください。

【Do Until s > 10】
ここはsに代入されてる値が10より大きくなるまで繰り返す」という処理になります。
Untilは、○○になるまで処理を実行というステートメントになります。

【Cells(s, 1).Value = s】 
【s = s + 1】
 こちらは前回の繰り返し【Do While】と同じで「s行目、1列目のセルにsに代入された値を入れる」
「sの値を今のsの値+1する」という処理になります。

最後に【Loop】 で閉じて、【Do Until】に戻って処理を実行するかの条件を確認します。

前回のWhileと今回のUntilの違いですが、Whileは前回の練習問題の解説でも説明したように、〇〇の間、処理を実行します」 という意味になります。
ですが、Untilは〇〇になるまで、処理を実行します」という意味になるのです。

つまり、【Do Until s > 10】【Do While s <= 10】は同じ処理を実行します。Untilの場合、「sが10より大きくなるまで=sが11になったら終了」
Whileの場合、「sが10までの間=sが11になったら終了」
という意味になります。

なのでどちらのステートメントを使っても、結果は同じになります。
ただ、例えば「○○の範囲を繰り返し」という時にはWhileを「○○になるまでは繰り返し」という時にはUntilを、という様に自分なりの使い分けを考えてみるのもいいかもしれませんね。

また、前回の繰り返し【Do While】でも説明したようにDoの後にUntilを付けた場合、処理実行前に条件を確認します。
Loopの後にUntilを付けた場合、処理実行後に条件を確認します。

最後に


最後におまけです。
前回の練習問題の「特定の文字が入ったセルまで、何か文字を入れてください」という問題を今回解説したUntilを使用して解答した場合、どういうコードになるかを解説します。
Sub 解答()
Dim s As Integer
s = 1
Do Until Cells(s, 1).Value = "↑ここまで↑"
    Cells(s, 1).Value = "まだ?"
    s = s + 1
Loop
End Sub
この様に、繰り返しの条件が【Do Until Cells(s, 1).Value = "↑ここまで↑"】となります。
上でも解説している様に、Untilの場合、「○○になるまで」という意味なので、【s行目、1列目のセルの値が「↑ここまで↑」になるまで繰り返し】という処理をします。

2017年3月17日金曜日

繰り返し【Do While】

VBAでは繰り返しのステートメントは大きく分けて3つほどあります。
今まではForFor Eachを紹介しました。

Do While


では今回はDo Whileを紹介していきたいと思います。

では早速簡単な例を出してみましょう。

例)Dim s As Integer
   s = 1
   Do While s < 11
       Cells(s, 1).Value = s
       s = s + 1
   Loop

【Dim s As Integer】
【s = 1】
この二つはもうわかりますよね?
sというInteger型の変数に1を代入しています。

【Do While s < 11】
このDoが繰り返しの始まりになります。
次のWhileは繰り返しを終了させる条件を記載する場所になります。
このコードでは【s < 11】が繰り返しの終了条件になり、この繰り返しの条件がTrue(真)になった時点で繰り返しが終了します。
なのでsの値が11になった時点で、Whileの条件がTrue(真)になるので、繰り返しが終了します。
つまり、繰り返しの回数は10回という事になります。

【Cells(s, 1).Value = s】 
これも今まで何度かやりましたね。
「s行目、1列目のセルにsに代入されている値を入れる」という処理です。

【s = s + 1】
これが意外と抜けやすいところです。
今までのForFor Eachでは「ここから、ここまで 」と繰り返しの範囲を決めていましたよね?
例えばFor s = 1 To 10とすると、「自動でsの値が+1ずつしていき、10になると終わる」というようになっていました。

ですが、Doの場合、Whileの後の条件がTrue(真)になるまで繰り返します。
ということはDoではsの値を+1するという事はしないのです。その為、自分で変数sに、今変数sに入ってる値+1しないとsはいつまで経っても1のままなので終わることが出来ません。
なので、【s = s + 1】が必要になります。

【Loop】
繰り返しの上の枠が【Do】であるように【Loop】は繰り返しの下の枠になります。
つまりDo~Loopまでの範囲が繰り返しの対象になりますので、「Doに戻ってください」の意味になります。

この【Do】のコードを簡単にまとめると「s行、1列目のセルにsに代入されてる値を、sが11になるまで繰り返す」と言う事になります。

またWhileに関してはDoの後、もしくはLoopの後のどちらかに記載をします。
Doの後にWhileを記載すると繰り返しに入る前に条件を確認し、Loopの後にWhileを記載すると処理が終わった後に条件を確認します。

その為、条件に合わなかった時、処理を始めたい場合はDoの後にWhileを記載します。
逆に1回目の処理を実行した後に条件に合わなければ繰り返したい時、Loopの後にWhileを記載します。

このDo While~LoopやDo~Loop Whileを上手く利用する事で、特定のセルまで繰り返したり、文字列などからセルを検索したりも出来るようになります。
また、IEの読み込み待ちにも、このDo Whileが使われています。

練習問題


では最後に練習問題
1.ExcelのA列、どこでもいいので好きな文字を入れてください。
2.自分でDoを使ってA列に入れた文字の上まで何かの文字を入れて繰り返しをしてみてください。


コード実行後はこのようになれば正解です。
また、実際のコードは次回の繰り返し【Do Until】に記載します。

2017年3月14日火曜日

セルの範囲選択と可変式選択

前回セルやワークシートの指定の応用として、範囲指定をする方法を説明したいと思います。

まずは例題としてA1からC3までの範囲を選択するVBAを紹介します。

例)Range("A1:C3").Select

これはExcelの関数を使える人ならすぐにわかりますよね?
単純に「:」を間に入れてあげることで範囲を選択します。
その後の「.Select」を入力する事で、「その範囲を選択してください」ということになります。

では行や列を選択する場合はどうするかというと

例1)Rows(1).Select
例2)Columns(1).Select

まずは例1の【Rows】から説明するとRowsとは行を意味しますので、括弧の中にある1番目の行という事で1行目を選択します。

次に例2の【Columns】ですがこちらは列を意味しますので、括弧の中にある1番目の列という事でA列を選択します。

では少し難しくして可変式の範囲選択をする方法を紹介します。
が、その前に2つのポイントを覚えないといけません。

まず覚えて欲しいのが【Row】と【Column】です。
Rowは行数、Columnは列数を表します。
この時、先程のRowsやColumnsの様にsは付いていない事に注意してください。

2つ目に【End(xl○○)】です。
この○○にはDownやUp、ToRightやToLeftが入ります。
意味は○○の方向の最後を意味します。
ちなみに最後と言っても入力があるセルの最後を取得しますので、もし空白のセルの最後を取得したらExcelの一番最後の数字を取得してしまうので注意してください。

では上記の2つのポイントをRangeと組み合わせて文字が入ってる一番下の行まで範囲選択するコードを書くと
Cells(Range("A1").End(xlDown).Row, 1).Select
となります。

例えばA1からA20のセルまで何かの文字が入っていた時、上記のコードではA1からA20のセルを選択します。
この「.End(xlDown).Row」は、後ほど解説している繰り返し【For】と組み合わせる事で「入力のあるセルの数だけ繰り返す」という使い方も出来るようになるので覚えておいた方がいいかと思います。

では最後にRangeの中にCellsを入れた範囲選択を紹介します。

例)Range(Cells(1, 1), Cells(3, 3)).Select

上記の例だとA1からC3の範囲を選択します。
Rangeの中にCells(1, 1)=A1のセルとCells(3, 3)=C3のセルを「,」で区切る事でその範囲を指します。
最後に「.Select」をつけることで範囲選択をするという事になります。

ただ、この方法を使うなら1番目に紹介した【Range("A1:C3")】の方が簡単なのであまり使うことはないと思いますが、稀に繰り返し【For】等を使用する時にセルの選択に変数を使用する場合があり、その際に活用する事があるので、また使う時があればこのサイトへ来て頂けたらと思います。

IE操作【表の取り出し】

ここまではVBAを使ったIE上のユーザーフォームの自動操作を説明してきました。
 今回はIE上にある表のデータをExcelに抜き出してくるというマクロを解説していきます。

ではサンプルページの送信ボタンの下にある表をExcelに抜き出していきたいと思います。
表の取り出し用マクロのコードは表の取り出し【コード】に記載、HTMLはIE操作用テストページ【HTML】に記載しています。
表のHTML
<table border="1px" id="list">
  <tbody>
    <tr>
      <th>種類</th>
      <th>原価</th>
      <th>販売額</th>
    </tr>
    <tr>
      <th>軽油</th>
      <th align="right">80円</th>
      <th align="right">100円</th>
    </tr>
    <tr>
      <th>レギュラー</th>
      <th align="right">100円</th>
      <th align="right">120円</th>
    </tr>
    <tr>
      <th>ハイオク</th>
      <th align="right">120円</th>
      <th align="right">140円</th>
    </tr>
  </tbody>
</table>
VBAコード
Sub 表の取り出し()
Dim objIE As Object
Dim tbl As Object
Dim cel As Object
Dim x As Integer
Dim y As Integer
Dim snam As String

'新しいシートを作成し、名前を変更する
Worksheets.Add
snam = ActiveSheet.Name

'InternetExplorerをobjIEに代入し、IEのプロセスを起動
Set objIE = CreateObject("InternetExplorer.Application")
    
    'IEを可視化するか = はい
    objIE.Visible = True
    
    'IEのリンク先URLはB1のセルのURL
    objIE.Navigate Worksheets("情報").Range("B1").Value
    
    'IEの表示待ち
    wait objIE
    
    'objIEのHTMLの中からtableのタグをobjに代入しながら確認
    For Each tbl In objIE.Document.GetElementsByTagName("table")
        
        'objに代入されたtableタグのIDがlistの場合
        If tbl.ID = "list" Then
            
                'tblに代入されているtableタグにあるセルをExcelに移し変える
                
                '変数yに0を代入、tblに代入されているtableの行数まで繰り返す
                For y = 0 To tbl.Rows.Length - 1
                    '変数xに1を代入、tblに代入されているtableの列数まで繰り返す
                    For x = 0 To tbl.Rows(y).Cells.Length - 1
                        'Excelのx列、y行の位置にtableタグのx+1列、y+1行のセルの値を入れる
                        Worksheets(snam).Cells(y + 1, x + 1).Value = tbl.Rows(y).Cells(x).InnerText
                        '変数aの値をプラス1することで次のセルに進む
                    Next
                Next
        End If
    Next
    
    '終了のメッセージボックスを表示
    MsgBox "終了"
    
    'objIEに代入したInternetExplorerを閉じる
    objIE.Quit
    
    'objIEを空にする
    Set objIE = Nothing

End Sub

Sub wait(objIE As Object)
'objIEに代入されたInternetExplorerがビジー状態、もしくは読み込み待ちの間、処理を待つ
Do While objIE.Busy Or objIE.ReadyState < 4
    DoEvents
Loop
End Sub

HTMLの基礎


まず、HTMLの基礎として、tableタグで枠を作ります。
次にtbodyタグで「ここが tableの中身ですよ」と教えてあげます。
tbodyの中にtrタグ=行、thタグとtdタグ=セルを入れることで表が出来上がります。

マクロではtrタグやthタグとtdタグで出来上がったtableタグの表を、Excelのセルと同じような表として認識することが出来ます。
その為、tableタグを取得し、CellsやRowsなどでセルの位置を指定することが出来るのです。

ワークシートの作成~シート名の取得


では実際のコードの解説に入りたいと思います。
※VBAのコードより、変数の宣言については、過去の記事でも多数説明している為、省略します。

【Worksheets.Add】
上記のWorksheets.Addについては「Worksheetを加えてください」の意味になります。つまり、新しいシートを作成します。

【snam = ActiveSheets.Name】
次にsnamの変数にアクティブになっているシート=先程新しく作成したシートの名前を代入します。

IEの起動~状態~サイトへのアクセス~読み込み待ち


【Set objIE = CreateObject("InternetExplorer.Application")】
 こちらはIE操作【IE起動~読み込み】でも説明したようにobjIEというオブジェクト変数にInternetExplorerを代入してます。

【objIE.Visible = True】
次のVisibleは可視化なので、Trueで表示、Falseで非表示でIEを起動します。

【objIE.Navigate Worksheets("情報").Range("B1").Value】
最後にNavigateでB1のセルの値に入っているURLにアクセスします。

【wait objIE】
上記でIEの読み込み待ちをします。

ここまでは前回までの記事のおさらいのような内容なので大丈夫ですかね?
次から少しずつ変わっていきます。

表の取り出し


【For Each tbl In objIE.Document.GetElementsByTagName("table")】
上記でtableタグをtblの変数に代入しながら探します。

【If tbl.ID = "list" Then】
tblに代入されたtableタグのIDがlistの時、次の処理を実行します。

【For y = 0 To tbl.Rows.Length - 1】
変数yの値の0からtblに代入されたtableタグの表の行数まで繰り返します。
※Rows.Lengthで 行数を取得、その後に付いてる-1は、VBAではExcelの行数や列数は1から始まりますが、IE上の表やタグの数などは0から始まります。
その為、0からスタートし、最終行-1まで繰り返すという表記になります。

【For x = 0 To tbl.Rows(y).Cells.Length - 1】
変数xの値の0からtblに代入されたtableタグのy行のセルの数だけ繰り返します。
※こちらもIEの表のセルなので-1を忘れないようにしてください。

【Worksheets(snam).Cells(y + 1, x + 1).Value = tbl.Rows(y).Cells(x).InnerText】
上記が少し難しいのですが、まず、Worksheets(snam)で最初にsnamの変数に代入した新しいシートの名前のワークシートを指定し、Cells(y + 1, x + 1).Valueで、新しいシートのxとyの値+1のセルの位置に入力します。
入力する内容はtblに代入されたtableタグy行目左からx番目のセルの文字列です。

ここが少しわかりにくいと思いますが、コードの色分けの様に「xとyを使い、同じセルの位置に表を取り出すように」ということを意識しながら実行してみるとわかると思います。

終了のメッセージ~オブジェクトの解放


最後に前回と同様に下記3つのコードを実行し、終了のメッセージを出した後、IEを閉じ、IEの解放を行ないます。
【MsgBox "終了"】
【objIE.Quit】
【Set objIE = Nothing】

1つの記事にまとめての解説なので見づらかったりするかと思うのですが、IEの基本操作として、「For Eachでタグを選択し、Ifで操作したいタグなら中身を実行する」ということを忘れなければ、操作は出来ると思います。
後は発想力を使って自分なりでいいのでコーディングしてみてください。

表の取り出し【コード】

Sub 表の取り出し()
Dim objIE As Object
Dim tbl As Object
Dim cel As Object
Dim x As Integer
Dim y As Integer
Dim a As Integer
Dim snam As String

'新しいシートを作成し、名前を変更する
Worksheets.Add
snam = ActiveSheet.Name

'InternetExplorerをobjIEに代入し、IEのプロセスを起動
Set objIE = CreateObject("InternetExplorer.Application")
    
    'IEを可視化するか = はい
    objIE.Visible = True
    
    'IEのリンク先URLはB1のセルのURL
    objIE.Navigate Worksheets("情報").Range("B1").Value
    
    'IEの表示待ち
    wait objIE
    
    'objIEのHTMLの中からtableのタグをtblに代入しながら確認
    For Each tbl In objIE.Document.GetElementsByTagName("table")
        
        'tblに代入されたtableタグのIDがlistの場合
        If tbl.ID = "list" Then
            
                'tblに代入されているtableタグにあるセルをExcelに移し変える
                
                '変数yに0を代入、tblに代入されているtableの行数まで繰り返す
                For y = 0 To tbl.Rows.Length - 1
                    '変数xに1を代入、tblに代入されているtableの列数まで繰り返す
                    For x = 0 To tbl.Rows(y).Cells.Length - 1
                        'Excelのx+1列、y+1行の位置にtableタグのx列、y行のセルの値を入れる
                        Worksheets(snam).Cells(y + 1, x + 1).Value = tbl.Rows(y).Cells,(x).InnerText
                    Next
                Next
        End If
    Next
    
    '終了のメッセージボックスを表示
    MsgBox "終了"
    
    'objIEに代入したInternetExplorerを閉じる
    objIE.Quit
    
    'objIEを空にする
    Set objIE = Nothing

End Sub

Sub wait(objIE As Object)
'objIEに代入されたInternetExplorerがビジー状態、もしくは読み込み待ちの間、処理を待つ
Do While objIE.Busy Or objIE.ReadyState < 4
    DoEvents
Loop
End Sub

IE操作用テストページ【HTML】

IE操作用テストページのHTML
<script type="text/javascript">
  function inf(frm){
    var nam = frm.h_name.value;
    var pas = frm.birthday.value;
    var sex = frm.sex.value;
      alert("ハンドルネーム:" + nam + "\n" + "パスワード:" + pas + "\n" + "性別:" + sex);
};
</script>

<form id="frm" onsubmit="return inf()">
  <table border="1px" id="main_table">
    <tbody>
      <tr>
        <th>ハンドルネーム</th>
        <td><input id="h_name" type="text" /></td>
      </tr>
      <tr>
        <th>生年月日</th>
        <td><input id="birthday" type="password" /></td>
      </tr>
      <tr>
        <th>性別</th>
      <td><input name="sex" type="radio" value="男性" /> 男性 
        <input name="sex" type="radio" value="女性" /> 女性</td>
      </tr>
      <tr>
        <th>使用したことのあるOS</th>
          <td><input name="os" type="checkbox" value="Windows" /> Windows 
             <input name="os" type="checkbox" value="Mac" /> Mac OSX 
             <input name="os" type="checkbox" value="Linux" /> Linux</td>
        </tr>
      <tr>
        <th>Excelのバージョン</th>
        <td><select id="version">
            <option value="2016">Excel2016</option>
            <option value="2013">Excel2013</option>
            <option value="2010">Excel2010</option>
            <option value="2007">Excel2007</option>
           </select></td>
      </tr>
      <tr>
        <th>メモ欄</th>
        <td><textarea cols="40" id="note" rows="3"></textarea></td>
      </tr>
    </tbody>
  </table>
  <br />
  <input id="date" onclick="inf(frm)" type="submit" value=" 送信 " />
</form>
<br />
<table border="1px" id="list">
  <tbody>
    <tr>
      <th>種類</th>
      <th>原価</th>
      <th>販売額</th>
    </tr>
    <tr>
      <th>軽油</th>
      <th align="right">80円</th>
      <th align="right">100円</th>
    </tr>
    <tr>
      <th>レギュラー</th>
      <th align="right">100円</th>
      <th align="right">120円</th>
    </tr>
    <tr>
      <th>ハイオク</th>
      <th align="right">120円</th>
      <th align="right">140円</th>
    </tr>
  </tbody>
</table>

2017年3月13日月曜日

IEの自動操作

まずはVBAを使ったIEの自動操作でどういうことが出来るのかを理解して頂く為に、こちらの記事では解説はせずに実際に私の方で作成したマクロを実行だけ試して頂きたいと思います。

IE自動操作用Excel(マクロ入り)

Chromeより実行する際、別タブが開き文字化けするという方は、右クリックから「名前をつけてリンク先を保存」からダウンロードし、実行してください。

上記のExcelファイルを開き、2,3行目を入力し、4,5,6行目の項目はリストから選択してください。
そこまでできたら「IE自動操作の実行」というボタンを押してみてください。

ボタンを押したら自動でIEが開き、こちらのブログに作成したテスト用のページに繋がります。
ページが表示されたら自分で入力した2~7行目の内容が反映し、送信ボタンが自動で押され、入力した内容のアラートがIE上に表示されると思います。
※実際には何も情報は送信しておりませんので安心してください。

次に「表の取り出し」のボタンを押してみてください。
同じテスト用のページに繋がり、先程の入力ボックスの下の表がExcel上に表示されたと思います。

このようにリストの取り出しからユーザーフォームの入力まで、基本的な操作は自動ですることが出来るのです。
ただし、HTMLと違い、Javascriptに関しては読み込みの確認などが出来ないので、知識の応用で処理できる方法をその都度探す必要があります。

では次回から解説に入りますので、これからIEの自動操作が出来るように頑張りましょうね。

変数宣言【Dim】

VBAの開発で一番基礎になり、一番使う事になるのが変数の宣言です。
変数の宣言とは簡単に説明すると一つの箱を用意してきました。
次にその箱の中身を決めましょうというお話です。

VBAのコードを書いていくとわかるようになるのですが、長いコードの中で何度も使う文字列オブジェクトなどを毎回自分で打つ、もしくはサイトやExcelなどから取り出すのは大変になります。
そういう時に変数の宣言で作った箱の名前をVBAのコードに書いてあげることで文字列オブジェクトなどをいつでも簡単に取り出すことが出来るようになるのです。

例) Dim sample As Variant
上記の変数を例に見ていきましょう。

まず【 Dim 】とは「これから変数を宣言しますよ~」
とマクロへ合図を送る事になり、次に来る名前の箱を作る材料をマクロが準備してくれます。
このDimの部分と後で説明しますがAsの部分の2箇所については、変数を宣言する中で変わることはありませんのでセットで覚えましょう

次に【 sample 】の部分についてです。
このsampleについては変数の名前になりますので、自分で好きな名前を付けてあげましょう。
また、名前の部分についてはVBAを使う中で呼び出す際に使いますので、Nameをnamの様にわかりやすく、3もしくは4文字程度で省略してあげると呼び出しやすくなります。
ただし、名前についてはスペース記号数字から始まる文字列は使用できなくなっています。
その他にもVBAのグローバル変数も使用できなくなっていますので注意が必要です。
グローバル変数についてはこちらを参照してください。

3つ目【 As 】についてはDimで箱を作る準備をしてもらい、sampleという名前の箱を作りました。
次にこのsampleという名前の箱を「こういう形に作ってくださいね。」
というオーダーを出しますよの合図になります。

最後に【 Variant 】についてです。
ここが一番重要になるのでよく覚えてくださいね。
まず、Variantの部分については「こういう形の箱を作りましたよ」という意味になります。
この箱の形には種類があり、自分が作った型の中に入りきれないものは変数として使う事ができませんので、変数を宣言する際には注意が必要です。
例えばIntegerという△の箱には「あいうえお」という〇の荷物は入りませんよね?
ただしVariantに関しては水のようなもので大抵の形の荷物は包み込んでくれますので便利ですが、消費メモリに書いてある通り、重くなりますので型がわかる場合は出来る限り適正な型を選ぶ事で、少しでも早く動いてくれるVBAが作れますので覚えれる範囲で型は覚えましょう。

主なデータ型の種類の一覧は下記になります。
またデータ型については変数のデータ型で詳しく解説してますので、もしよければご覧ください。

データ型名前消費メモリ格納できるもの
Integer整数型2byte-32,768~32,767まで
Long長整数型4byte-2,147,483,648~2,147,483,647まで
Single単精度浮動小数点数型4byte-3.402823E38~
-1.401298E-45(負の値)
1.401298E-45~
3.402823E38(正の値)
Double倍精度浮動小数点数型8byte-1.79769313486232E308~
-4.94065645841247E-324(負の値)
4.94065645841247E-324~
1.79769313486232E308(正の値)
Currency通貨型8byte-922,337,203,685,477.5808~
922,337,203,685,477.5807
String文字列型2byte指定した文字列
Date日付型8byte日付と時間
Objectオブジェクト型4byteオブジェクト
Variantバリアント型16byteほぼ何でも
Booleanブール型2byteTrueまたはFalse


Subプロシージャの呼び出し

これからマクロを使ってInternetExplorerの自動操作をしていく上で、Subプロシージャの呼び出しは、よく使うことになるので覚えておいた方が良いかと思います。

では簡単な例から説明します。

例)Sub sample1()
    Dim a1 As Object
    Set a1 = Range("A1")
    sample2 a1
    MsgBox a1.Value
  End Sub

  Sub sample2(a1 As Object)
    a1.Value = "呼び出せるかな?"
  End Sub

上記のコードを実行してみてください。
A1のセルに「呼び出せるかな?」と表示され、メッセージボックスにも「呼び出せるかな?」が表示されたと思います。

では処理の順番などを上から説明していきたいと思います。

まず、【Dim a1 As Object】変数宣言【Dim】でも説明している通り、「a1というObject型の箱を用意しますよ」という意味ですね。

次の【Set a1 = Range("A1")】ですが、これは変数の代入ですね。
オブジェクト型に関しては【Set オブジェクト名 = 代入するオブジェクト】という形で入力する事を覚えておいてください。

ここからが重要です。
sample2 a1の部分ですが、ここはsample2というSubプロシージャを呼び出すという意味です。
a1の部分に関しては変数の受け渡しになります。
sample1で宣言した変数をsample2でも使用しますよ」という事になるので、変数を宣言したSubプロシージャとは違うSubプロシージャで同じ変数を使用する場合、必ず宣言してください。

次はMsgBox a1.Valueには行かずSub sample2(a1 As Object)を実行します。
これはsample2 a1の部分でSub sample2(a1 As Object)を呼び出しているからです。

ではその中の処理として【Range("A1").Value = "呼び出せるかな?"】を実行して、A1のセルに「呼び出せるかな?」を入力し、sample2の処理が終わったのでsample1のSubプロシージャに戻ります。

最後に【MsgBox a1.Value】でメッセージボックスにA1の値を表示したら終わりになります。

このようにSubプロシージャの呼び出しをすると、他のSubプロシージャで作ったマクロを実行しているマクロから呼び出し、処理をする事が出来るのです。

最後に、この記事の最初に軽く話をしたIEの自動操作の時にSubプロシージャの呼び出しをよく使うという話ですが、これはIEでページを移動した際、ページが読み込まれるまでの間に次の処理に進んでしまうと、確実に意図しない処理をしてしまいますよね?
なので、そういう時に読み込み待ちをする為のSubプロシージャを作成しておき、ページが変わるタイミングの所で、そのSubプロシージャを読み込むとページが表示されるのを待ってくれるのです。

では、おまけとしてIEの読み込み待ちに使えるSubプロシージャをご紹介します。

Sub プロシージャ名(IEの変数名 As Object)
  Do While IEの変数名.Busy Or IEの変数名.ReadyState < 4
    DoEvents
  Loop
End Sub

このように「IEがビジー状態、もしくは読み込みが完了じゃない間、OSに処理を戻して、読み込みが終わったらループを抜けて次の処理に行く」という流れになります。
これは後々IEの自動操作をするようになるとよく使うようになるので、覚えておいたら良いと思います。

【Functionプロシージャ】の応用

前回のVBAの書き始め【Function】の便利な使い方として、Excel関数として使用するという方法があります。

どういうことかというと、Functionプロシージャを作成し、Excelのセルの中に「=Functionプロシージャ名()」を記載する事で実際にExcelの関数として使うことが出来るようになるのです。

例)Function 足し算(a As Integer, b As Integer)
    足し算 = a + b
  End Function

上記のコードをVBAへ記載し、A1のセルに1を入力、B1のセルに1を入力し、C1のセルに「=足し算(A1,B1)」と入力するとC1のセルには2という数字が表示されます。

では少し応用して税込価格と税抜き価格を表示できるようにしてみましょう。
Function 税込み(a As Integer)
  税込み = a * 1.08
End Function
上記のコードをVBAへ記載し、適当なセルに数字を入れます。
次に開いてるセルに「=税込み(セル)」を記載するとセルの中に入ってる数字×1.08で税込みの金額が出るようになります。


上記の画像は実際に入力した画面です。
C3のセルに「=税込み(B3)」を記載し、B3のセルの値の税込価格を表示しています。

このようにFunctionを関数として使うことでVBAを使えない人にも自分で作った数式の入力方法を教えてあげる事で、みんなに自分の作ったマクロを使ってもらうことが出来るようになるのです。

VBAの書き始め【Function】

前回の記事ではSubプロシージャについて説明しましたが、今回の記事ではFunctionプロシージャを説明していきたいと思います。

まずFunctionプロシージャの特徴として、値を返すという特徴を持っています。
例えばSubプロシージャの途中でFunctionプロシージャを記載するとFunctionプロシージャで処理した結果をSubプロシージャへ返してくれるのです。

例)Function Sample()戻り値のデータ型
   ここに処理を記載
   Sample = 戻り値
  End Function
上記の様にFunctionには戻り値というものが付いてきます。
では1行ずつ説明していきます。

まず【Function Sample()戻り値のデータ型】の部分では、プロシージャ名のSampleという名前の箱戻り値のデータ型の形で用意します。
この戻り値のデータ型については変数のデータ型を参照してください。

次に処理の記載ですが、この処理の内容に関しては自分で処理したい内容になりますので、その都度自分で作成が必要です。

次の【Sample = 戻り値】が重要です。
1行目で作ったFunctionプロシージャの名前にある、Sampleという箱に戻り値を入れるのですが、この時戻り値のデータ型と=の後の戻り値があってなければ代入する事が出来ませんので注意してください。

最後に【End Function】でFunctionプロシージャを終了します。

では実際にSubプロシージャへ値を戻してみましょう。
例)Sub 足し算()
   MsgBox 結果
  End Sub
  Function 結果()As Long
   結果 = 1 + 1
  End Function
上記のコードを実行した際、Excelにはメッセージボックスには2が表示されます。
これはSubプロシージャのコードを実行した際に【結果】というFunctionプロシージャの数字が戻り値として代入される為です。

ではこちらも順を追って説明します。

まず、Subプロシージャを実行すると【MsgBox 結果】の部分にある結果に入ってる値をメッセージボックスで表示しようとします。
ただ、そのままだと結果に値は入っていないので表示する前に、その結果に入る値をFunctionプロシージャで処理し、戻り値としてSubプロシージャへ返してくれるので、戻り値が入ったらメッセージボックスを表示して終了となります。

注意点としては、Functionプロシージャ名に戻り値の代入を忘れない事と戻り値のデータ型を間違えないようにする事です。

個人的にはFunctionプロシージャを使うよりはSubプロシージャからの変数の受け渡しをする事の方が多いので、上記のような使い方をすることは少ないです。
ただし、Functionプロシージャにはとても便利な使い方があるので、その使い方については次回のFunctionプロシージャの応用で説明しますね。

VBAとは?

これからVBAを始めるにあたって、まずはVBAが組めるようになるとどういうことが出来るのかを理解してもらいたいと思います。

まずはExcelを開き、キーボードのAltとF11のキーを同時に押してください。


すると上記のような画面が出てきたと思います。
次に自分が今開いてるブックを右クリックし、挿入、標準モジュールをクリックします。


そうすると下記のようなウィンドウが現れると思います。


このウィンドウに下記のコードを貼り付け、Excelの画面に戻ってください。
Sub セルの色づけ()
Dim x As Integer
Dim y As Integer
Dim c As Integer
c = 1
For y = 1 To 14
    For x = 1 To 4
        Cells(y, x).Interior.ColorIndex = c
        c = c + 1
    Next
Next
End Sub
Excelに戻った後、キーボードのAltとF8を同時に押すと下記のような画面が出てくると思います。


マクロのウィンドウの中に先程のコードのSubの後の「セルの色づけ」というものがあると思いますので、選択後、実行のボタンを押してみてください。


上記の様に表示されていたら成功です。
例えば上記の画像の様にセル一つ一つに全色の色を付けていこうと思うと「1つセルを選んでは塗りつぶし」を繰り返していくとかなりの時間がかかると思います。
その作業をたった12行のコードを記載し、実行する事で一瞬で出来てしまうのです。

このようにVBAでは「自分が手動でやっている作業を自動で作業してもらう為の文を書く事」で手動よりも早く作業を終わらせる事が出来るのです。
つまり、毎日1時間作業しているところをVBAを組むのに3時間かけたとしても、VBA完成後には1分で作業が終わるかもしれないのです。
VBA完成後では同じ作業をしてる人がいたとしても、VBAを作ってない人は1時間かけて作業してるのに、VBAを作った自分は1分で作業が終わります。
4日目にはVBAを組んだ人と組まなかった人では、この4日間に使った時間までもがあきらかに差が出てきますよね?
VBAを組めるようになると今まで使っていた時間が1/2にでも1/3にでもなるのです。
なので空いた時間は遊ぶもよし、もっと勉強するもよしで時間を有意義に使うことが出来るようになるのです。

VBAを始める準備

VBAをこれから始めるという方、まずはExcelを開いてみてください。
この画像と自分のExcelで違いがあることに気がつきますか?
※ユーザー名は個人情報のため、隠しております。
また、バージョンの違いなどによるデザインの違いではないです。
答えは開発というタブがあるところです。
この開発のタブを利用する事でVBAを書いたり実行したりする機能が使いやすくなるのです。
ではこの開発タブの表示の仕方を説明していきたいと思います。

まず、自分の開いてるExcelのファイルのタブをクリックしてください。
バージョンによってはデザインが少し違います。
上記のような画面が表示されると思います。
左のメニューの中からオプションをクリックしてください。
するとこのような画面が出てくると思いますので、その中から「リボンのユーザー設定」をクリックし、右側のメインタブの中から開発のタブにチェックを入れたらOKをクリックしてください。

これで準備は完了です。
Excelの画面に戻ると開発のタブが増えてると思います。
その中で主に使うのが下記の画面の中の【Visual Basic】【マクロ】【挿入】の3つの項目になります。
まずは【Visual Basic】の項目はVBAのコードを記載する為のウィンドウを開いてくれるボタンです。
ショートカットキーとしてAltとF11のキーを同時に押すと同じ画面が出てきます。

次に【マクロ】の項目は【Visual Basic】で作成したマクロを一覧で表示、実行する為のウィンドウを開いてくれるボタンです。
こちらもショートカットキーがありAltとF8を同時に押す事で同じ画面が出てきます。

最後に【挿入】の項目はVisual Basicで作成したマクロを【マクロ】の項目からではなく、ボタンなどから実行する時に使用する事ができます。
例えば【挿入】の項目からボタンを挿入します。
その際にマクロの登録を挿入したボタンにしてあげる事でそのボタンをクリックすると登録したマクロを実行してくれます。

ここまででマクロの準備は完成しましたので、次のVBAとは?へお進みください。

IE操作【inputタグへの値の入力】

では前回のIE操作【IE起動~読み込み】の続きで、サンプルページのユーザーフォームの上から「ハンドルネーム、生年月日、性別、使用した事のあるOS」の操作を解説していきたいと思います。
ではフォームの入力【コード】より下記のコードを抜き出して解説していきます。
'objIEのHTMLの中からinputのタグをobjに代入しながら確認
    For Each obj In objIE.Document.GetElementsByTagName("input")
        
        'ハンドルネームの記載
        
        'objに代入されたinputタグのIDがh_nameだった場合
        If obj.ID = "h_name" Then
            'objに代入されたinputタグにhnameに代入したB2のセルの値を入れる
            obj.Value = hname
        End If
        
        '生年月日の入力
        
        'objに代入されたinputタグのIDがbirthdayだった場合
        If obj.ID = "birthday" Then
            'objに代入されたinputタグにbrdに代入したB3のセルの値を入れる
            obj.Value = brd
        End If
        
        '性別の選択
        
        'objに代入されたinputタグのInnerTextがB5のセルと同じだった場合
        If Trim(obj.Value) = Worksheets("情報").Range("B4") Then
            'objに代入されたinputタグを選択する
            obj.Click
        End If
        
        '使用した事のあるOSの選択
        
        'B5のセルが空白じゃなかった場合
        If Range("B5") <> "" Then
            'objに代入されたinputタグのInnerTextがB5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("B5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
        
        'C5のセルが空白じゃなかった場合
        If Range("C5") <> "" Then
            'objに代入されたinputタグのInnerTextがC5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("C5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
        
        'D5のセルが空白じゃなかった場合
        If Range("D5") <> "" Then
            'objに代入されたinputタグのInnerTextがD5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("D5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
    Next
まず、HTMLの基礎知識として、【<input>~</input>】のように<>で囲まれた要素をタグといいます。
このタグには属性をつけることができ、IEの自動操作でよく使う属性としては「id、name、value」などがあります。
例としてid="handle_name"と書いていた場合、id属性の値はhandle_nameとなり、このhandl_nameを特定し、このタグに操作をVBAで送る事で自動操作をするという事になります。

では一つ目のハンドルネームの記載の部分を実際のHTMLと比較しながら解説したいと思います。
ハンドルネームのHTML
<th>ハンドルネーム</th>
<input  id="h_name" type="text">
VBAのコード    
'objIEのHTMLの中からinputのタグをobjに代入しながら確認
For Each obj In objIE.Document.GetElementsByTagName("input")
    'ハンドルネームの記載
    'objに代入されたinputタグのIDがh_nameだった場合
    If obj.ID = "h_name" Then
        'objに代入されたinputタグにhnameに代入したB2のセルの値を入れる
        obj.Value = hname
    End If
上記のVBAのコードの上から順番に説明していきます。

【For Each obj In objIE.Document.GetElementsByTagName("input")】
上記コードを日本語で訳すと「For Eachを使ってobjという変数にobjIEのドキュメント内からinputというタグ名の要素を代入しながら取り出してきてください。」ということになります。
つまり起動したIEのHTML内のinputというタグを全て確認してくれるのです。

次の【If obj.ID = "h_name" Then】の部分では「ForEachでobjに代入されたinputタグのID属性がh_nameの時」という処理になりますのでHTMLのinputタグのid属性を見てみてください。
h_nameとなっていますよね?
なのでid属性がh_nameになっているハンドルネームのinputタグに次の処理をします。

ではその次の処理にあたる【obj.Value = hname】では、【h_nameというIDのinputタグ=ユーザーフォームのハンドルネームの部分】に対して、hnameの変数に代入したB2のセルの内容を入力してくれます。

このようにHTMLのタグと属性からVBAで操作したい要素を特定し、処理をしていきます。
上記の部分を必ず覚えておいてください。
この基本さえわかれば、後はHTMLを確認しながら「どうやって特定して、どうやって処理するか」をVBAでコーディングしてあげるだけで、IEの自動操作は出来るようになるのです。

では次の生年月日の部分に入りますね。
生年月日のHTML
<th>生年月日</th>
<input  id="birthday" type="password">
VBAのコード
'生年月日の入力
    'objに代入されたinputタグのIDがbirthdayだった場合
    If obj.ID = "birthday" Then
        'objに代入されたinputタグにbrdに代入したB3のセルの値を入れる。
        obj.Value = brd
    End If
こちらも先程のハンドルネームと同じです。
【If obj.ID = "birthday" Then】でobjに代入された要素のIDがbirthdayの場合、次の処理を実行と記載します。

上記のIfがTrueの時、次の【obj.Value = brd】でbirthdayというIDのinputタグにbrdに代入したB3のセルの値を入力します。

この生年月日の入力のポイントとしては、先程のハンドルネームの入力の前にしている【For Each】と同じ【For Each】の中での処理になっています。
最初にしているForEachではinputタグ全てをまわっているので、何度も1からinputタグをまわるより、同じForEach内でそれぞれの要素に処理をした方が効率的ですよね?

なので「同じタグ=1つのForEach内での処理」という事を心がけましょう。
ただし、例えば検索ボタンも同じinputタグだった場合、他のinputの要素への文字の入力より先に検索ボタンを押してしまうと、当然検索のキーワードなどは入ってないのに検索しますのでエラーになりますよね?
そういう時には一度ForEachをNextで閉じた後、新しく作ったForEachで同じタグの検索ボタンを実行することが必要になる場合もあります。

では次に性別の選択を説明します。
性別の選択のHTML
<th>性別</th>
<input  name="sex" value="男性" type="radio"> 男性 
<input  name="sex" value="女性" type="radio"> 女性
VBAのコード
'性別の選択
    'objに代入されたinputタグのInnerTextがB4のセルと同じだった場合
    If Trim(obj.Value) = Worksheets("情報").Range("B4") Then
        'objに代入されたinputタグを選択する
        obj.Click
    End If
こちらの性別の選択に関しては、ページ上でラジオボックスになっています。
このラジオボックスは単純にクリックしてしまえば選択できますので、
【If Trim(obj.Value) = Worksheets("情報").Range("B4") Then】でobjに代入されたinputタグのvalue属性の値がB4のセルと同じだった場合に処理します。

次の【obj.Click】でobjに代入されたinputタグをクリックし、選択します。

注意点としてはTrim()を使っているところです。
例えばオブジェクトの特定の際、今回だとinputタグのvalue要素の男性の文字の前後にスペースが入っていた場合、一致しないとマクロが判断してしまいますので、Trim()でobj.Valueを囲んであげる事で文字の前後にあるスペースを削除してくれます。

他にもReplace()を使った方法などもありますが、それはまた別の記事で紹介したいと思います。

では最後に使ったことのあるOSの選択を解説したいと思います。
使用した事のあるOSの選択のHTML
<th>使用したことのあるOS</th>
<input  name="os" value="Windows" type="checkbox"> Windows 
<input  name="os" value="Mac" type="checkbox"> Mac OSX 
<input  name="os" value="Linux" type="checkbox"> Linux
VBAのコード
'使用した事のあるOSの選択
    'B5のセルが空白じゃなかった場合
    If Range("B5") <> "" Then
        'objに代入されたinputタグのInnerTextがB5のセルと同じだった場合
        If obj.Value = Worksheets("情報").Range("B5") Then
            'objに代入されたinputタグにチェックを入れる
            obj.Checked = True
        End If
    End If
    'C5のセルが空白じゃなかった場合
    If Range("C5") <> "" Then
        'objに代入されたinputタグのInnerTextがC5のセルと同じだった場合
        If obj.Value = Worksheets("情報").Range("C5") Then
            'objに代入されたinputタグにチェックを入れる
            obj.Checked = True
        End If
    End If
    'D5のセルが空白じゃなかった場合
    If Range("D5") <> "" Then
        'objに代入されたinputタグのInnerTextがD5のセルと同じだった場合
        If obj.Value = Worksheets("情報").Range("D5") Then
            'objに代入されたinputタグにチェックを入れる
            obj.Checked = True
        End If
    End If
Next
最後のこちらはチェックボックスになっています。
こちらのチェックボックスは複数選択可能なので、配布しているExcelでも3つの項目を用意し、Excelの5列目に記載しているOSをチェックするようにしています。

では解説です。
【If Range("B5") <> "" Then】ではB5乗せるが空白ではなかった場合、次の処理を実行という記載になっています。
VBAの基本として、代入と等号は【=】、不等号は【<>】という事を覚えておいてください。

次の【If obj.Value = Worksheets("情報").Range("B5") Then】では「objに代入されているinputタグのvalue要素がB5のセルと一致した時、次の処理を行なう」ということになります。

上記2つのIfがTrueの時、【obj.Checked = True】で「B5のセルの値と同じvalue要素を持ったinputタグのチェックボックスのチェックを入れる」という処理をします。

このときの注意点としては【Checked = True】を訳して「チェックしている状態?⇒はい」というように、チェックボックスをチェックしてあげる必要があります。

残りの2つはC5やD5を上記の解説した部分と同じように処理しているだけです。

最後にNextでinputタグを代入していたForEachを閉じてあげる事を忘れないでくださいね。

かなり長くなりましたが、ここまでは大丈夫でしょうか?
このFor Eachで全てのタグの中からIfで特定する」ということを覚えておけば基本的には応用するとIEの自動操作が出来るようになりますので、今回の記事ではこの事を覚えて次に進んでください。

次回はメモ欄への記載とExcelのバージョンの選択を解説していこうと思います。

フォームの入力【コード】

Sub IE操作()
Dim objIE As Object
Dim obj As Object
Dim slt As Object
Dim opt As Object
Dim s As Integer
Dim hname As String
Dim brd As String

'hnameの変数にB2のセルの値を代入
hname = Worksheets("情報").Range("B2").Value

'pasの変数にB3のセルの値を代入
brd = Worksheets("情報").Range("B3").Value

'InternetExplorerをobjIEに代入し、IEのプロセスを起動
Set objIE = CreateObject("InternetExplorer.Application")
    
    'IEを可視化するか = はい
    objIE.Visible = True
    
    'IEのリンク先URLは情報のシートのB1のセルのURL
    objIE.Navigate Worksheets("情報").Range("B1").Value
    
    'IEの表示待ち
    wait objIE
    
    'objIEのHTMLの中からinputのタグをobjに代入しながら確認
    For Each obj In objIE.Document.GetElementsByTagName("input")
        
        'ハンドルネームの記載
        
        'objに代入されたinputタグのIDがh_nameだった場合
        If obj.ID = "h_name" Then
            'objに代入されたinputタグにhnameに代入したB2のセルの値を入れる
            obj.Value = hname
        End If
        
        '生年月日の入力
        
        'objに代入されたinputタグのIDがbirthdayだった場合
        If obj.ID = "birthday" Then
            'objに代入されたinputタグにbrdに代入したB3のセルの値を入れる
            obj.Value = brd
        End If
        
        '性別の選択
        
        'objに代入されたinputタグのInnerTextがB4のセルと同じだった場合
        If Trim(obj.Value) = Worksheets("情報").Range("B4") Then
            'objに代入されたinputタグを選択する
            obj.Click
        End If
        
        '使用した事のあるOSの選択
        
        'B5のセルが空白じゃなかった場合
        If Range("B5") <> "" Then
            'objに代入されたinputタグのInnerTextがB5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("B5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
        
        'C5のセルが空白じゃなかった場合
        If Range("C5") <> "" Then
            'objに代入されたinputタグのInnerTextがC5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("C5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
        
        'D5のセルが空白じゃなかった場合
        If Range("D5") <> "" Then
            'objに代入されたinputタグのInnerTextがD5のセルと同じだった場合
            If obj.Value = Worksheets("情報").Range("D5") Then
                'objに代入されたinputタグにチェックを入れる
                obj.Checked = True
            End If
        End If
    Next
    
    'メモ欄への記載
        
    'objIEのHTMLの中からtextareaのタグをobjに代入しながら確認
    For Each obj In objIE.Document.GetElementsByTagName("textarea")
        
        'objに代入されたtextareaのタグのIDがnoteの場合
        If obj.ID = "note" Then
            'objに代入されたtextareaのタグにB7のセルの値を入れる
            obj.Value = Worksheets("情報").Range("B7").Value
        End If
    Next
    
    'Excelのバージョンの選択
    
    'objIEのHTMLの中からselectのタグをsltに代入しながら確認
    For Each slt In objIE.Document.GetElementsByTagName("select")
        
        'sltに代入されたselectタグのIDがversionだった場合
        If slt.ID = "version" Then
            'sltのタグに含まれるoptionのタグをoptに代入しながら確認
            For Each opt In slt.GetElementsByTagName("option")
                
                'optに代入されたoptionタグのInnerTextがB6のセルと同じだった場合
                If Trim(opt.InnerText) = Worksheets("情報").Range("B6").Value Then
                    'optに代入されたoptionタグを選択
                    opt.Selected = True
                End If
            Next
        End If
    Next
    
    '送信ボタンのクリック
    
    'objIEのHTMLにあるinputタグをobjに代入しながら確認
    For Each obj In objIE.Document.GetElementsByTagName("input")
        
        'objに代入されたinputタグのvalueの値が送信だった場合
        If Trim(obj.Value) = "送信" Then
            'objをクリック
            obj.Click
        End If
    Next
    
    '終了のメッセージボックスを表示
    MsgBox "終了"
    
    'objIEに代入したInternetExplorerを閉じる
    objIE.Quit
    
    'objIEを空にする
    Set objIE = Nothing
End Sub

Sub wait(objIE As Object)
'objIEに代入されたInternetExplorerがビジー状態、もしくは読み込み待ちの間、処理を待つ
Do While objIE.Busy Or objIE.ReadyState < 4
    DoEvents
Loop
End Sub

IE操作用テストページ


ハンドルネーム
生年月日
性別 男性  女性
使用したことのあるOS Windows  Mac OSX  Linux
Excelのバージョン
メモ欄


種類 原価 販売額
軽油 80円 100円
レギュラー 100円 120円
ハイオク 120円 140円