-PR-
解決済み

excelを使用したVBAの問題に関する質問です。

  • 困ってます
  • 質問No.9331005
  • 閲覧数139
  • ありがとう数1
  • 気になる数1
  • 回答数3
  • コメント数0

お礼率 38% (19/50)

excelを使用したVBAの問題に関する質問です。 下記のサイトの問題19の解答の中で、 http://excel-ubara.com/excel-answer/EXCELVBA619A.html



'縦合計の客単価
If i = 4 Then
Cells(20, j) = Cells(18, j) / Cells(19, j)
End If



なぜ、週を表している「i」が「4」(if=だったら)なのでしょうか?
「4」だった場合、「合計」欄ではなく、
「第4週目」欄を表すのではないでしょうか?


実は以前にもこの問題19の回答について質問させて頂いております。
しかし、未熟ゆえ、未だに全体的にこの問題の回答が理解できません。

もしよろしければ、
回答全体をひとつずつ「なにがしたいのか」、「どうしてこんなことをしているのか」、について
丁寧にお教え頂けますと、とても助かります。


VBAを始めたばかりの初心者でいて、
理解力が乏しいため

お詳しい方がいらっしゃいましたら、是非、お教え下さい。

よろしくお願い致します。
通報する
  • 回答数3
  • 気になる1
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.2
レベル14

ベストアンサー率 43% (7214/16615)

>なぜ、週を表している「i」が「4」(if=だったら)なのでしょうか?

このif文が成り立った時のみ「縦合計の客単価」を計算しています。

「縦合計の客単価」は「合計の売上÷合計の客数」で求めます。

さて、ここで「合計の売上」と「合計の客数」が「最終的な数値に確定する」のは、どの時点でしょうか?

それは「1~4週目の計算を順次に行なって、4週目の計算が終わった時」です。

では「4週目の計算が終わった時」とは「どの変数が、どういう値になった時」でしょうか?

それは「iが4になった時」です。

つまり

If i = 4 Then

が成り立つ時です。

>「合計」欄ではなく、
>「第4週目」欄を表すのではないでしょうか?

Cells(20, j) = Cells(18, j) / Cells(19, j)

は「18行目の値を、19行目の値で割って、20行目に入れる」です。

表の構造をよく見て下さい。

1行目:見出し
2~5行目:1週目の日付、売上、客数、客単価
6~9行目:2週目の日付、売上、客数、客単価
10~13行目:3週目の日付、売上、客数、客単価
14~17行目:4週目の日付、売上、客数、客単価
18行目:合計の売上
19行目:合計の客数
20行目:合計の客単価

18行目には何が入っていますか?

19行目には何が入っていますか?

20行目には何が入りますか?

それを踏まえて、4週目の計算が終わった時点で

Cells(20, j) = Cells(18, j) / Cells(19, j)

は、何をしていますか?

18~20行目は「合計に関する行」です。

「合計に関する行」について処理していて「4週目の行」には、何もしていません。

因みに、1~4週目の客単価を計算しているのは

Cells(ix + 3, j) = Cells(ix + 1, j) / Cells(ix + 2, j)

の行です。

ixは「1週目が2、2週目が6、3週目が10、4週目が14」と変化していき「各週の日付の行」の行番号を示す値が入っています。

表の各週は「日付」「売上」「客数」「客単価」の順に行が構成されているので「ixが日付の行」「ix + 1が売上の行」「ix + 2が客数の行」「ix + 3が客単価の行」を意味しています。

なので

Cells(ix + 3, j) = Cells(ix + 1, j) / Cells(ix + 2, j)

は「各週の、売上を客数で割って、客単価に入れている」のです。

話を戻して

Cells(20, j) = Cells(18, j) / Cells(19, j)

を見てみましょう。

実行されるタイミングは「4週目の計算が終わった時」ですが、計算しているのは、固定の「18~20行」であって「4週目の行」ではありません。

4週目の行なら

Cells(ix + 3, j) = Cells(ix + 1, j) / Cells(ix + 2, j)

になる筈です。ですが、プログラムは

Cells(20, j) = Cells(18, j) / Cells(19, j)

になっています。

つまり「4週目の下にある、合計の欄を計算している」のです。

タイミングは「4週目だけ」ですが「計算対象は合計の行」なのです。

因みに「forループしている最中、4週目だったら、合計を計算する」としないで「forループが終わって、合計以外がすべて確定したら、合計を計算する」でも、同じ結果になります。

その場合、プログラムは

Sub 練習問題19()
  Dim i As Long
  Dim j As Long
  Dim ix As Long
  '全体のfont色をリセット
  Range("A1:J20").Font.ColorIndex = xlAutomatic
  '合計欄の消去
  Range("J2:J20").ClearContents
  Range("C18:I20").ClearContents
  '4週
  For i = 1 To 4
    ix = (i - 1) * 4 + 2 '日付の行位置
    '単価の消去と小数設定
    With Range(Cells(ix + 3, 3), Cells(ix + 3, 10))
      .NumberFormatLocal = "0.0"
      .ClearContents
    End With
    '7列
    For j = 3 To 9
      '横合計と客単価
      Cells(ix + 1, 10) = Cells(ix + 1, 10) + Cells(ix + 1, j)
      Cells(ix + 2, 10) = Cells(ix + 2, 10) + Cells(ix + 2, j)
      Cells(ix + 3, j) = Cells(ix + 1, j) / Cells(ix + 2, j)
      '縦合計
      Cells(18, j) = Cells(18, j) + Cells(ix + 1, j)
      Cells(19, j) = Cells(19, j) + Cells(ix + 2, j)
    Next
    '横合計の客単価
    Cells(ix + 3, 10) = Cells(ix + 1, 10) / Cells(ix + 2, 10)
    For j = 3 To 9
      If Cells(ix + 3, j) < Cells(ix + 3, 10) Then
        Cells(ix + 3, j).Font.Color = vbRed
      End If
    Next
    '縦横合計
    Cells(18, 10) = Cells(18, 10) + Cells(ix + 1, 10)
    Cells(19, 10) = Cells(19, 10) + Cells(ix + 2, 10)
  Next
  '総合計の客単価
  For j = 3 To 10
    Cells(20, j) = Cells(18, j) / Cells(19, j)
  Next
End Sub

となります。

このプログラムは、元のプログラムの最後の部分で

  '縦横合計の客単価
  Cells(20, 10) = Cells(18, 10) / Cells(19, 10)

とやっていたのを

  '総合計の客単価
  For j = 3 To 10
    Cells(20, j) = Cells(18, j) / Cells(19, j)
  Next

に変えてあります。

また、上の「For i = 1 to 4」の中にある

      '縦合計の客単価
      If i = 4 Then
        Cells(20, j) = Cells(18, j) / Cells(19, j)
      End If

が無くなっています。

つまり

      '縦合計の客単価
      If i = 4 Then
        Cells(20, j) = Cells(18, j) / Cells(19, j)
      End If

を「iのForループ」の外に追い出して移動したので、外で「jのForループ」をする必要が出ます。つまり、iのForループが終わった後の

  '縦横合計の客単価
  Cells(20, 10) = Cells(18, 10) / Cells(19, 10)

の部分を

  '縦合計の客単価
  For j = 3 To 9
    Cells(20, j) = Cells(18, j) / Cells(19, j)
  Next
  '縦横合計の客単価
  Cells(20, 10) = Cells(18, 10) / Cells(19, 10)

のようにする訳です。

で、この処理を良く見ると「3~9列目をループで処理してから、単独で10列目を処理」しています。だったら「3~10列目まで一気に処理してしまう」で構いません。

その結果、改良したプログラムは、最後が

  '総合計の客単価
  For j = 3 To 10
    Cells(20, j) = Cells(18, j) / Cells(19, j)
  Next

になっているのです。jのForループが「3~9」ではなくて「3~10」になっている事に注目して下さい。
お礼コメント
jl777

お礼率 38% (19/50)

大変に分かりやすいご説明、ありがとうございました。参考にさせて頂きます。m(__)m
投稿日時 - 2017-05-19 17:48:22

その他の回答 (全2件)

  • 回答No.1
レベル12

ベストアンサー率 66% (266/402)

他カテゴリのカテゴリマスター
1~4週の合計が確定するのが4週目だからです。
各週で合計をセルに書き込むと処理速度の低下になるためです。

For i = 1 To 4~Nextにより、18~20行の3行の情報は、
1週目から順次算出していき4週まで繰り返します。
その際の1週目、1~2週目、1~3週目、1~4週目の合計のうち、
4週目の合計がすべての合計となるためi=4(4週目)のときにだけ
合計欄の処理をしています。

たとえば、以下のように変更して各週において処理を行っても結果は同じですよ。最後に合計された4週目の値が上書きされるのでi=1~3の処理は無駄なだけですが。

If i = 4 Then
  Cells(20, j) = Cells(18, j) / Cells(19, j)
End If
   ↓
Cells(20, j) = Cells(18, j) / Cells(19, j)

確認のため、ifの条件式をi=1を設定したあと実行してみてください。
月曜日の合計客単価は「916.4567901」と表示されます。
実際の合計の客単価は299959/323=928.6656347なので
異なっていますよね。
これは、第1週目の月曜日74,233/81=916.4567901の時点での
合計が計算されているからです。


  • 回答No.3
レベル12

ベストアンサー率 66% (266/402)

他カテゴリのカテゴリマスター
No1に補足です。
>回答全体をひとつずつ「なにがしたいのか」、
>「どうしてこんなことをしているのか」、について

エクセルのVBAにはブレークポイント(プログラムの中で一時停止する箇所)を指定したり、プログラムの先頭またはブレークポイントで一時停止した箇所から1行ずつ処理を実行する「ステップ実行」というデバッグ機能があります。

F8でステップ実行しながら各行がどのようにセルに反映されていくのか
1行ずつ確認しながら実行していくことでプログラムの流れがつかめると思いますので、まずは挑戦してみてください。
http://plus1excel.web.fc2.com/learning/l301/t405.html

コード内のコメントを頼りにやはりご自身で取得、
どうしても理解できない場合に的を絞り質問されたほうが良いかと思います。
このQ&Aのテーマ
このQ&Aで解決しましたか?
関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-

特集


開業・独立という夢を持つ人へ向けた情報満載!

ピックアップ

ページ先頭へ