Excel VBA(マクロ)研修 入門テキスト覚える命令は4種類だけ!
研修用YouTube動画(前編)
研修用YouTube動画(後編)
このテキストの内容に沿って、動画で説明をしています。
ぜひ、このテキストと動画を合わせながらVBAを学んでいただければと思います。
動画方は解像度をわざと落としてあります。画面の小さいスマホ、もしくはパソコンのディスプレイの隅に表示してExcelと一緒に見てください!
-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
★電子書籍の形の方が言い方はこちらをどうぞ!★
●電子書籍版(A4サイズ PC、タブレット向け)
●電子書籍版(スマホサイズ 小画面向け)
-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
・VBAの書籍を買ったけど、結局よくわからなくて閉じてしまった人はいませんか?
・VBAで大作を作る気はなく、ちょっとしたデータ整理だけできるレベルの知識だけほしくありませんか?
・今のうちにプログラミングを学んでおかないと、AIに仕事を取られるのではないかと思っていませんか?
そんな人を対象にして、このテキストは作られています。
必須で覚える命令は、実は4種類だけなんです。
・セルの指定:Cells( , )
・繰り返し:For~Nextループ
・無限繰り返し:DoループとExit
・条件分岐:If文
Excel内での難しくない単調なデータ整理作業は、この4つを組み合わせるだけで、大体のことはできてしまいます。これ以外の重要な命令は、Excelが書いてくれます。
本テキストでは、プログラミングの経験が無い人を対象に、なるべく平素な言葉を使っています。さらにプログラミングを勉強するのではなく、Excelにおけるデータの整理・整頓で使うことを最終目標にしています。
そのため、
「本当なら**だが、ここでは省略しても動くので**は教えない。」
「**した方が楽に書けるが、覚えることが増えるので教えない。」
という形をとっています。
プログラミングに慣れてきたり、強く興味を持ったなら、効率よく、綺麗な形でプログラムを書けるような方法を勉強していただければと思います。
Excelでゲームを作ろうとか、大規模なソフトウェアを開発するのが目的ならば、市販されている分厚い本でしっかりと学んでください。(^^)
-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
~ もくじ ~
1.Excel VBA概論
★「マクロとVBAの違い」
2.VBAは“書く”のではなく“書かせる”
2.1 「開発タブ」の表示
2.2 マクロの記録と実行
3. VBAは“書く”のではなく“書き換える”
★「Subって何?」
5.プログラミング言語
5.1 四則演算と変数の箱
5.2 繰り返し作 For ~ Next ループ
5.3プログラムの流れを見る方法
★「なぜI , J , Kなの?」
5.4変数の中身を見る方法
5.5二重ループ
★「命令は小文字で入力」
5.6 条件判定If ~ Then ~ End IFと不等号
★「If文の他の命令文」
5.7 無限ループ Do ~ Loopと強制脱出 Exit Do 命令
★ 「暴走をとめるのはESCキー」
5.8 配列変数の設定
★「変数の型の宣言」
6.ファイルの読み込み
6.1 Excelファイルの読み込みとファイルを閉じる作業
6.2 テキストファイルの読み込み
★「文字データの結合は“&”と“+”」
6.3 ファイル名の読み込みを自動化する場合
7.プログラムの高速化
11.VBAヘルプやインターネットの活用
13.ファイル名やフォルダ名をマウスで指定
★「あなたはプログラマではない」
~付録~
1)Excelでよく使う VBA命令一覧
2)Excelではないがよく使う VBA命令一覧
3)セルの列名と数値
(★:一言メモ)
-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
1.Excel VBA概論
VBAとは“Visual Basic for Applications”の頭文字で、アプリケーション(WordやExcelのこと)の為のVisual Basic(以下VB)という意味である。VBはプログラミング言語の名前で、Windows上のアプリケーション開発でよく使われているプログラミング言語である。VBAの基本はVBであるが、それにアプリケーション専用の関数が追加され、様々なアプリケーションをコントロールし易いように改良されている。
それでは、Excelと会話するためのプログラミング言語である、VBAを学んでいくことにする。
2.VBAは“書く”のではなく“書かせる”
2.1 「開発タブ」の表示
下のような画面が表示されたら、リボンのユーザー設定を選択し、右の枠の中の「開発」にチェックマークを入れ、OKボタンを押す。そうすると、開発タブ(リボン)が使用できるようになる。
2.2 マクロの記録と実行
マクロの表示や記録だけなら、「表示」タブの「マクロ」からも選択できる。
3. VBAは“書く”のではなく“書き換える”
さて、先ほどの記録したVBはどこにあるのだろうか?それを見るために、VBエディッタを立ち上げる必要がある。開発タブから「Visual Basic」のボタンを押し、VBエディッタを立ち上げる。
もしくは、表示からも以下の手順で立ち上げることができる。
すると、あまり見慣れない画面が立ち上がる。これがVBエディッタである。
記録したプログラムが入っているのは、標準モジュールの中のModule1である。Module1をダブルクリックすると、記録されたVBAが表示される。複数ファイルがあり、それぞれマクロがある場合は、あちこちにModuleが出てくるので、間違えないように気をつけること。
記録されたマクロは以下の通りである。
――――――――――――――――――――――――――――――――――
Sub Macro1()
‘
‘ Macro1 Macro
‘
‘
Range("B2").Select
ActiveCell.FormulaR1C1 = "1"
Range("B3").Select
End Sub
――――――――――――――――――――――――――――――――――
では、プログラムの部分の解説をしていく。
Range("B2").Select “B2” セルを選択する
ActiveCell.FormulaR1C1 = "1" “1” を書き込む
Range("B3").Select “B3” セルを選択する
(リターンを押したため、カーソルが下に移動)
※文字は“ ”でくくる。数字や変数は文字では無いため、そのままでOK。
(↑ダブルクオーテーション)
プログラムの中の“ ”で囲まれた部分を変更したらどうなるだろうか?答えは、変えたら、その通りに変わるのである。B2をA1に変えれば、A1セルに書き込まれるし、1ではなく100と変えれば、100が書き込まれる。書き換えたら、緑の三角形の実行ボタンを押して、結果を確認してみよう。さて、思ったような結果が出力されただろうか?
###################################################
<一言メモ> 「Subって何?」
サブルーチン(subroutine)の略称です。古代(?)BASICで使われていた言葉で、メインルーチンと分けて使われていました。例えば、メインプログラム(メインルーチン)の中で何度も使われる部分を切り出し(この切り出した部分をサブルーチンと呼ぶ)、プログラム全体を見やすくしたり、プログラム全体の長さを短くしたりするのが目的です。VBAでは、さしあたって、Excelがメインルーチンで、VBAがサブルーチンみたいなものでしょうかね?
###################################################
4.少し長めのプログラムに挑戦
以下の動作を記録させてみよう。ExcelとVBエディッタを左右に並べて表示しながら記録させると、作業した瞬間に命令が記録されるため、個々の作業と命令とのひも付きがよくわかる。
1)Sheet1を選択し、適当なセルに数値を入力する
2)新規にシートを作成する
3)Sheet1に戻り、先ほどの数値をコピーする
4)新規シートのセルを選択し、貼り付ける
マウス操作の違いにより、多少よけいなものが混じっている可能性があるが、以下のようになったはずである。自分の行った動作がプログラムのどの部分に対応しているのかが、おおよそ読めるようになってきたであろうか?
――――――――――――――――――――――――――――――――――
Sub Macro2()
Sheets("Sheet1").Select ‘ Sheet1を選択する
Range("A1").Select ‘ A1セルを選択する
ActiveCell.FormulaR1C1 = "12345" ‘ “12345”を入力する
Range("A2").Select ‘ A2セルを選択する
Sheets.Add After:=Sheets(Sheets.Count) ‘ 新規にシートを追加する
Sheets("Sheet1").Select ‘ Sheet1に戻る
Range("A1").Select ‘ A1を選択する
Selection.Copy ‘ 選択した場所をコピーする
Sheets("Sheet4").Select ‘ Sheet4(新規シート)を選択する
Range("A1").Select ‘ A1を選択する
ActiveSheet.Paste ‘ 選択した場所に貼り付ける
End Sub
――――――――――――――――――――――――――――――――――
<重要>
セルの選択の仕方に、もう1つ方法がある。
今までは Range( "A1" ).Select と書いていたが、Cells( 1 , 1 ).Select と書くこともできる。書式は
Cells ( 行番号 , 列番号 ) 覚え方 「 縦 ・ 横 」 ※( Y , X )座標
となる。繰り返し作業をさせる場合は、Rangeは使えない。Cellsを使用することになるので、必ず覚えておいて欲しい。
範囲指定の場合は以下のようになる。下の例は、A1~E3の範囲を選択した場合である。
Range ( Cells( 1 , 1 ) , Cells( 3 , 5 ) ).select
↑左上 ↑右下
ここから、Excelのマクロ記録機能では記録できない部分の解説を行う。必要最小限のプログラミング言語や変数のルールしか記載しないが、大体のことはここで紹介する3つの命令文(Forループ、If文、doループ)のみで解決できる。
5.1 四則演算と変数の箱
四則演算の記号はExcelと同様で、以下の通りである。これは何も問題は無いかと思う。
足し算 + → +
引き算 - → -
かけ算 × → *
わり算 ÷ → /
多少やっかいなのが、変数である。プログラム内で計算をさせたいということは必然的に出てくる。小中学校で習う四則演算とは多少ルールが異なるので、ここでしっかりと理解しておいて欲しい。
まず、以下の式は理解できるだろうか?
A = 1 ‘Aに1を入れる
B = 3 ‘Bに3を入れる
A = B ‘AにBの中身の数値を入れる
今までの知識だと、「=」の意味は、「同じである」ことを表している。しかし、プログラムの世界では異なる。この意味は、「値を代入する」である。「=」の意味は、「代入」である。
Aという箱とBという箱がある。今、Bには3という数字が入っている。A = Bとは、Bの値をAへ代入するという意味なので、このA = Bを実行した後は、Aの値が3になり、Aに入っていた“モノ”は上書きされて消える。
では、次の式はどういう意味だろうか?
A = A + 1
普通に考えれば、「成り立っていない!」ということになるが、プログラムではよく見る書き方である。「=」は代入なので、先ほどの箱の例で例えると、次のようになる。
① 「A+1」を計算
② A = 2を実行この命令を実行した後は、Aの中身は2になる。「=」の右側は、少し過去のA、左側は少し未来のAと考えても良い。
5.2 繰り返し作業 For ~ Next ループ
繰り返し作業をさせる中で中核となるのが、このForループである。以下の式は、命令文を10回繰り返すForループである。(今回は変数にJを使用しているが、特に決まりはない。)
では、以下のプログラムを入力し、実行させてみよう。
――――――――――――――――――――――――――――――――――
Sub 繰り返し()
Sheets("Sheet2").Select ‘ Sheet2を選択
For J = 1 To 10 ‘ Jを1から10になるまで繰り返す
Cells( J , 1 ) = 1 ‘ セル(J , 1)に1を書き込む
Next J ‘ Jの値を増やす
End Sub
――――――――――――――――――――――――――――――――――
結果は、1が10個縦に並んだと思う。1を順番に書き込むという作業を10回繰り返させたのである。前にも書いたがCellsを使う理由は、このように変数を使うことができることである。
###################################################
<一言メモ> 「命令は小文字で入力」
VBAの入力画面では、スペースが自動的に入ったり、大文字や小文字を自動的に修正してくれたりする。特に、プログラム(命令文)は頭文字が大文字で、それ以降は小文字になる。小文字で全部入力して、入力確定をした後、また頭文字が小文字ならば、どこかスペルミスをしていることとなる。
正) cells -(確定)→ Cells 小文字→大文字
誤) cels -(確定)→ cels 小文字→小文字
###################################################
まず、プログラムが書いてある左側の少し幅のあるグレーのバーをクリックしてもらうと、●が付きその位置に対応した行のみ反転する。これにより、プログラムを実行した際、この反転した行が実行される前でプログラムが停止する。 実行ボタン(緑の三角形)を押すたびに次の停止までプログラムが動く。止める場所の指定は1カ所だけではなく、複数指定することができる。
動作を見たい行を予め反転させておき、実行ボタンを押すと、止めたい場所まで逐次実行されることになる。想像通りの動作が行われているかなどをチェックする際に役立つ。
###################################################
<一言メモ> 「なぜI , J , Kなの?」
ループにて使われる変数ですが、これらはカウンタ変数と呼ばれ、一般的には、I,J,Kが使われます。では、なぜI,J,Kなのでしょうか?諸説ありますが、その一部をご紹介します。
1) 「繰り返し」を英語で書くとIterationと書くため、その頭文字が使われた。JとKはIの続きなので、そのまま使った。
2) 初期のFORTRANというコンピューター言語では、I,J,K,L,M,Nには整数を入れるという定義があり、その習慣が今も生き続けている。
※本テキストでは、「I」と「1」を見間違う可能性があるため、Jを使っています。また、I,J,Kにこだわる必要は無く、好きな変数名を使う事ができます。
###################################################
5.4変数の中身を見る方法
プログラミングで思ったように動かないなんてことは日常茶飯事である。上手く動かない原因をバグ(虫)と言い、その虫を取ることをデバッグ作業と言う。ここではデバッグに関するテクニックを紹介する。
変数の中身を見たい場合、変数にマウスカーソルを重ねる(クリックではない)ことで、その変数の中身がポップアップで表示される。これでいちいちセルに書き出さなくても中身を見る事ができる。
それ以外にも、「表示」→「ローカルウインドウ」を選択することで、各変数の詳細をチェックすることができる。エラーが出てプログラムが止まった場合は「デバッグ」を押し、ここの値を見て、想像通りの値になっているかをチェックする。
5.5 二重ループ
以下のように、ForループをさらにForループで囲むこともできる。下のプログラムは1列を1で埋める作業を、ヨコ10列(10回)行う命令である。
――――――――――――――――――――――――――――――――――
Sub 繰り返し2()
Sheets("Sheet2").Select ‘ Sheet2を選択
For K = 1 To 10 ‘ Kを1から10になるまで繰り返す
For J = 1 To 10 ‘ Jを1から10になるまで繰り返す
Cells(J , K) = 1 ‘ セル(J , K ) に1を書き込む
Next J ‘ Jの値を1増やす
Next K ‘ Kの値を1増やす
End Sub
――――――――――――――――――――――――――――――――――
結果は、Sheet2のA1セルと起点として10×10のセルに1が入力されたはずである。
試しに「Cells(J , K) = 1」を次のように書き換えて、結果がどうなるか見てみよう。
1) Cells(J , K) = J & K
2) Cells(J , K) = J & “,” & K ※&の前後にはスペースが必要!
「&」は文字や数字をくっつける役割をする。
5.6 条件判定 If ~ Then ~ End IFと不等号
プログラムを書いていると、様々な条件で処理を変えたい場合が出てくる。その際にはIf文を使う。文法は以下の通りである。
例えば、たくさんあるデータの中で、ある数値を見つけて、その値を修正する作業をプログラミングすると以下のようになる。
――――――――――――――――――――――――――――――――――
Sub 検索と置換()
Sheets("Sheet2").Select ‘ Sheet2を選択
For K = 1 To 10 ‘ Kを1から10になるまで繰り返す
For J = 1 To 10 ‘ Jを1から10になるまで繰り返す
If Cells( J , K ) = 30 Then ‘ もし、セル( J 、K )の値が30ならば・・・
Cells( J , K ) = 100 ‘ 選択したセルの値を100に変える
End If ‘ If文の終わり
Next J ‘ Jの値を1増やす
Next K ‘ Kの値を1増やす
End Sub
――――――――――――――――――――――――――――――――――
If文の中にある Cells( J , K ) = 30 の「=」は代入ではない。「イコール(同じ)」である。
では、30以上や以下のもの全てに100を加えたい場合はどうするか。その際には条件文に不等号を使う。不等号の種類は以下のものがある。
Cells( J , K ) > 30
:30より大きい ( 31、32、33・・・)
Cells( J , K ) >= 30
:30以上 ( 30、31、32、33・・・)
Cells( J , K ) <= 30
:30以下 (・・・27、28、29、30 )
Cells( J , K ) < 30
:30より小さい(・・・27、28、29 )
Cells( J , K ) <> 30
:30以外(・・・27、28、29、 31、32、33・・・、文字、空白)
If文の条件は、何も数字だけではない。例えば、セルのデータの有無をチェックして何か命令を実行したい場合は、以下のように書く。このテクニックは、データの数が不明な場合にデータの最後のセルを見つける方法としてよく使われる。
If Cells( J , K) = "" Then ‘ もし、セル(J 、K)が何もないなら
Cells( J , K ) = "データ無し" ‘ 選択したセルに「データ無し」を書き込む
End If ‘ If文の終わり
###################################################
<一言メモ> 「If文の他の命令文」
If文にはまだまだできることがあります。例えば、条件を2つ設定したいなんてこともありますよね?そういう場合には、以下のように条件をandでつなぎます。
If 条件1 and 条件2 then
2つの条件の内、片方だけを満たした時に命令を実行したい場合はorで条件をつなぎます。
If 条件1 or 条件2 then
他には、ElseIfというのもありまして、以下のように、条件を重ねることも可能です。If文を何度も繰り返すことで、同じことができますが、このように書いた方が、スマートですね。
If 条件1 then
命令1
ElseIf 条件2 then
命令2
Else
命令3
End If
###################################################
5.7 無限ループ Do ~ Loopと強制脱出 Exit Do 命令
繰り返す回数が明確な場合はForループを使うが、対象によってはデータの数が不明な場合がある。そのような場合には、Doループを使う。ただし、終了する命令が無い場合は無限にループし続けてしまう。そのため、ループ内で、条件に合うものが見つかったら、ループを抜け出す命令を書く必要がある。その命令は、強制的にループを抜け出す Exit 命令である。
――――――――――――――――――――――――――――――――――
Do
IF 条件文 Then
Exit Do
End If
命令文
Loop
――――――――――――――――――――――――――――――――――
下のプログラムは、A列の最終行(データ無いセル)を見つけ出し、データ数を出力するプログラムである。
――――――――――――――――――――――――――――――――――
Sub データ数カウント()
Sheets("Sheet2").Select ‘ Sheet2を選択
J = 0 ‘ 変数Jに0を入れる
Do ‘ Do ループ開始点
If Cells(J + 1, 1) = "" Then ‘ J + 1行目にデータが無いなら
Exit Do ‘ Doを抜ける
End If ‘ If文の終わり
J = J + 1 ‘ Jを1つ増やす
Loop ‘ Do ループ終了点
Cells(1, 2) = "データ数" & J & "個" ‘ B2のセルを選択し個数を出力
End Sub
――――――――――――――――――――――――――――――――――
このExitであるが、使い道が結構ある。DoループやForループを強制的に抜けたい場合、もしくはプログラムを強制的に抜けたい(Exit Sub)場合である。
ちなみに、以下の1行の命令で、上のプログラム同様、対象のセルの行数のカウントができるが、隣り合う列に数字が入っている場合、その集団で最も長い列の値を返すので注意。
A = Range("A1").CurrentRegion.Rows.Count
もしくは、最終行から上の方へ探していくという考え方で以下のような書き方もあります。
B = Cells(Rows.Count, 1).End(xlUp).Row
###################################################
<一言メモ> 「暴走をとめるのはESCキー」
For~NextでもDo~Loopでも、どちらでもループさせることは可能なので、好みで使い分けて下さい。ただし、Do~Loopの気をつけなければいけないのは、条件設定を誤ると、無限ループになって、プログラムが止まらなくなることも・・・?そんな時は、「ESC」キーでプログラムを止めましょう。
それ以外にも、プログラムが止まっているように思えた時には、「ESC」キーで一時停止をさせて、ちゃんと動いているか、どこまで作業が進んだのかを確認するのも良いですね。
###################################################
5.8 配列変数の設定
「配列」という言葉を聞くと、凄く難しいイメージがあるかと思うが、ただ変数の箱が並んでいるだけである。配列なので、2次元、3次元、4次元・・・と配列を作ることができる。書き方は、以下の通りである。Subのすぐ後に書く。変数の開始ナンバーは0からになるが、勘違いを避けるため、A(0)等の箱は使わない方が良い。
――――――――――――――――――――――――――――――――――
Sub Macro1()
Dim A ( 5 ) ‘ A(0)~A(5)の6個の変数を使うという宣言
Dim B ( 2 , 5 ) ‘ B(0,0)~B(2,5)の18個の変数を使うという宣言
命令文
End Sub
――――――――――――――――――――――――――――――――――
この配列変数の利点は、配列変数のカッコ内の数値そのものを変数にすることで、ループの中で極めて便利に変数を使うことができる。例えば、表全体の数値を全て変数に取り込み、様々な計算や並び替えをさせて、出力させるような場合である。ただし、使う前にDim ~と書いて、先に箱を作っておく必要がある。ちなみに、DimはDimension(次元)の略である。
今、セルのA1~A10に何か数字(文字)が入っているとする。以下のプログラムを実行すると、上下を反転することができる。
――――――――――――――――――――――――――――――――――
Sub 上下反転()
Dim A(10) ‘ A(0)~A(10)を使うと宣言する
For J = 1 To 10 ‘ 変数Jを1~10まで変化させる
A( J ) = Cells( J , 1 ) ‘ A( J )にA1~A10までの値を入れる
Next J ‘ 変数Jを増やす
For J = 1 To 10 ‘ 変数Jを1~10まで変化させる
Cells( J , 1 ) = A( 11 - J ) ‘ Bの列にA(10)→A(1)の順で書き出す
Next J ‘ 変数Jを増やす
End Sub
――――――――――――――――――――――――――――――――――
###################################################
<一言メモ> 「変数の型の宣言」
VBでは、本当は最初に変数の型の宣言を行うのが正式です。「変数の型って何?」ということですが、例えば、「この変数には8桁の数字しか入れません」「整数しか入れません」「文字列しか入れません」、中には「文字が入るかも知れないし、数字が入るかも知れないし、良くわかりません」というのもあるかもしれません。それが予めわかっていれば、それに見合った箱をVBが用意してくれます。利点は次の2つがあります。
・余計なメモリーを使わずに済むこと
宣言をしないと、最大級の大きさの箱が用意されます。当然その分のメモリーが
使われるため、変数が多い場合はメモリー不足になるかもしれません。
・デバッグが容易になること
「数字しか入らない」と宣言をしてプログラミングしていたにも関わらず、プログラムの実行途中で「変数の型が違う!」というエラーが出たとします。 数字しか入らない場所に、実際には文字が入るように命令されていたなんてことがあります。セルの参照場所が1行間違っているなんて日常茶飯事です。変数を宣言することで、このようなバグを容易に気づくことができます。
宣言していないと、変数に文字列を入れたまま、次の命令へ移動して、最後の最後で計算エラーが出て、「あれ?」ってことになります。
###################################################
6.ファイルの読み込み
集めたデータがテキストファイル(*.txt)で、それをExcelにまとめるという作業をやったことはないだろうか。もしくは、1実験のデータが1のExcelファイルに入っていて、複数のデータをまとめるために、Excelファイルを開いたり閉じたり、さらには間違って同じファイルを開いて、同じデータをコピーしてしまったりしたことは無いだろうか。ファイルの数が3~4個なら、手作業で繰り返せばいいので問題は無いが、ファイルの数が数十個となると大変である。これらの作業こそVBAにやらせるべきである。
6.1 Excelファイルの読み込みとファイルを閉じる作業
そろそろわかってきたと思うが、VBAは書くのではなく、書かせるのである。実際にマクロの記録を実行し、Excelファイルを開き、欲しい部分をコピーし、閉じる作業まで行い記録を終了してみる。ここまでできれば、あとはファイル名を変数に入れ、それをForループで繰り返せばいいだけである。
まずは書かせたものを読み解いてみよう。
――――――――――――――――――――――――――――――――――
Sub Macro1()
‘ ファイルを開く(長いプログラムは、“_”で折り返される)
Workbooks.Open Filename:= _
"C:\Documents and Settings\User\デスクトップ\data\2301c01r.xls"
Range("C8:C36").Select ‘ 範囲を選択
Selection.Copy ‘ 選択範囲をコピー
Windows("Book1.xls").Activate ‘ Book1.xlsを表示
ActiveSheet.Paste ‘ 今見えているシートにコピー
Windows("2301c01r.xls").Activate ‘ 元ファイルを選択
ActiveWindow.Close ‘ いらないので、閉じる
End Sub
――――――――――――――――――――――――――――――――――
修正点は以下の3点。
(1)ループ化:処理が1回で終わってしまっては困ります。
(2)ファイル名の変数化:毎回同じファイルを読み込んでは困ります。
(3)貼り付け場所の変数化:毎回同じ場所に上書きコピーされては困ります。
修正したプログラムは以下のようになる。
――――――――――――――――――――――――――――――――――
Sub Macro1()
Dim file_name(12) ‘ file_name( )という変数を12個用意(12ヶ月分)
file_name(1) = "2301c01r.xls"
‘ file_name(1)に、「2301c01r.xls」というファイル名を代入
file_name(2) = "2302c01r.xls" ‘ 以下、同様
file_name(3) = "2303c01r.xls"
file_name(4) = "2304c01r.xls"
file_name(5) = "2305c01r.xls"
file_name(6) = "2306c01r.xls"
file_name(7) = "2307c01r.xls"
file_name(8) = "2308c01r.xls"
file_name(9) = "2309c01r.xls"
file_name(10) = "2310c01r.xls"
file_name(11) = "2311c01r.xls"
file_name(12) = "2312c01r.xls"
For J = 1 To 12 ‘ Jを1~12まで変化させる
‘ ファイルを開く(長いプログラムは、"_"で折り返される)
Workbooks.Open Filename:= _
"C:\Documents and Settings\User\デスクトップ\data\" & file_name(J)
Range("C8:C36").Select ‘ 範囲を選択
Selection.Copy ‘ 選択範囲をコピー
Windows("Book1.xls").Activate ‘ Book1.xlsを表示
Cells(1, J).Select ‘ :
ActiveSheet.Paste ‘ 今見えているシートにコピー
Windows(file_name(J)).Activate ‘ 元ファイルを選択、
ActiveWindow.Close ‘ いらないので、閉じる
Next J
End Sub
――――――――――――――――――――――――――――――――――
どうだろうか?ループ、変数、セル操作、問題なく実行できただろうか?これが出来るようになれば、日頃の業務の単純なファイル間にまたがるデータ収集作業が劇的に楽になるはずである。
6.2 テキストファイルの読み込み
テキストファイル(CSV,PRN,TXT)の読み込みも、Excelファイルとほぼ同様である。違うのは、テキストファイルの場合、データ間の区切りがどうなっているのかを指定する必要があるが、これもマクロ自動記録で書かせてしまえば問題は無い。参考までに、CSVファイル読み込み時のプログラム例(マクロ記録で書かせたモノ)を記載しておくが、読み込み条件の命令の中身を理解する必要は全くない。
――――――――――――――――――――――――――――――――――
Workbooks.OpenText Filename:= _
"C:\Documents and Settings\User\デスクトップ\test.csv", Origin:=932, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, Comma:=False _
, Space:=False, Other:=False, FieldInfo:=Array(Array(1, 1), Array(2, 1), _
Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), _
Array(10, 1), Array(11, 1), Array(12, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array( _
16, 1), Array(17, 1), Array(18, 1), Array(19, 1), Array(20, 1), Array(21, 1), Array(22, 1), _
Array(23, 1), Array(24, 1), Array(25, 1)), TrailingMinusNumbers:=True
――――――――――――――――――――――――――――――――――
###################################################
<一言メモ> 「文字データの結合は“&”と“+”」
文字の結合には、&(アンパーサンド)と+(プラス)の2つがあります。例えば、以下のようなプログラムがあった時、CとDの中身は全く同じになります。
A = ”あけまして”
B = ”おめでとう”
C = A & B
D = A + B
しかし、以下の場合、Dはエラーになります。何故かというと、Aが数字だと判断されてしまい、数字と文字の足し算はできないと怒られるのです。なので、混乱を避けるため、なるべく文字の結合は“&”にすることをお勧めします。
A = 10
B = ”歳の誕生日”
C = A & B ‘:この場合は、文字と文字の結合と判断される
D = A + B ‘:数字+文字はダメ(エラーになる)
###################################################
6.3 ファイル名の読み込みを自動化する場合
ファイルの読み込みでプログラムが止まってしまうことがよくある。よく調べてみると、ファイル名が半角と全角の違いがあったり、微妙な表記の違いであったりすることがある。人間なので「間違いなくファイル名を入力せよ」というのも酷な話である。ここでは1つのフォルダ内にあるファイル名を一気にテキストファイルで取得する方法を説明する。
――――――――――――――――――――――――――――――――――
Sub Macro1()
' ↓ワイルドカード
a = Dir("C:\Documents and Settings\User\デスクトップ\" & "*.xls")
' 変数aに指定フォルダ内のxlsファイルの名前を入れる
J = 1 ' 1行目からデータを書き出す
Do
If a = "" Then
Exit Do ' もし、aに何もデータが無い場合はDoを抜ける
End If
Cells(J, 1) = a ' セルにファイル名を出力する
J = J + 1 ' 1行ずらす
a = Dir() ' 変数aに次のファイル名を入れる
Loop
End Sub
――――――――――――――――――――――――――――――――――
新しく、Dir命令を使用した。これは、ディレクトリ内のファイル名やフォルダ名などを取得するのに使う命令で、*(ワイルドカード)が使用できる。Dir()を実行するたびに、次々と変数aにファイル名を読み込み、ファイルが無くなったら終了するというプログラムである。
7. プログラムの高速化
プログラムを高速化したい場合には、自動再計算を止めておくと良い。
“ ツール → オプション → 計算方法タブ → 計算方法:手動 ”
しかし、プログラム実行後には自動に戻しておかないと、計算が止まったままなので結果が変になる。忘れずに自動に戻すこと。これもマクロで手動自動切り替え可能である。
また、マクロで画面の描画を止めて高速化することも可能である。
8.グラフのコントロール
「グラフの場所を綺麗に並べたい」「グラフの大きさを揃えたい」という要望があるだろう。1つのシートに20個ほどのグラフがあり、それを1つ1つ手作業で大きさを揃えたりするのは面倒な作業である。ここで紹介するのは、データからグラフを新規に作成し、その大きさや位置を希望の大きさに揃えるプログラムである。
――――――――――――――――――――――――――――――――――
Sub グラフ()
For k = 1 To 3 'グラフを3個作るので3回ループ
j = (k - 1) * 4 + 2 '表の左上のセルの指定(A→E→I)
ActiveSheet.Shapes.AddChart.Select 'グラフを追加
ActiveChart.ChartType = xlColumnClustered 'グラフの種類は棒グラフ
ActiveChart.SetSourceData Source:=Range(Cells( 1, j ), Cells( 5, j + 2))
'データ範囲指定
ActiveChart.Parent.Width = 200 'グラフの幅を指定
ActiveChart.Parent.Height = 200 'グラフの高さを指定
ActiveChart.Parent.Left = Cells(10, (k - 1) * 4 + 1).Left 'ヨコの位置を指定
ActiveChart.Parent.Top = Cells(5 + k, 10).Top 'タテの位置を指定
Next k '(↑理解のためわざとk行ずつずらしてます)
End Sub
――――――――――――――――――――――――――――――――――
結果は以下のようになる。マクロの記録を使い、対象のグラフを作成するマクロをExcelに書かせて、上記のプログラムの後半部分を追加すれば良い。
9.画像のコントロール
画像ファイルをExcelに並べて貼り付けるような作業をしていないだろうか。大きさや位置を揃えたり、貼り付いた画像と、貼り付けたい画像が一致しているか不安になったりしていないだろうか。下記のプログラムを使うと、画像ファイル名に対応した画像を、そのファイル名が記載されたセルに貼り付けることを行ってくれる。
――――――――――――――――――――――――――――――――――
Sub 画像貼り付け()
For K = 1 To 2 'タテ位置に貼り付ける画像数
For J = 1 To 3 'ヨコ位置に貼り付ける画像数
p_name = Cells(J, K) 'p_nameという変数に画像ファイル名を入れる
Cells(J, K).Select 'ファイル名が書かれているセルを選択する
ActiveSheet.Pictures.Insert _
("C:\Documents and Settings\User\デスクトップ\" & p_name & ".jpg").Select
‘「A1.jpg ~A6.pg」という名前の画像ファイルを読み込む
Next J
Next K
End Sub
――――――――――――――――――――――――――――――――――
デスクトップにA1.jpg ~ A6.jpgの画像が置いてある状態で実行した結果、以下のようになる。
10.ボタンの付け方
マクロを実行するために、毎回VBエディッタを立ち上げるのは不便である。ここでは、Excelシートにマクロを実行するボタンを配置する方法を紹介する。登録できたなら、大きさや位置、ボタンの名前を希望のものへ変更する。
11.VBAヘルプやインターネットの活用
ある程度使えるようになると、「インターネットから自動的にファイルをダウンロードしたい」「画像データの処理をさせたい」など、色々な要望が出てくる。その時には、検索サイトにて、「Excel VBA」と実行したい内容を合わせて検索してほしい。希望するプログラムがきっと見つかるはずである。VBAヘルプ(インストール必要)も活用して欲しい。
12.いっぱいできたModuleの消し方
マクロの記録を繰り返すと、何かの拍子でModule2、Module3がどんどんできてしまうことがある。あっても問題は無いが、見栄えがあまりよくないので整理するにはどうすればいいか。対象のModuleにて、右クリックをし、「Moduleの解放」を選択すると、次のような画面が出てくる。ここで「いいえ」を押せば、対象のModuleを削除(解放)することができる。
※「削除する前に・・・」なんて言うなら、「Moduleの解放」なんて言わずに「Moduleの削除」って言えばいいのに・・・紛らわしい。
13.ファイル名やフォルダ名をマウスで指定
ファイル名を指定するのに、セルやマクロの中にファイル名を打ち込む作業が面倒と感じたならば、以下のプログラムをつかって欲しい。実行するとマウスでファイルが選択でき、シートにフォルダ名とファイル名を出力する。
――――――――――――――――――――――――――――――――――
Sub ファイルを設定()
Dim OpenFileName As String, FileName As String, Path As String
OpenFileName = Application.GetOpenFilename("Microsoft Excelブック,*.xls")
If OpenFileName <> "False" Then
FileName = Dir(OpenFileName)
Path = Replace(OpenFileName, FileName, "")
Cells(1, 2) = Path
Cells(2, 2) = FileName
Else
MsgBox "キャンセルされました"
End If
End Sub
――――――――――――――――――――――――――――――――――
###################################################
<一言メモ> 「あなたはプログラマではない」
世の中にあるVBAの書籍のほとんどは、清く正しくプログラミングをするにはという視点で書かれています。そのために、プログラミングにおける様々な作法や儀式を学ばなければ、自分の勉強したかった、本当にやりたかった部分にたどり着けないし、作法や儀式の段階で挫折した人もかなりいたのではないかと思います。
しかし、清く正しくある必要があるのでしょうか?数回使って終わりのような小さいプログラムなら、多少止まりながらもそれなりに動けば、それで十分ではないでしょうか。そんな視点でこの研修テキストを書きました。
プログラムを生業とする人は作法や儀式を学ばないといけません。集団で1つのソフトウェアを作る、プログラムの保守や新規OSへの対応などの業務は、決まったルールの中でプログラミングをしないと、後々非常に困ったことになります。
しかし、あなたにはルールや規制はありません。自分の作業の効率化のためにプログラミングをするのです。それなりに動けばいいのです。
そう、あなたはプログラマではないのです。
###################################################
<付録1 Excelでよく使う VBA命令一覧>
●セルの操作
――――――――――――――――――――――――――――――――――
セル選択(セルA1を選択)
Range("A1").Select
または
Cells(1,1).Select
Cells(行番号, 列番号)という指定になります
――――――――――――――――――――――――――――――――――
セル範囲選択(セルA1: B3を選択)
Range("A1: B3").Select
または
Range(Cells(1, 1), Cells(3, 2)).Select
――――――――――――――――――――――――――――――――――
アクティブセルの行番号 ActiveCell.Row
アクティブセルの列番号 ActiveCell.Column
――――――――――――――――――――――――――――――――――
行選択 Rows("3:3").Select
行挿入 Range("A1").Select
Selection.EntireRow.Insert
――――――――――――――――――――――――――――――――――
クリア Selection.ClearContents
――――――――――――――――――――――――――――――――――
コピー Selection.Copy
――――――――――――――――――――――――――――――――――コピーモード解除 Application.CutCopyMode = False
――――――――――――――――――――――――――――――――――貼り付け ActiveSheet.Paste
――――――――――――――――――――――――――――――――――最下行 Range("A1").CurrentRegion.Rows.Count
――――――――――――――――――――――――――――――――――最右列 Range("A1").CurrentRegion.Columns.Count
――――――――――――――――――――――――――――――――――新規データを入力するセルを選択する Rows("65536").End(xlup).Offset(1).Select
――――――――――――――――――――――――――――――――――全セル選択 Worksheets("Sheet1").Cells.Select
――――――――――――――――――――――――――――――――――列幅を自動調整する Columns("A").EntireColumn.AutoFit
――――――――――――――――――――――――――――――――――全列幅を自動調整 Cells.Select
Selection.Columns.AutoFit
――――――――――――――――――――――――――――――――――セル(A1)に値を入力する Range("A1").Value = "値"
――――――――――――――――――――――――――――――――――セル(A3)に数式を入力する Range("A3").Formula = "A1+A2"
――――――――――――――――――――――――――――――――――使用されているセル範囲を選択 ActiveSheet.UsedRange.Select
――――――――――――――――――――――――――――――――――
●ブックの操作
――――――――――――――――――――――――――――――――――新規作成 Workbooks.Add
――――――――――――――――――――――――――――――――――名前を指定してブックを開く
Workbooks.Open FileName:="C\Data\Test.xls"
――――――――――――――――――――――――――――――――――ブックをすべて閉じる Workbooks.Close
――――――――――――――――――――――――――――――――――ブックを保存して閉じる Activeworkbook.Close True
――――――――――――――――――――――――――――――――――ブックを保存しないで閉じる Activeworkbook.Close False
――――――――――――――――――――――――――――――――――上書き保存 Activeworkbook.Save
――――――――――――――――――――――――――――――――――
●シートの操作
――――――――――――――――――――――――――――――――――開いているシート数を取得 ActiveWorkbook.Worksheets.Count
――――――――――――――――――――――――――――――――――シート非表示 Worksheets("シート名").Visible=False
――――――――――――――――――――――――――――――――――シートアクティブ Worksheets("シート名").Activate
――――――――――――――――――――――――――――――――――シート削除 ActiveSheet.Delete
――――――――――――――――――――――――――――――――――シート追加 WorkSheets.Add
――――――――――――――――――――――――――――――――――ワークシートをブックの最後に2枚挿入する
Worksheets.Add After:=Worksheets(Worksheets.Count), Count:=2
――――――――――――――――――――――――――――――――――シートコピー(同一ブック内)
Worksheets("sheet1").Copy After:=Worksheets("sheet3")
――――――――――――――――――――――――――――――――――シートコピー(別のブックに)
Worksheets("sheet1").Copy Before:=Workbooks("Test.xls").Sheets(2)
――――――――――――――――――――――――――――――――――シートコピー(新規ブックに)
Workbooks("ブック.xls").Worksheets("sheet1").Copy
――――――――――――――――――――――――――――――――――
●その他
――――――――――――――――――――――――――――――――――画面表示の動きを停止 Application.ScreenUpdating = False
処理の最後に、Application.ScreenUpdating = True に戻す
――――――――――――――――――――――――――――――――――確認・警告メッセージを表示しない Application.DisplayAlerts = False
処理の最後に、Application.DisplayAlerts = True に戻す
――――――――――――――――――――――――――――――――――ステータスバーに処理中の文字を表示
Application.DisplayStatusBar = True
Application.StatusBar = "処理を表示する文字列"
処理の最後に、Application.DisplayStatusBar = False に戻す――――――――――――――――――――――――――――――――――
<付録2 Excelではないがよく使う VBA命令一覧>
●文字列操作
――――――――――――――――――――――――――――――――――文字列の文字数を数える A = Len("123456")
Aには「6」が入る
――――――――――――――――――――――――――――――――――文字列の左端から指定した文字数分の文字を切り出す
A = Left("123456",3 )
Aには「123」が入る
――――――――――――――――――――――――――――――――――文字列の中で指定した開始文字数から指定した文字数分の文字を切り出す
A = Mid("123456", 3 , 2 )
3文字目から2文字抜き出す
Aには「34」が入る
――――――――――――――――――――――――――――――――――文字列の右端から指定した文字数分の文字を切り出す
A = Right("123456", 3 )
Aには「456」が入る
――――――――――――――――――――――――――――――――――文字列を指定した文字で分割し、1次元配列へ格納する
※配列の開始は0からになることに注意
A() = Split("1-2-3-4-5-6", "-")
A(0)=1 A(3)=4
A(1)=2 A(4)=5
A(2)=3 A(5)=6
――――――――――――――――――――――――――――――――――指定された文字列の一部を、別の文字列で指定された回数分で置換した文字列を返す
A = Replace("123456","6","1")
6を見つけ、1に置換する
Aには「123451」が入る
――――――――――――――――――――――――――――――――――文字列を検索し、最初に見つかった文字位置を返す
A = InStr("123456", "3")
3の位置を前から何番目か検索する
Aには「3」が入る
――――――――――――――――――――――――――――――――――最後の文字位置から検索を開始し、最初に見つかった先頭からの文字位置を返す
A = InStrRev("123456","5")
5の位置を後ろから何番目か検索する
Aには「2」が入る
――――――――――――――――――――――――――――――――――アルファベットの大文字を小文字に変換
A = LCase("ABC")
Aには「abc」が入る
――――――――――――――――――――――――――――――――――アルファベットの小文字を大文字に変換
A = UCase("abc")
Aには「ABC」が入る
――――――――――――――――――――――――――――――――――
●ファイル操作
――――――――――――――――――――――――――――――――――ファイルをコピーする
FileCopy "C:\data.txt" , "D:\data.txt"
コピーしつつ、ファイル名の変更も可能
――――――――――――――――――――――――――――――――――ファイルを削除する Kill "C:\data.txt"
――――――――――――――――――――――――――――――――――ファイルの名前を変える Name "C:\old_name.txt" as "C:\new_name.txt"
――――――――――――――――――――――――――――――――――ディレクトリの作成 MkDir "C:\AAA"
――――――――――――――――――――――――――――――――――ディレクトリの削除 RmDir "C:\AAA"
――――――――――――――――――――――――――――――――――
<付録3 セルの列名と数値>
R1C1形式にいちいち切り替えてプログラミングをするのも面倒な場合がある。そこで、下の数列番号を参照しながらプログラミングを行うと、いちいち切り替えずに済むので活用して欲しい。
例:**は何番目?
BC = AZ + C = 52 + 3 = 55番目
GG = FZ + G = 182 + 7 = 189番目
~あとがき~
プログラムは中学生のころから趣味として30年以上やっています。MSX BASICとN88-BASIC(PC-98)、ポケコンBASIC、マシン語(アセンブラ、ニーモニック)、C言語、Perl、そしてVB、最後にVBAですかね。JAVAは断念したかな。自作のゲームを作りたいという思いでしたね。
でも、私はプログラマではありません。そのおかげで、プログラムをよくわからない人の気持ちが、プロのプログラマに比べてわかるつもりです。
知ってしまうと、知らない人の気持ちがわからくなるのです。そして、知ってしまって、当たり前になると、無意識にそのルールや言葉を使ってしまいます。
コンピューター言語の本を開くと、いきなり専門用語のオンパレードで、まるで外国語を学んでいるかのような気分になるでしょう。
私は、これまで会社の中で、一般の事務業務を担当されている方々にVBAを500人以上教えてきた経験があります。当然、文系の方々ですし、いわゆる、事務のおば様たちです。強敵ですよ。このような方々にどう教えるかを思案してできたのが、このテキストになっています。
本文中にも書きましたが、別に素晴らしいプログラムを書く必要は無いのです。あなたなりの理解の範囲で、昨日より少しでも効率よく、仕事が楽にできるようになればいいのです。
少しでも、皆様のVBA理解の一助になれば幸いです。
2020年1月1日
Macro-K
いただいたサポートは、有益な情報を提供し続けるための活動にあてていきたいと思います!