みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
エクセルVBAを使ってバラバラの経費精算書のデータをデータベースに集約するを目標にシリーズ連載しています。
前回の記事はこちら。
オブジェクトの扱い方とセルの値のコピー&ペーストという基本的かつ重要な内容となっております。
今回はその続き。
エクセルVBAでDo While~Loop文を使って複数行の経費データをコピペできるようにしていきたいと思います。
では、行ってみましょう!
前回のおさらい:一行だけコピーする
まず、社内のスタッフの太郎さんから受け取ったエクセルファイルについて、以下のような「経費精算書」シートがありまして
これを「経費データ」という以下のシートに一行だけコピペするというプログラムを作りました。
コードはこちらです。
Sub 経費精算データ取り込み()
Dim ws As Worksheet
Set ws = Workbooks("201807経費精算書_経費_3001.xlsx").Worksheets(1)
wsData.Cells(2, 1).Value = ws.Range("G4").Value '1 対象月
wsData.Cells(2, 2).Value = ws.Cells(12, 1).Value '2 日付
wsData.Cells(2, 3).Value = "" '3 部署No
wsData.Cells(2, 4).Value = ws.Range("G6").Value '4 部署
wsData.Cells(2, 5).Value = ws.Range("G8").Value '5 社員No
wsData.Cells(2, 6).Value = ws.Range("G7").Value '6 氏名
wsData.Cells(2, 7).Value = ws.Cells(12, 2).Value '7 科目
wsData.Cells(2, 8).Value = ws.Cells(12, 5).Value '8 摘要
wsData.Cells(2, 9).Value = ws.Cells(12, 6).Value '9 金額
wsData.Cells(2, 10).Value = ws.Cells(12, 7).Value '10 備考
End Sub
太郎さんのエクセルファイルには、経費データは5行分ありますが、この例では1行だけしかコピペできていませんね。
ということで、今回は繰り返し処理を入れて全てのデータ行をコピーしたいと思います。
Do While~Loop文による繰り返し
コンピュータは繰り返しが得意です。VBAでも繰り返しのための構文がいくつか用意されていまして、今回はDo While~Loopを習得していきたいと思います。
書き方はこちら。
’繰り返したい処理
Loop
けっこうシンプルですね。
条件式が満たされている間だけ繰り返しを行います。逆に言うと、条件式が満たさなくなったら繰り返しは終了します。
Do While~Loop文で行を移動させながら繰り返しをする
Do While~Loop文を使って、行を移動させながら繰り返し処理をするルーチンは以下のようにまとめることができます。
カウント変数 = 最初の行数
Do While Worksheetオブジェクト.Cells(カウント変数, 列数).Value <> ""
'繰り返したい処理
カウント変数 = カウント変数 + 1
Loop
まず、「行を移動する」という要素をルーチンの中に仕込んであげる必要があります。
そのために、カウント変数を自前で用意して
- 繰り返しを開始となる開始行の行数を初期値として設定する
- 繰り返し処理の中で処理する行数を1増加させる
という処理を入れる必要があります。
また、条件式のところですが、例えば太郎さんの経費精算書をよく見ると、最後のデータ行の次の行の1列目は空になっていますね。
ですから、「1列目のデータが空だったら終了」、裏を返すと「1列目のデータが空でない間は繰り返す」とすれば良いわけです。
「<>」は「等しくない」という意味です。「=」の逆ですね。
また、「””」は空文字、つまり何も入力されていない状態を表しています。
これにより、カウント変数が表す現在の行数の、指定した列数のセルの値が空っぽでない間は繰り返してねという意味になります。
今回の場合、太郎さんのデータの開始行は12行目になり、データが空になったか確認するセルの列数を上記の通り1列目とすると、以下のようなルーチンを作ればよいわけです。
Dim i As Long
i = 12
Do While ws.Cells(i, 1).Value <> ""
'繰り返す処理
i = i + 1
Loop
Do While~Loop文を使う際の注意点
Do While文内の繰り返し処理(Doブロックとも言います)の中に「i=i+1」を設置しないと大変なことになります。
このような場合です。
Dim i As Long
i = 12
Do While ws.Cells(i, 1).Value <> ""
'繰り返す処理
Loop
これを実行するとどうなりますか?
iの初期値は12です。
経費精算書の(12,1)には「2018/7/10」という値が入っています。空文字ではありませんので、条件式が成立していて繰り返しがなされることになりますが、いつになったら繰り返しが終わるでしょうか?
そうなんです。恐ろしいことに永久にループをすることになります…!
このような現象を無限ループといいます。
うっかり無限ループが作られているプロシージャを実行してしまった場合には、すかさず Esc キーを押して、処理を中止するようにしてください。
Do While~Loop文で陥りがちな現象ですので、必ずDoブロック内をループが終わるように(つまり条件式が満たされなくなるときがくるように)注意してください。
For~Next文とDo While~Loop文の違いは?
繰り返しでいいますとFor~Next文という代表的な構文もりまして以下の記事で紹介しています。
どのように使い分けたら良いでしょうか?
For~Next文はカウント用変数が最終値に到達したら繰り返しが終わりますので、繰り返しの回数が明確なときに使いやすい場合が多いです。
一方でDo While~Loop文は繰り返し回数が明確でないときに別の条件で終わらせたいときに使いやすい場合が多いですね。
また前述したように、Do While~Loop文は条件文を満たす限り永遠にループをします。きちんと条件文が満たさなくなるときが来るように設計しないといけません。
さらに経費精算書を作った太郎さんが、うっかり途中の行なのに日付の入力を忘れ
ていたらどうなりますか?
その行でDo While~Loop文から抜け出してしまうので、それ以降の行にデータがあったとしても転記がされません。
などといった、業務フロー上のエラーなども有り得ます。
For~Next文でもこういったケースが全くないわけではありませんが、総合してDo While~Loop文のほうが少し上級者向けかも知れませんね。
まとめ
さて、今回はエクセルVBAで条件に応じて繰り返しをするDo While~Loop文の使い方について紹介しました。
繰り返し処理はコンピュータの最も得意とするところ、うまく活用するとお仕事を劇的に効率化できるプログラムが組めますね。
For~Nextとうまく使い分けながら活用していきましょう!
さて、まだDo While~Loop文についてプログラムに落とし込めていませんので、次回その部分を進めていきたいと思います。
どうぞお楽しみに!
連載目次:エクセルVBAで経費データをデータベースに集約する
請求書シリーズと逆のパターンですが、バラバラの帳票からデータ一覧つまりデータベースに情報を集めて蓄積していく、というお仕事も多いと思います。ここでは各担当者から提出された経費精算書をデータベースに蓄積するプログラムを目標にして進めていきます。- 【エクセルVBA入門】バラバラの経費精算書をデータにまとめる
- 【エクセルVBA入門】Do While~Loop文で条件を満たす間繰り返し
- 【エクセルVBA入門】繰り返しを使ってデータの転記をするときの2つのポイント
- 【エクセルVBA入門】With文でプログラムをスッキリわかりやすく書く
- 【エクセルVBA入門】他のワークブックをWithで開く&保存せずに閉じる
- 【エクセルVBA入門】フォルダやファイルを操作するFileSystemオブジェクトとその使い方
- 【エクセルVBA入門】For Each~Next文でフォルダ内のブック全てを開く方法
- 【エクセルVBA入門】シートのデータがある最終行番号を求めるステートメントを徹底解説
- 【エクセルVBA入門】開いたブック名から文字列を抽出して人為的なミスを回避する方法
- 【エクセルVBA入門】マクロを作るときに知っておきたいマスタデータのこと
- 【エクセルVBA入門】開いたブックのファイル名から番号を取り出して数値に変換する
- 【エクセルVBA入門】マクロでVlookupを使ってデータを検索する方法
- 【エクセルVBA入門】Vlookupメソッドを使ったときに発生するエラーを回避する方法
- 【エクセルVBA入門】エラーが発生したときに分岐処理を追加する方法
- 【エクセルVBA入門】オートフィルタや行の非表示で隠れている行を全て表示する