趣味でExcel VBAが使える趣味でExcel VBAが使える

技術者に師事したことはないですが、ある意味プロフェシッショナルかもしれない楽々アート会(趣味で絵を描くサークル)会員の私が、ソフト制作初心者のために蘊蓄を語ります。楽々アート会のページへ(←我々の絵画作品も掲載しています)

7.Excel VBAでプログラミング(1)

[Excel VBAとは]

ExcelとはMicrosoft Officeに含まれる表計算ソフトです。表に数式を入力することで簡単に計算ができ…って今更書く必要もないくらいで解説するページもネット上に山ほど存在します。VBAも同様ではありますが、これを使うとセルに入力する関数ではどうにも出来ないことが出来るようになったりします(設定をテキストにして読みこめるしDLLやら別のアプリを使うことが出来るし…)。つまりが、Excelを使う上でやりたいことをやるための道具の1つな訳です…やりたいことが思いつかない向きもあろうかと思いますが、作ったシートを誰かに使って貰ったりすれば「こんなこと出来ない?」とか言われることもあるでしょう…それを実現するための道具…なのですが、例えば数式入力で出来ることもVBAで行うことができます

[VBAを使う]

下は税抜き金額を入力して消費税込みの金額を計算させる数式です。
消費税計算
解説不要ですが超初心者のために解説すれば「=B2*1.1」は、「セルB2に入力した数字に1.1掛けた数値を(この数式を記載したセルに)表示せよ」ってことです…つまりが消費税10%ですね。いや8%の商品もあるし…ってのは(これも商品が決まっているならドロップダウンさせてリストから読み込んでも良いし何らかのフラグを立てて税率を変更しても良いが…)この際無視します。
このセルをコピーして必要なだけ下に張り付ければ出来上がり。…全く同じことをVBAでやってみるのですが、前準備としてメニューに“開発”を表示します。それなりに新しいExcelなら、メニューのファイルから“オプション”を選択、“リボンのユーザー設定”で“開発”にチェックしOKとします。
VBAを使う
さて、表示された開発メニューを選択し“Visual Basic”をクリックします。
VBAを使う
プロジェクトの“Sheet1(Sheet1)”(現在制作中のシート)をダブルクリックすると下のようなダイアログが表示されるので、ドロップダウンから“Work sheet”を選択すると
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub

という文字列が自動で生成されます。この2列の間に書き込んだ命令は、セルの値が変更された時に実行されます。
VBAを使う
では実験です。下記のように“MsgBox Target”と書き込んで、元のシートに戻り、値を変更してみましょう。
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox Target
End Sub
下記のように変更後の数値が表示されます。
VBAを使う
MsgBox Targetは、Targetの値を(メッセージボックスで)表示せよという命令です。つまりTargetという変数には、変更されたセルの値が入っているってことです。
では再び実験です。下記のように“MsgBox Target.Address”と書き込んで、元のシートに戻り、再び値を変更してみましょう。
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox Target.Address
End Sub
下記のように変更されたセルのアドレスが表示されます。
VBAを使う
つまりTarget.Addressには変更されたセルがどのセルか?という情報が入っています。
では、次に下記のように2行書き込んで、もう一度値を変更してみましょう。
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox Left(Target.Address, 3)
MsgBox Right(Target.Address, Len(Target.Address) - 3)

End Sub
まずメッセージボックスで“$B$”と変更したセルの列が$に囲まれて表示され、次に“2”と変更したセルの行が表示されます。ちなみにLeft( 文字列 ,3)は左から3文字にする、Right( 文字列 ,1)は右(後)から1文字で、Len( 文字列 )は文字列全体の文字数です。$B$3の文字数は4、$B$の3文字を引いています。
「Left(Target.Address,3)って、Target.Addressの値($B$3)の左から3文字ってことなら、セルがABとか($AB$3)ならどうするの?」さて、どうするかは考えて下さい(僕はやり方自体は変更しないけども)。…例えば文字列の中にある文字が何文字か?と調べる関数に“InStr”があります。「VBA 文字列の位置」とかで検索すると幾つもヒットすると思います。列と行が区切られているのが“$”という文字だから…と MsgBox InStr(Target.Address, "$") と記述して実行すれば“1”が表示ってきます。そう、最初の$の位置が“1”だからです。
後ろから検索する“InstrRev”という関数もあるのですが、初めの$が邪魔だから削除しちゃえと思いついたら、「vba 文字列の削除」とかググると…ありゃ?「vba 文字列操作」とググるとMid( 文字列 , 開始位置 , 取得文字数 )という関数があります。MsgBox Mid(Target.Address, 2, Len(Target.Address) - 1) とすれば…

Private Sub Worksheet_Change(ByVal Target As Range)
tarads = Target.Address '変数taradsにアドレス代入
adr = Mid(tarads, 2, Len(tarads) - 1)
colstr = Mid(adr, 1, InStr(adr, "$"))
rowstr = Right(adr, Len(adr) - InStr(adr, "$"))
MsgBox adr
MsgBox colstr
MsgBox rowstr
End Sub

