<HOME  <お願い事項   <Access2002 TOP   <Access2000 TOP   <サイト内検索
 Access97 VBAの森>縦のものを横に



(3)

4.くり返し処理を作ります。

くり返し処理にはいろいろなパターンがあります。今回のように決まった回数ではなくて、「売上テーブルの最後のレコードまで」というような一種の条件が付いている場合は、Do.. Loop..という構文がよいでしょう。

Do Loopにもいろんな種類があって、微妙に結果が異なるので、ヘルプを見て違いを比べてみてください。

今日は・・・そうですねぇ。いろいろ使いまわしがきくと思うんで、Do Until ...Loopというのをやってみましょう。

ある条件が満たされるまで処理を繰り返す、というタイプの繰り返し処理です。

Do Until ループを抜ける条件
 (処理)
Loop

と、こんな感じですね。今回は、「売上テーブルの最後のレコード」になるまで処理を繰り返し、そのレコードの処理が完了したところでLoopから抜けるようにしようと思います。ループを抜ける条件は

テーブル名.EOF

と書きます。テーブル名はこの場合、変数にしてますよね。わたしはd1という名前の変数にしてますけど、みなさんは?

Do Until d1.EOF
 (処理)
Loop

「d1のエンド・オブ・ファイル」という意味ですかね。もっといろんな方法がありますけど、これは結構使えるパターンだと思います。

(処理)っていうのは、書くとこじゃないですよ。これから書くとこなので、1行くらいあけておいていただければオッケーです。

で、さらに大切なのが、「指示しないとずーっと1レコード目から動かない」ということです。処理が終わってLoopする前に、必ずd1の次のレコードに移動しておいてもらわないとなんないわけです。

Do Until d1.EOF
 (処理)
d1.MoveNext
Loop

この辺も、どういう順番で書くかとか、ケースバイケースだと思います。今日はとりあえずこれで行きましょう。




5.1月だったら、2月だったら、3月だったら・・・。

んじゃ、真ん中の処理を作ります。

まず、そのレコードの[売上日]が何月なのか、Datepart関数を使って判断させないといけないんですよね。で、この関数によって出された答えが、Select Caseの条件にあたるわけです。

Select Case DatePart("m",d1![売上日])
 Case 1
 (1月のときはどうする)
 Case 2
 (2月のときはどうする)
 Case 3
 (3月のときはどうする)
 ・
 ・
 ・
End Select

と、こんな感じかな。

d1![売上日]という書き方は、みなさんオッケーでしょうか。VBAやSQL文などの場合、テーブルの中のフィールド名とか、フォームの中のテキストボックス名をあらわすときは、[ ]で囲んで、びっくりマークで区切って入力するんですよね。

これが、Do Loopの中の処理にあたります。

で、肝心の(1月のときはどうする)っていう部分のお話です。これそのまま書いたってだめですよね。何をするかというと、1月ならd2![1月]に、2月ならd2![2月に]・・・とやるわけですよね。これは、そのまんまだったら、

d2![1月] = d1![売上金額]

と、イコールで結んでやるわけですよね。右から左に代入するってことになります。

でもでも、ヨーク考えてください。今回は、ループしてるわけですよ。この部分を、「売上テーブルのレコード数分」通過するわけです。代入するということは、最後のレコードの売上金額しか残らないことになります。

イコールですからねぇ。

と、どうするかというと、

d2![1月] = d2![1月] + d1![売上金額]

これでオッケーなはず。この違い、じっくり見比べてみてください。このふたつの式の意味が分からない・・となると、VBAを使いこなすのは少々難儀かも・・・。さくっと慣れてしまいましょう。


さあて、ここまでの情報を基に記述をしてみると・・・。

テーブルの中に、データを追加/更新するのには、AddNewとUpdateっていうのを書かないといけなかったですよね。

と、すると・・・えーと・・・

Do Until d1.EOF

Select Case DatePart("m",d1![売上日])
 Case 1
 d2.AddNew
 d2![1月] = d2![1月] + d1![売上金額]
 d2.Update

 Case 2
 d2.AddNew
 d2![2月] = d2![2月] + d1![売上金額]
 d2.Update

 ・
 ・
End Select

d1.MoveNext
Loop

これでいいのかな・・・ん?まてよ??だめじゃんこれじゃ!!!

これじゃ、一回ループする毎に、新しいレコードをd2、つまり「売上集計」のテーブルに作成しちゃうってことにならないですかね。んー、じっくりと眺めて、上から順々に処理を追っていってみましょう・・・。

動くことは動きますが、これじゃ、ぜんぜん集計にはならないですねぇ。

