ここから本文です

乱数を使ったシフト表がうまく動きません。 図のような、6日×5週分のシフト表を...

オリオンさん

2019/9/2002:26:02

乱数を使ったシフト表がうまく動きません。
図のような、6日×5週分のシフト表を作っています。
B列とAJ列の合計が合致して、
19行目で1を入れている日には、1人ずつ入れたいのです。

AJ28で最大値を表示するようにしており、これが1になって、
前述のB列とAJ列の合計が合致したらループを抜けて処理終了としました。

コードを書いてみたのですが、
最初に発生する乱数の合計が大きすぎて、なかなか収束しません。
どのようにコードを修正したらよいかご教示願いたいです。
----------------------------------------------------------

Sub shuffle() '6日×5週分のシフトをランダムで生成

Randomize
Do

For cls = 22 To 27 '名前’21行目は手動選択

Do
For col = 6 To 35 '列

If Cells(19, col) = 0 Then Cells(cls, col) = 0
If Cells(19, col) = 1 Then Cells(cls, col) = Int(Rnd() * 2) '0か1の乱数を発生させる

If Cells(cls, 2) = Cells(cls, 36) And Cells(28, 36) = 1 Then Exit Do

Next col

Loop Until cls < 28 '★

Next

If Cells(cls, 2) = Cells(cls, 36) And Cells(28, 36) = 1 Then Exit Do '★


Loop

End Sub

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

If Cells,1 Then Exit Do,And Cells,Loop Until cls,0 Then Cells,End If,割当日

閲覧数:
79
回答数:
2
お礼:
100枚

違反報告

ベストアンサーに選ばれた回答

auq********さん

編集あり2019/9/2019:34:21

ご質問の場合、全てランダムに決めようとする事に無理があります。

●ある人のシフトに1が入った瞬間に、その日の他の人のシフトは0に決まる。

●ある人のシフトに1が3回入った時点で、その人の他の日のシフトは0に決まる。

●ある人のシフトには必ず1が3回なければならない。

この3つの条件を組み込まないとご希望のシフトは完成しません。



Sub shuffle() '6日×5週分のシフトをランダムで生成

Range("F22:AI27").ClearContents

Dim i As Long
Dim j As Long

Randomize

For j = 6 To 35
If Cells(19, j) = 0 Then
Cells(21, j).Resize(7) = 0
End If
If Cells(21, j) = 1 Then
Cells(22, j).Resize(6) = 0
End If
Next j
For i = 21 To 27
For j = 6 To 35
If Cells(i, j) = ""Then
If WorksheetFunction.CountBlank(Range(Cells(i, 6), Cells(i, 35))) + WorksheetFunction.CountIf(Range(Cells(i, 6), Cells(i, 35)), 1) = Cells(i, 2) Then
Cells(i, j) = 1
ElseIf Cells(i, 2) <>Cells(i, 36) And WorksheetFunction.CountBlank(Range(Cells(i, 6), Cells(i, 35))) + WorksheetFunction.CountIf(Range(Cells(i, 6), Cells(i, 35)), 1) >Cells(i, 2) Then
Cells(i, j) = Int(Rnd() * 2)
Else
Cells(i, j) = 0
End If

If Cells(i, j) = 1 Then
If i <27 Then
Range(Cells(i + 1, j), Cells(27, j)) = 0
End If
End If

End If
Next j
Next i
End Sub



最後に、この方法はシフト表の1行目から右方向にランダムに1か0を決めて、0や1が確定した所はランダムではなく0や1を確定させています。

何回も試してみると分かると思いますが、左上の方がランダムに決まりやすく、右下に行くほど1が偏りやすくなります。

完全にランダムにするには、「1か0か」をランダムにするのではなく、「シフト表のマスに1を埋めて行く順番」をランダムにしなければなりません。

  • 質問者

    オリオンさん

    2019/9/2021:54:09

    早速のお答えありがとうございます。

    サクサク動きました。感謝です。

    自分としてはresizeの使い方が今一つ分かりません。

    このコードを見て、具体例として勉強します。

    本当にありがとうございました。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

質問した人からのコメント

2019/9/20 21:55:35

ご教示ありがとうございました。

勉強させていただきます。

ベストアンサー以外の回答

1〜1件/1件中

qas********さん

2019/9/2019:39:56

具体的なコードはお任せしますが、必要な日をランダムにソートして、頭から順に人を割り付けるだけです。

例えば、必要な日が
2, 3, 5, 7, 11
で、希望日数が
Aさん:3日
Bさん:2日
であったとします。
2, 3, 5, 7, 11
をランダムにソートして、
5, 3, 11, 2, 7
が得られたら、始めの三つの数字をAさんの割当日、次の二つをBさんの割当日、すなわち、
Aさん:3, 5, 11
Bさん:2, 7
とするということです。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる