アプリ版:「スタンプのみでお礼する」機能のリリースについて

以前に回答いただいたVBAですが、理解できない部分があったので、抜粋して質問に投稿したところ、多くの方々から、「これでは、わからない」などの指摘をいただき、これでは、以前に回答していただいた回答者様の名誉にかかわると思い全文を記載させていただくことにしました。
 あわせて、この、VBAの詳しい説明を快くしていただける方は回答よろしくお願いします。以下のとうりです。
 A列  B列
1 期間  90
2 人数  21
3
4 氏名  回数
5 A   23
6 B   23
7 C   19
8 D   16
9 E   12
10 F   9
11 G   8
12 H   7
13 I   7
14 J   6
15 K   6
16 L   6
17 M   5
18 N   5
19 O   4
20 P   4
21 Q   4
22 R   4
23 S   4
24 T   4
25 U   4


Sub 当番割当()
Dim 期間 As Integer
Dim 人数 As Integer
Dim 氏名() As String
Dim 回数() As Integer

Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim m As Integer
Dim n As Integer
Dim n1 As Integer
Dim n2 As Integer
Dim p As Single
Dim q As Single
Dim 当番() As String
Dim 担当() As Single

期間 = Cells(1, 2)
人数 = Cells(2, 2)
ReDim 氏名(人数)
ReDim 回数(人数)
For i = 1 To 人数
氏名(i) = Cells(4 + i, 1)
回数(i) = Cells(4 + i, 2)
Next i

ReDim 当番(期間 * 2)
ReDim 担当(期間 * 2)

n = 0
For i = 1 To 人数
n1 = 0
n2 = 0
For j = 1 To 人数
If 回数(j) = 回数(i) Then
n1 = n1 + 1
If j <= i Then n2 = n2 + 1
End If
Next j

p = 期間 / 回数(i)
For j = 1 To 回数(i)
q = p * (n2 - 0.5) / n1 + p * (j - 1)
m = 1
For k = n To 1 Step -1
If 担当(k) <= q Then
m = k + 1
Exit For
End If
当番(k + 1) = 当番(k)
担当(k + 1) = 担当(k)
Next k
当番(m) = 氏名(i)
担当(m) = q
n = n + 1
Next j
Next i

Range("E:G").Clear
For n = 1 To 期間
Cells(n, 5) = n & "日"
Cells(n, 6) = 当番(n * 2 - 1)
Cells(n, 7) = 当番(n * 2)
Next n
End Sub

A 回答 (7件)

理解できている部分まで説明しても冗長になるだけですし、どの部分が理解出来ないのか記載したほうがいいんじゃないですか

    • good
    • 0

こんばんは。



ご質問にて全文が掲載されておりますので、
わからない部分を補足にお願いします。
全部説明するのは大変なので・・・。

この回答への補足

氏名(i) = Cells(4 + i, 1) ここは行、列の(4,1)ですが、+i とは?
回数(i) = Cells(4 + i, 2)
Next i

ReDim 当番(期間 * 2)   ここはそれぞれ、人数*2、日*2ですね。
ReDim 担当(期間 * 2)

n = 0
For i = 1 To 人数
n1 = 0
n2 = 0
For j = 1 To 人数
If 回数(j) = 回数(i) Then    
n1 = n1 + 1     
If j <= i Then n2 = n2 + 1  ← ここです。
End If
Next j

p = 期間 / 回数(i)
For j = 1 To 回数(i)
q = p * (n2 - 0.5) / n1 + p * (j - 1)   ← -0.5 とは?ここからです。
m = 1
For k = n To 1 Step -1    ここは戻る意味ですか?  この辺りが理解できません。
If 担当(k) <= q Then
m = k + 1            2になれば戻る?
Exit For
End If
当番(k + 1) = 当番(k)
担当(k + 1) = 担当(k)
Next k
当番(m) = 氏名(i)
担当(m) = q
n = n + 1
Next j
Next i

j~qまでの変数がおぼろげにしか理解できていません。これは「これを指している!」と理解したいのです。
時間をかけて初めから、勉強するつもりなのですが、この回答いただいた、VBAだけは
確実に理解したいと思っています。
自分のレベル以上のものに取り組んでしまっていますが、
どうか、説明よろしくお願いします。
そしてこれが、VBAへの入り口になればと思っています。

補足日時:2010/08/07 20:23
    • good
    • 0

全部みるのは時間かかるので、一部だけ回答します。



この前の続きと思いますが、
わからない理由のひとつにデバッグのやり方を知らないってことはありますか。

回答を待つ間に、
VBAにおけるデバッグのコツとして、
ステップ実行(1行ずつ実行させる)のやり方、
「Debug.Print n2」や「Msgbox("n2=" & n2)」とか記載して
処理途中の変数の内容を検証するやり方、
この2つくらいはマスターしておくと良いです。
基本的なロジックは変えないで、
わざと内容を明示させる動きに変えてやる方法です。
(内容確認できたら元の状態に戻すことも忘れずに。)

