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
条件分岐(IF)|VBA入門

等しいことを表す比較演算子は、「=」である。

コードを実行するとエラーが発生した

「型が一致しません」とのこと。

デバッグを押すと、以下の黄色の箇所に問題があることが分かった。

おそらく、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を加えている。

条件に当てはまらなかったら、変数はそのままなので、出力先に空白ができない。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です