Excel VBAを自分の武器に
はじめに
4月からプログラミングの業務が開始になるので、Excel VBAでプログラミングの勉強をしていく。
今いる職場は、色んなことがあって去ることになった。
この資本主義社会で、企業の問題を解決していこう。
組織で協調的にやっていくことも必要だ。
しかし、自分の性格を踏まえると、プログラミングスキルを磨いていくのが手っ取り早い。
まずは、Excel VBAを身につけて、自信を持つ。
情熱が心の奥底から湧いてくるのを感じる。
それでは早速始めていこう。
新しい世界の幕開けだ。
判定処理を行う
VBAの練習問題を解答・動画・サンプルファイルつきで紹介!学習のコツも解説 | ユースフル
こちらのサイトで、判定処理を書いてみる。
使用する演習ファイル
以前ダウンロードした演習ファイルを使用していく。
まだの方は、こちらをクリックして、ダウンロードしていただきたい。
開くと、以下のモーダルが出現する。
「マクロを有効にする」をクリックして、進んでいく。
このような画面が開かれる(売り上げ管理表は空欄のはず)。
どんな問題か
基準年月日が2018年10月31日と一致する日付のみを転記してみよう。(セルの8~12行目)
という問題だ。
そのため、売上管理表からは、データを削除しておく。
データが残っていたのは、以前の記事で解いた問題が残っているからだ。
転記元の箇所はこちら。
また、出力先のエリアに空白行ができないようにする必要がある。
さらに、押したら処理が始まるボタンを作成する必要がある。
マクロ実行後のイメージはこちら。
さっそく問題を解いていく
札幌のスタバで高校生が話していた内容を意識して、問題を解いていく。
どんな内容かというと、以下のような会話だ。
「お前さ〜。答え見て暗記しても意味ないって〜。答えは見ずに、試行錯誤して解いていくから実力が付くんだよ」
通常の転記をする場合
まずは、ベーシックなやり方から確認していこう。
詳しい書き方は、以前の記事を参考にしていただきたい。
以下の記述で、売上管理表に値を転記することが出来ていた。
開発タブのマクロをクリックすると表示される以下のモーダルで、上記の処理を記述した「データの転記処理」を実行する。
そうすると、売上管理表に値が転記された。
今回やりたいこと
今回やりたいことは、日付が「2018/10/31」の行のみを転記すること。(範囲は、セルの8~12行目)
さらに、以下のような空白を作らないようにする。
IF文の使い方
そのまま転記すると、日付が「2018/10/18」などの10/31以外のデータも転記されてしまう。
そのため、E列の日付が「2018/10/31」の場合に、転記の処理を行うというプログラムを記述する必要がある。
まずは、Excel VBAのIF文のお作法を学ぼう。
こちらのサイトで、基本的なIF文の使い方が学べた。
以下のように、「If 条件 Then 条件が当てはまるときの処理 End If」という感じで書く。
Cellsは、Cells(行, 列)という形で、行と列の番号を指定して、セルを取得することができる。
If文の使い方について、詳しくはこちらの記事で書いた。
IF文を今回やりたいことに応用する
データの転記処理のマクロを編集していく。
マクロモーダルで、データの転記処理を選択した状態で、編集をクリックしていただきたい。
コードの編集画面を開くことが出来た。
条件は、「日付が、2018/10/31」なので、以下の条件式と思われる。
If Range("E8:E12") = "2018/10/31" Then
Range("C8:H12").Copy Range("L8:Q12")
End If
等しいことを表す比較演算子は、「=」である。
コードを実行するとエラーが発生した
「型が一致しません」とのこと。
デバッグを押すと、以下の黄色の箇所に問題があることが分かった。
おそらく、Range(“E8:E12”) と 2018/10/31の型が合っていない。
詳しくは、こちらの記事をご確認いただきたい。
型とは
Excel VBAにおける型とは、何なのだろうか?
こちらのサイトによると、以下のような型が存在する。
- 整数型(Integer)
- 長整数型(Long)
- 通貨型(Currency)
- 単精度浮動小数点数型(Single)
- 倍精度浮動小数点数型(Double)
- 文字列型(String)
- 日付型(Date)
- ブール型(Boolean)
- オブジェクト型(Object)
- バリアント型(Variant)
先ほどのエラーの原因は、「Range(“E8:E12”)がオブジェクト型で、2018/10/31が文字列型であること」と考えられる。
型チェックする方法
それでは、Excel VBAで型をチェックするには、どうすればいいのだろうか?
こちらのサイトによると、TypeNameを使用するらしい。
上記の例で言うと、intAという変数に5が入っている。
12行目で、TypeNameを使って、intAの型を調べている。
出力結果は、Integer。
5は整数なので、Integerという型が割り当てられている。
型チェックでエラーの原因を解明していく
まずは、Range(“E8:E12”)の型チェックをしていこう。
以下のようにして、型チェックを試みた。
実行すると同じように型のエラーが出た。
Rangeは何かという疑問を解消していこう。
Rangeはセルを指定する方法だ。
Debug.Printの使い方
そもそも、Debug.Printはどのように使うのか。
こちらのサイトによると、イミディエイトウィンドウという場所に、返り値を出力するらしい。
イミディエイトウインドウはどこから開けるのか?
VBAの下の方に色々なウインドウが表示されていたが、ばつ印をクリックすると、イミディエイトウインドウが出てきた。
試しに、以下の処理を書いていたので、1という値が出力されていた。
こちらのサイトでは、Control + Gを押せば、イミディエイトウインドウが表示されると書いてある。
しかし、macを使用しているので、この方法では開くことが出来なかった。
上部のメニューから、表示を選択し、イミディエイト ウインドウを選択すると開くことができる。
「^ ⌘ G」のショートカットでも開くことができる。
「^」は「Control」のことだ。
「⌘」は「Command」
まずは、1セルだけで条件分岐を書いてみる
まずは、以下のような処理を書いてみた。
実行すると、「変数が定義されていません。」というエラーが出た。
セルのE8を指定したつもりが、変数名のE8と認識されてしまったらしい。
セルのE8を指定するにはどうすればいいのか。
Range(“E8”)と書いてみる。
実行を押すと、以下のように値がコピーされた。
これだと、日付が「2018/10/31」以外も転記してしまっている。
E8が「2018/10/18」だった場合、C8からG12の範囲を転記するという処理を書いていたためだ。
やりたいことは、E列に入力してある文字が、「2018/10/31」だった場合に、その行を転記するということ。
なので、以下のようにVBAを書き換えた。
売上管理表を空欄にして、実行すると、以下のように値が転記された。
先ほどは、転記元のH列を含めていなかったが、今回は含めた。
備考欄は空白だったから、含めなくても結果に変化はないが、念の為、正確に記述した。
これで、とりあえず、一行だけでやりたいことを実現することが出来た。
今回は、C8〜H12セルで日付が「2018/10/31」の場合のみ、その行を転記するという処理を書く必要がある。
ちなみに今気づいたが、D2セルに、基準年月日として「2018/10/31」が記載されていた。
この値をセルで指定するのもいいかもしれない。
繰り返し処理の書き方
先ほどの条件式を、8行目〜12行目に対して繰り返せば、今回やりたいことが実現できそうだ。
繰り返し処理の書き方については、こちらの記事で解説した。
今回やりたいこと
やりたいことを日本語にすると以下のようになる。
C8セルからH12の範囲で、8行目から順番に繰り返し処理を行う。
もし、E列に記入されている値が「2018/10/31」なら、その行を売上管理表に転記する。
まずは、以下のように書いてみた。
実行すると、このようになった。
8行目から12行目まで繰り返し処理が行われ、もしE8やE12が2018/10/31なら8行目の岡田さんのデータを売上管理表に転記するというコードとなっている。
やりたいことは、日付が2018/10/31の行の人のデータを転記すること。
こうしてみたら、氏名だけを転記することができた。
他の列も転記するには、どうすればいいのだろうか?
以下のように書いたら、他の列も転記することができた。
実行結果はこちら。
やりたいことにだいぶ近づいた。
空白行を詰める
空白行が三つできてしまっているが、これを無くすにはどうすればいいだろう。
eという変数を追加したらできた。
ステップバイステップで解説していこう。
最初は、E8が2018/10/31かどうかが調べられる。
2018/10/18なので、elseの後が実行されて、e が1になる。
2周目は、E9が2018/10/31かどうかが調べられる。
2018/10/19なので、elseの後が実行されて、eが2になる。
3周目は、eが3になる。
4周目は、E11が2018/10/31なので、If文の条件に当てはまり、転記の処理が実行される。
Range(C11,H11).Copy(L8,Q8)が実行される。
5周目も条件に当てはまり、Range(C12,H12).Copy(L9,Q9)が実行される。
少し説明が飛躍している部分もあるが、こんな感じの説明となる。
ボタンを作成する
以前の記事でボタンを作成する方法について書いた。
開発タブのボタンをクリックして、売上管理表作成のボタンを作成した。
このボタンを押すと、先ほど書いた処理が実行される。
模範解答の確認
こちらのページに以下の模範解答があった。
Sub sampleAnswer_step3()
'-------------------------------------------------------------------
' 変数を使って基準年月日と同日の明細を転記する(上から5行目まで)
'-------------------------------------------------------------------
'出力行を指定する変数を定義
Dim cntRow
'出力行の開始位置を設定
cntRow = 8 '8行目から出力する
'基準年月日(D2)と1行目の日付が同一かを判定する
If (Range("E8").Value = Range("D2").Value) Then
Range("L" & cntRow).Value = Range("C8").Value
Range("M" & cntRow).Value = Range("D8").Value
Range("N" & cntRow).Value = Range("E8").Value
Range("O" & cntRow).Value = Range("F8").Value
Range("P" & cntRow).Value = Range("G8").Value
Range("Q" & cntRow).Value = Range("H8").Value
'1行出力したため、出力行の位置を+1する
cntRow = cntRow + 1
End If
'2行目の日付を判定する
If (Range("E9").Value = Range("D2").Value) Then
Range("L" & cntRow).Value = Range("C9").Value
Range("M" & cntRow).Value = Range("D9").Value
Range("N" & cntRow).Value = Range("E9").Value
Range("O" & cntRow).Value = Range("F9").Value
Range("P" & cntRow).Value = Range("G9").Value
Range("Q" & cntRow).Value = Range("H9").Value
'1行出力したため、出力行の位置を+1する
cntRow = cntRow + 1
End If
'3行目の日付を判定する
If (Range("E10").Value = Range("D2").Value) Then
Range("L" & cntRow).Value = Range("C10").Value
Range("M" & cntRow).Value = Range("D10").Value
Range("N" & cntRow).Value = Range("E10").Value
Range("O" & cntRow).Value = Range("F10").Value
Range("P" & cntRow).Value = Range("G10").Value
Range("Q" & cntRow).Value = Range("H10").Value
'1行出力したため、出力行の位置を+1する
cntRow = cntRow + 1
End If
'4行目の日付が同一かを判定する
If (Range("E11").Value = Range("D2").Value) Then
Range("L" & cntRow).Value = Range("C11").Value
Range("M" & cntRow).Value = Range("D11").Value
Range("N" & cntRow).Value = Range("E11").Value
Range("O" & cntRow).Value = Range("F11").Value
Range("P" & cntRow).Value = Range("G11").Value
Range("Q" & cntRow).Value = Range("H11").Value
'1行出力したため、出力行の位置を+1する
cntRow = cntRow + 1
End If
'5行目の日付が同一かを判定する
If (Range("E12").Value = Range("D2").Value) Then
Range("L" & cntRow).Value = Range("C12").Value
Range("M" & cntRow).Value = Range("D12").Value
Range("N" & cntRow).Value = Range("E12").Value
Range("O" & cntRow).Value = Range("F12").Value
Range("P" & cntRow).Value = Range("G12").Value
Range("Q" & cntRow).Value = Range("H12").Value
'1行出力したため、出力行の位置を+1する
cntRow = cntRow + 1
End If
End Sub
出力行の開始位置を変数で指定している。
条件に当てはまって値を出力したら、この変数に1を加えている。
条件に当てはまらなかったら、変数はそのままなので、出力先に空白ができない。
コメントを残す