2行目のクォーテーションマーク以下はコメント(説明)で実行には関係しません。

確かにこれを実行すると B$2→B$→2 と順に表示される(つまりB$と2が分けて取得できる)…先に記載したように僕はやり方を変えませんが、そういう道筋を思いついてググって結果を得る…それがプログラミングってものだとは思います~そして「vba 文字列の削除」とググって出てきた関数(Replaceやら)もあなたが使える道具の1つです。

…はい、Left~、Right~の2行の分(太字のところ)に戻ります。
この MsgBox Left(Target.Address, 3) で $B$ と表示されることで変更したのがB列である、と解りました。以下のコードを実行するとB列に数字を入れると変更した行数が表示されますが、例えばA列に数字を入れても何も表示されません。

Private Sub Worksheet_Change(ByVal Target As Range)
If Left(Target.Address, 3) = "$B$" Then
MsgBox Right(Target.Address, _
Len(Target.Address) - 3)
End If

End Sub

3行目ラストのアンダースコアはひとつの命令文を2つに分けるためのもので実際は分ける必要はありません。
元は MsgBox Right(Target.Address, Len(Target.Address) - 3) スマホ表示の為に2、3行に分けている。

つまりが条件分岐な訳ですが、If (条件式) Then ~ End If は、 Left(Target.Address, 3) が "$B$"の時だけ、ThenとEnd ifの間の記述を実行します。
最後に以下の記述をして、B列を変更してみて下さい。
Private Sub Worksheet_Change(ByVal Target As Range)
If Left(Target.Address, 3) = "$B$" Then
Range("$C$" & Right(Target.Address, Len(Target.Address) _
- 3)) = Round(CInt(Target) * 1.1)
End If

End Sub
Range("$C$3")は、シート上のセルです。=の右に記述した値が入ります。&は文字列をくっつける記号、文字列は " (クォーテーションマーク)でくくって記述します。
Rooundは四捨五入です。丸める桁を指定できますが、しない場合は小数点以下を丸めます(切り捨て等の関数もあります)。
Cintは文字列を整数化する関数です。桁数によっては別の関数が必要なのでググって下さい。
もうひとつ、気にしないといけないことがあります。それは、使う人が想定外の使い方をする可能性についてです。今回のシートでも例えば数字を入れるべきところに文字を入れる…などということが想定されます。
VBAを使う
以下のように修正してみます。
Private Sub Worksheet_Change(ByVal Target As Range)
If Left(Target.Address, 3) = "$B$" Then
If IsNumeric(Target) = True Then
Range("$C$" & Right(Target.Address, _
Len(Target.Address) - 3)) = _
Round(CInt(Target) * 1.1)
Else
Range("$C$" & Right(Target.Address, _
Len(Target.Address) - 3)) = 0
End If
End If

End Sub
IsNumeric( 変数 )は、変数の中身が数字であればTrueを返します。
VBAを使う
勿論、メッセージボックスを出すことも、数字の色を変えることも、色々と出来ます。これで文字が入力されてもエラーになりません。他にエラーになった場合の処理を記述(On Error GoTo)する…という方法もあります。上のコードなら1行目でも実行されるのでヘッダは書き込み禁止にしておく必要があるかもですね。

シートに数式を書くのがベストな場合もあると思います。が、例えばシートに数式を書くと入れ子、入れ子で別のセルも使って…とかなる場合もVBAなら整理できます。何より行を選択して並び替えるやら、どこぞのセルをコピーするやら、計算以外の機能がごっそりとあるので、自動でそれらを行うことが出来…モノによっては処理時間がかかるのですが…自前のアプリじゃないから仕方ない…出来ます。ステータスバーに処理済パーセンテージなど表示するようにしておけば、固まってないな~とか、安心できるのではないでしょうか。
後、シートに数式を記述して、下にコピーする場合は、そそっかしい人(僕もか…)はコピー忘れなどあるのでご注意を。[VBAを使う]の最初で「=B2*1.1」としているのは「=$B2*1.1」でも構いません…が「=$B$2*1.1」と行も絶対化してしまうとコピーしてもB3、B4と自動で変わってくれません。コピーもミスすれば元も子もありませんので、ちゃんと検証することが大事です。また、他人が触ることを考えてプロテクトを掛ける(方法はググって)などの予防も必要かと思います。計算させるシートを作って非表示にするとか…よくやりましたね~


■ 記事一覧

絵画の一歩絵画初心者のために蘊蓄を語るページ
1.絵を描く
音楽の一歩楽器初心者のために蘊蓄を語るページ
1.ギターを弾く
プログラミングの一歩ソフト制作初心者のために蘊蓄を語るページ
1.プログラミングとは
2.JAVAを使う
3.JAVAでプログラミング(1)
4.JAVAでプログラミング(2)
5.JAVAでプログラミング(3)
6.PHPでプログラミング(1)
7.Excel VBAでプログラミング(1)
8.Excel VBAでプログラミング(2)