1回目のループのときはAddNewだけど、2回目以降はEditってことになりますね。おそらく。うーん・・・でもそんな処理、なんか非効率な感じがするなぁ。。。。。しません?

それに、この構文だと、とにかく1回ループする毎に、「売上集計」のテーブルの方にもデータの書き込みするわけですよね。

なんか、書類をファイルに綴じるときに、1枚ずつパンチで穴あけてる人みたいな感じかも・・・。1枚書類取って、パンチで2つ穴あけて、ファイルに通して、ファイルを閉じて、2枚目の書類手に取って、パンチで2つ穴あけて、ファイルに通して、ファイルを閉じて、3枚目の書類手に取って、パンチで2つ穴あけて、ファイルに通して・・・・。え、もういい?

みなさんならどうします?10枚ずつくらいまとめて穴をあけて、全部穴あけ終わってから、揃えてファイルに通しますよね。まあ、どう書いても処理が正しく完了すればそれが正解ですけれど、プログラムの書き方も書くありたいですよねぇ。




6.やはり、変数か・・・・。

でも、くるくる何回もループしますからね。
2レコード目の処理をするためにループの先頭に戻って処理をはじめたときに、1レコード目のときにゲットした[売上金額]をどっかに残しておかないといけないですよね。
でも、どこに残しておいたら・・・。

どういうやり方をしましょうかねぇ。いろいろ考えられると思うんですが・・・ここはひとつ、変数を使ってみましょうか。

VBAでの腕の見せ所その2は、変数を効率よく使う!(その1はセンスよくループ処理を作る)

1月から12月までの、答えを仮に入れておく器を作るのです。12個要りますね。

変数ですから、Dimというのを使って、まずどういう名前の変数を使いたいのか、ずらっと並べておきます。
で、できれば、その変数の中に数値が入るのか、文字が入るのか・・・ちゃんと決めて書いてあげた方が何かとよいです。

Public Function BBB()
Dim db As Database
Dim d1, d2 As Recordset
Dim m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12 As Integer
Set db = CurrentDb
Set d1 = db.OpenRecordset("売上テーブル")
Set d2 = db.OpenRecordset("売上集計")

m1 = 0
m2 = 0
m3 = 0
m4 = 0
m5 = 0
m6 = 0
m7 = 0
m8 = 0
m9 = 0
m10 = 0
m11 = 0
m12 = 0

書くところはどこでもいいんですが、まあ、なんとなく気分的に、データベースとかテーブルとかの変数を宣言したすぐ下あたりがいいんじゃないかなー・・・。
もうちょっと効率のいい書き方がありそうなカンジしますけど、まあ、今日は練習なのでこんな感じで・・・。

変数はカンマで区切って横に並べて宣言することもできます。縦に並べるのと同じことです。

Integerはいんてじゃーと読みます。数値型の一種です。まあ、細かいことは後回しにしましょう。

で、その下あたりに、変数をゼロにしておく、つまり初期化するような構文を入れておくといいんじゃないかなーと思います。
まあ、べつにこんなことしなくても、宣言したてほやほやの変数の中に、変な数字が残っちゃってることはないんですが、何も入ってないということ=ゼロとは限らないんですよ。

何もない=ゼロにしたければ、どこかでそういう配慮を考えないとなりません。手っ取り早いのは、一番最初にこうやってゼロをぶち込んでおくやりかたじゃないかと・・・。

それで、改めて先ほどの処理・・・。

Do Until d1.EOF

Select Case DatePart("m", d1![売上日])
Case 1
m1 = m1 + d1![売上金額]
Case 2
m2 = m2 + d1![売上金額]
Case 3
m3 = m3 + d1![売上金額]
Case 4
m4 = m4 + d1![売上金額]
Case 5
m5 = m5 + d1![売上金額]
Case 6
m6 = m6 + d1![売上金額]
Case 7
m7 = m7 + d1![売上金額]
Case 8
m8 = m8 + d1![売上金額]
Case 9
m9 = m9 + d1![売上金額] 
Case 10
m10 = m10 + d1![売上金額]
Case 11
m11 = m11 + d1![売上金額]
Case 12
m12 = m12 + d1![売上金額]
End Select

d1.MoveNext
Loop

で、Select Caseの処理が終わって、ループを抜けた後、この後に、m1からm12までの変数の中には、「売上テーブルの最後のレコードまでくるくるループして足しあわせた売上金額の合計」が入っているはずなんですよね。

もっとなんか工夫できそうな気もしますが・・・こんな感じでいきましょうか。