あと、何がどうなっているかわからないときは
ごく単純な値、基本的な動きで試してみるという手段もあります。
B5からB25までいろんな値になってますが
全部1や全部2にしてみたらどうか?など。
こういうことから動き、内容のヒントになることあります。
B5からB25まで合計するとセル21個分、計180、90×2になってますね。


-----------------------------

大きくn1とn2を求めるまでの処理と
求められてからの処理を分けて検証したらよさそうです。


>Cells(4 + i, 2)
セル上から4+i行目と左から2番目を指しています。B5,B6,B7・・・・・


>人数 = Cells(2, 2)
>For i = 1 To 人数
より、
人数はB2の「21」の意、
この「21」はB5からB25、(A~U)を指しているようです。


>For i = 1 To 人数
>n1 = 0
>n2 = 0
>For j = 1 To 人数

この同じような仕組みが2つ並んでいるところが
理解をややこしくしていると思われます。
i = 1に対してj = 1から21まで21回数処理、
i = 2に対してもj = 1から21まで21回数処理、
i = 3に対してもj = 1から21まで21回数処理、
・・・・・・
i = 21になるまで繰り返し。


>p = 期間 / 回数(i)
まずはこの行直前までの仕組みを考えてみる。

この時点の結果で求められているはn1とn2、何が設定される??。
n1とn2で値が同じとき、違うときはどういう条件の場合か。



>For k = n To 1 Step -1
nから1、つまりはn、nの-1の値、nの-2の値、・・・・2、1の順に処理されます。

変数をわかりやすい日本語名前に変えてみるのも良いです。

この回答への補足

デバッグのやり方、2つとも知らないです。本にはF8で一行づつ実行できるとありますが、できませんでした。詳しくは記述してないのかもしれません。
処理途中の内容を検証するやり方も載ってないです。

何度も申し訳ありませんが、
ぜひ、教えてください。
私の周りには、VBAに詳しい人がいないため本か、このような質問に頼るしかないのです。
よろしくおねがいします。

補足日時:2010/08/08 00:39
    • good
    • 0

このソースの見難い点は殆どの変数が一文字であると言う点がありますね


変数はその内容を表す文字列であらわしたほうが理解するのに楽です。
(自分のソースを後から自分が見たときにもです)

これから勉強されるのでしたら変数の使い方は真似しないほうがいいでしょう。
    • good
    • 0

参考に。



「VBA」「ステップ実行」 「デバッグ」「やり方」などいろいろ
検索してみるとこういうところがありました。参考。
http://shadowslasheizan.blog114.fc2.com/blog-ent …

1行ずつ実行っていうのは、
コードが表示されている状態で、
一時的に止めたい行を選んでF9を押下し止まる行を確定、もう一回F9で解除、
(複数行で止めること可能)

例えば、
「期間 = Cells(1, 2)」と「p = 期間 / 回数(i)」の2行に対して
選んでF9を押す。
あとは、F8を押す毎に1行ずつ進みます。
途中で
イミディエイトウィンドウ使ったり、
「n1」にマウスを近づけても内容が表示されたりします。

今までと同じように何もしないで一気に実行したい場合はF5。

----------------

こうやって他の人に見てもらうこともあるわけですから、
誰が見ても何やってるかわかりやすい、
実行させなくてもおおよそ何がどうなるか想像がつく、
こういうのを目指すのが良いと思います。
プログラムの構造は教えてもらったものだからあまり変えたくないとしても
今後のために、
変数名変えたりコメント追記したりしておくのも良いです。
(コメントばかりというのも見にくいですが。)
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
とても役立つことなので、感謝しています。
ありがとうございました。

お礼日時:2010/08/08 18:40

別のところでも書きましたが、わたしもこのコードの内容には強く関心を持ちましたので、内容について知りたいと思っていました。



今回のご質問へのアドバイスとしては、

(1)あなたがVBAに関してどの程度の知識があるのかによって、回答者もどの程度の説明をすべきかが分からないので、それをはっきりさせたほうがよいです。

(2)全文のコードを記したとしても、その前提となっている話が見えなければ、回答者も推測が困難である。
質問番号 「6068226」 の回答1番の「回答への補足」と、回答4番 を参照していただきたい旨を明記したほうがよいです。

(3)当質問の2番の「回答への補足」冒頭「+iとは?」という内容からも、VBAに関してはほとんど知識をお持ちでないことが推測されますので、今回のコードはかなり複雑なロジックで組まれているようなので、練習用にするにはもっと簡単な素材のほうがよいと思います。

(4)他回答にも出ていますが、デバッグやステップ実行などを通じて、変数の動きをご自身で追ってみる、これもとても大切です。
#3、#5さんが書かれているような方法です。
これは今回のコードの解読以前に学習しておくべきではないかと思います。

また、このコードにご自身で書き加えて、変数の動きを記録してみるのも手ですが、そこまではまだ思いつかれないかもしれません。

例えば、最初のFor i=1 to 人数 Next i のループ。

