プロが教えるわが家の防犯対策術!

21名で二人づつのペアでの畑の水入れ当番を作りたいと思います。21名がそれぞれの所有面積に応じて当番の当たる間隔日数を出しています。期間は考えずにローテーションによって回る当番です。所有面積の多い人で最小間隔日数が(7.74)日一名です。続いて(7.87)一名(9.1)一名(11.5)一名(14.97)一名(19.34)一名(22.1)一名(24.43)一名(25.78)一名(30.94)三名(38.67)二名(46.4)七名です。このそれぞれの間隔日数をあまり崩さないように当番を組んでいきたいのですが、二名ペアだということだとか、とても複雑でできそうにありません。
手書きで作ったりもしてみたのですが、できればエクセルで関数、を使って(マクロ)作りたいと思っています。一度詳しい方に質問したのですが、間隔日数が変動してしまい(その時は期間をきめていたので・・・)この案がメンバーに受け入れてもらえず、再びお知恵をお借りしたく質問させていただいています。私のPCレベルは中級ですが、マクロに関してはほとんど知識がないので、解読文章(わかりやすく)つきで、回答いただきたいと思います。
こんなの簡単だ!!と思われる方は是非回答よろしくおねがいします。

氏名  面積      間隔日数    比較順位
Aさん  60      7.74        1
Bさん  59      7.87        2
Cさん  51      9.1         3
Dさん  42      11.05       4
E     31      14.97      5
F     24      19.34       6
G     21      22.1        7
H     19      24.43       8
I      18      25.78       9
J      15      30.94      10
K      15      30.94      10
L      15      30.94      10
M      12      38.67      11
N      12      38.67      11
O      10      46.4       12
P      10      46.4       12
Q      10      46.4       12
R      10      46.4       12
S      10      46.4       12
P      10      46.4       12
U      10      46.4       12
面積  合計464  

このような感じです。困っています。間隔日数をある程度保ちながらできるだけ公平に組み合わせたいのです。
よろしくおねがいします。

A 回答 (4件)

>エクセルのシートに氏名を表記したいのです。



下記のようにA列とB列に必要な情報を入力してから、VBAを実行してください。
E,F,G列に結果が表示されます。

  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


VBAをここで詳しく解説することはできないので、ご自分で調べてみてください。
簡単なコマンドだけですので、そんなに難しくないと思います。


難しいのは、なぜこの方法で当番の割り当てができるのかだと思いますので、簡単に説明しておきます。

期間は90日ですが、この時間軸上に各担当者ごとに当番日時を均等に振り分けます。
例えば、Aさんは23回なので、90/23=3.91=3日22時間を計算して、
Aさんの1回目:3日22時
Aさんの2回目:7日20時
Aさんの3回目:11日18時
Cさんは19回なので、90/19=4.73=4日17時間を計算して、
Cさんの1回目:4日17時
Cさんの2回目:9日10時
Cさんの3回目:14日3時
というように配分します。
(実際はもう少し細かい計算をしていますが簡単に言うとこういうことです)
21名全員について同じように配分します。
しかしこのままでは、当番がいない日があったり、3人以上が当番になる日が発生しますので、
あとは、早い順に2名づつ当番に割り当てているだけです。

この方法で割り当てると、当番の間隔日数はそんなにずれることはないと思います。
    • good
    • 0
この回答へのお礼

ありがとうございます!
そうなんです。どのようにして当番割り当てを作成したかがしりたかったのです。
私には、アイデアが浮かばなかったので、どのようにしてしたかの見当もつかなかったのです。
説明していだだいて理解できました。あとは、実際に作ってみます。時間がかかるとおもいますが、
コマンドの意味していることも、調べようと思います。手元にある本にはそれらしきコマンドがみつからないので、早速探してみます。
アイデアがひらめくようには、なれないですけど、手順だけでも少しは理解できるようなりたいですから。
 ほんとうにありがとうございました。これを機会に進歩していきます。

お礼日時:2010/07/29 20:37

VBAで作成してみましたので試してみてください。


計算結果をシートに転送していますので、シートモジュールで実行してください。

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

期間 = 90
人数 = 21
ReDim 氏名(人数)
ReDim 回数(人数)
氏名(1) = "A": 回数(1) = 23
氏名(2) = "B": 回数(2) = 23
氏名(3) = "C": 回数(3) = 19 ' 回数の合計が181になっていたので20を19に変更しました
氏名(4) = "D": 回数(4) = 16
氏名(5) = "E": 回数(5) = 12
氏名(6) = "F": 回数(6) = 9
氏名(7) = "G": 回数(7) = 8
氏名(8) = "H": 回数(8) = 7
氏名(9) = "I": 回数(9) = 7
氏名(10) = "J": 回数(10) = 6
氏名(11) = "K": 回数(11) = 6
氏名(12) = "L": 回数(12) = 6
氏名(13) = "M": 回数(13) = 5
氏名(14) = "N": 回数(14) = 5
氏名(15) = "O": 回数(15) = 4
氏名(16) = "P": 回数(16) = 4
氏名(17) = "Q": 回数(17) = 4
氏名(18) = "R": 回数(18) = 4
氏名(19) = "S": 回数(19) = 4
氏名(20) = "T": 回数(20) = 4
氏名(21) = "U": 回数(21) = 4

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

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