「Next i」の前の行に、
Worksheets(2).Cells(Rows.Count,1).End(xlUp).Offset(1).Value=i
Worksheets(2).Cells(Rows.Count,2).End(xlUp).Offset(1).Value=氏名(i)
Worksheets(2).Cells(Rows.Count,3).End(xlUp).Offset(1).Value=回数(i)

というのを書き加えてみるとか。
(次のシートに動きを記録させています。意味が分からないならば、分かるようにしてからお使いいただくのが肝要です。)


そのうえで、このコードについて私が解釈した部分までを記します。

Sub 当番割当

Dim で各種変数の宣言
氏名()、回数()、当番()、担当()は、配列として宣言している

変数「期間」にB1セルの90(日)をセット
変数「人数」にB2セルの21(人)をセット

変数「氏名()」を、要素数「人数(=21)」として再宣言
変数「回数()」を、要素数「人数(=21)」として再宣言

 こういうことをしている理由は以下を読まれると良いでしょう。
 http://pc.nikkeibp.co.jp/article/NPC/20070803/27 …

 http://pc.nikkeibp.co.jp/article/NPC/20070802/27 …
 ここの(6)、(7)に目を通してみましょう。

最初のFor i=1 to 人数 のループでは、変数「氏名(i)」、「回数(i)」に、シートのA5からB25のデータをセットしています。
i の意味といっても、単なるカウンタですので意味はありません。

ただ、ここの場合、i=1 to 21 ですから、AさんからUさんの処理をしていることはお分かりになると思います。
最初のAさんのデータを、i=1 で処理しています。Aさんのデータは5行目に入っています。
だから、(4+i,1) なのです。
どういう処理がなされているかを、i の数を変化させながら考えてみてください。たぶんここはすんなり行けると思います。

次に、当番()を 要素数 180として再宣言。
担当()を、要素数 180として再宣言。

これは90日で、各日ふたり担当である、決定すべき当番が 180コマあることから、そのように宣言しています。

あとはこのあとの i=1 to 21 のループです。ここがキモでしょう。
ループの中にループが入っている場合の動作については、ご理解されていますか?
ご理解されているとして、

i=1 の時に、その中のj=1 to 21 のループがあります。
i=1 の時の、このループが終わった時、n1=2、n2=1
i=2 の時の、このループが終わった時、n1=2、n2=2
・・・
i=20 の時の、このループが終わった時、n1=7、n2=6
i=21 の時の、このループが終わった時、n1=7、n2=7

n1 は、その回数(Aさんなら23回)の人が何人いるかを示していると思われます。
n2 は、その回数と同じ人が何人か居た場合、その中での何番目かを示していると思われます。

長文すみません続きます。
    • good
    • 0

#6 です。

冗長ですみません。

pはそれぞれの人の適性間隔ですね。Aさんなら、90日÷23回

その次のFor j=1 to 回数(i) のループです。ここがちょっと私も難解でよく理解できませんでした。

まず、i=1(Aさんのとき)には、回数(i)=23ですから、ここのループは、
For j=1 to 23 になります。ですから、Aさんの23回分について処理していることが分かります。
ここでも j はカウンタですから特に意味はありません。

q の前半、 p*(n2-0.5)/n1
でその人の1回目の日時を出しているように思いますが、なぜこの式で算出しているかは私は分かりません。

q の後半、 +p*(j-1) は、初回の日時に適性間隔を足していますので、2回目以降の日時を出しているようです。j=1 ならば、この項はゼロですから。

その中の For k=n to 1 Step -1 のループは私もちょっと分からず、いろいろいま調べています。
n はどんどん増えていきますし、最終的にはn=180 に行くような気がします。

となると、k は、1づつ減少のカウンタになってるようなので、それぞれの人に対して、一番後ろの回から決定してるのではないかと思いましたが、まだ動作検証の途中のため分かりません。
詳しい方のご回答をお待ちください。


最後のFor n=1 to 90 のループは結果を転記するためのものですから、これはいいでしょう。
動きが分からないようでしたら、n=1、2、と当てはめてどうなるか、考えてみましょう。


中途半端な回答で申し訳ありません。
あなたと同様に、このコードでわたしも勉強させていただいております。有難うございます。
    • good
    • 0
この回答へのお礼

何度も助言していただいて、ありがとうございます。

私のレベルは、エクセルは中級、VBAは、今回初めて試みています。
最初にVBAでできないものかと、気軽な気持ちで質問したのですが、回答いただいた内容が全く理解できなかったため、慌ててすぐに書籍を買って内容を解読にかかった次第です。
当然、細切れに意味はわかっても、それだけの状態ですので、詳しい説明を聞くと大筋が理解できるかもしれないと、躍起になっていたのです。

 知識のないまま次々と、手をつけていき、たくさんの回答をいただいて、今、頭のなかを整理しないといけないような状態です。
 たくさんの回答者様にも、なかなかお礼も送れてません。
 自分のレベルに合わない質問をして、反省しています。が、これから、時間をかけて、
ひとつづつ、消化していこうと思っています。

 何度も、何度も、説明感謝しています。
ありがとうございます。<(_ _)>

お礼日時:2010/08/08 18:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!