For n = 1 To 期間
Cells(n, 1) = n & "日"
Cells(n, 2) = 当番(n * 2 - 1)
Cells(n, 3) = 当番(n * 2)
Next n
End Sub

この回答への補足

ありがとうございます。
私のレベルが低いので、できればこのマクロを一行づつ解説をいただきたいのですが、とても面倒だとは思いますが、わたしも、ぜひ理解したいと思います。
サンプルではA,B,さんとしてありますが、これを氏名にかきなおすとしたら、どうすればいいのでしょうか?エクセルのシートに氏名を表記したいのです。マクロ自体さわったことがないので、張り付けることもようやくでした。エクセルのシートのシート1にだけ表ができていますが、それでただしいのでしょうか?nag0720さんが想像している以上に四苦八苦しています。
一文字づつ、本をみながら、理解しようとしたのですが、できません。
どうか、解説(簡単に説明)よろしくお願いします。
本当に、もうしわけないです。

補足日時:2010/07/28 18:19
    • good
    • 0

最小間隔日数の代わりに担当割合を使用する案です。


詳しくは添付図をご覧ください。

W2=SUM(B2:V2)
B3=B2/$W$2
B6=B$3
B7=B$3-COUNTIF($W$6:$W6,B$1)/$A6
W6=INDEX($B$1:$V$1,MATCH(MAX($B6:$V6),$B6:$V6,FALSE))

3行目でそれぞれの面積/全面積を計算、担当割合とします。
6行目以降の考え方としては、
・3行目の担当割合から、これまでの実際の担当割合(担当回数/全回数)を引く(B列~V列)
・上記の値が最も大きい(予定の担当割合への到達率が最も低い)人を担当とする(W列)
これを繰り返します。

464回分を計算した結果では、担当割合、間隔日数ともにそこそこ良い結果がえられました。

図が読みにくい等あれば補足ください。
「21名で二人づつのペアでの畑の水入れ当番」の回答画像2

この回答への補足

早速作成しました。時間がかかりましたが、できました。ありがとうございます。
関数だけでもできるのですね。申し訳ありませんが、関数只今勉強中の身なので、ごく簡単にこの関数の説明をしていただけたらうれしいです。よろしくお願いします。

補足日時:2010/07/28 20:11
    • good
    • 0
この回答へのお礼

 ありがとうございました。実際に作成してみて理解できました。
最初、同じ割合の人がたくさんいるのにどうして、順位がつけられるのかと、わからなかったのですが・・・
表とにらめっこして、考えた結果こういうことだろう・・わかりました。
とても勉強になりました。
本当にありがとうございました。

お礼日時:2010/07/29 20:46

疑問が1つ。



464日間を1周期とすると、その期間内に、Aさんは60回、Bさんは59回、・・・、Uさんは10回水入れ当番になるということですね。
そうすると、延べ回数は464回になります。
464日間で464回ですから、ペアで当番になるとすると、毎日ではなくて1日置きに水入れをすることになりますがそれでいいんでしょうか。

この回答への補足

そうですね。期間を考えないとそうなりますね。頭わるくてすみません。
以前は3カ月間に設定していたのですが・・・(30日*3*2)ペアなので180日というふうに・・
期間中のそれぞれの割り当て日数をだして、振り分けます。
Aさんから順番に
A 23回
B 23回
C 20
D 16
E 12
F 9
G 8
H 7
I  7
J 6
K 6
L 6
M 5
N 5
O 4
P 4
Q 4
R 4
S 4
T 4
U 4回とします。
期間中の個人の割り当て日数はできればまもって、間隔日数は少々は違ってもだいだい同じ間隔で当番があたるのであれば充分です。
二人ペアになることで、一人の人が決まった間隔日数よりも短い日数であたるのはできればさけたいのですが。でもそれも1~3日位であればいいと思います。ただし、もともと間隔日数の短いひとは
短くならないほうが、望ましいですね。
私は、口でいうのは簡単ですが、エクセルの関数を使ってつくるのはできません。
できるだけ簡単な関数で、よろしくお願いします。これができると、この当番表はこの先ずっと使われていくものです。よろしくお願いします。
PS・・これって田んぼの面積が増減したりしても後から私でも簡単に操作して調整できるものにできたりしたらいいのですが・・・
どうか、どうか、よろしくお願いします。気になってこんな時間に目がさめました。

補足日時:2010/07/28 04:11
    • good
    • 0

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