プロが教える店舗&オフィスのセキュリティ対策術

VBAで書いたコードの間違いをご指摘頂きたいです!

セルB1~K54までに1000~9999までの整数の乱数を表示させたく、HPを参考にコードを書いたのですが実行できません。

間違いをご指摘いただけると嬉しいです!

「VBAで書いたコードの間違いをご指摘頂き」の質問画像

質問者からの補足コメント

  • 写真を追加しました。

    「VBAで書いたコードの間違いをご指摘頂き」の補足画像1
      補足日時:2017/03/27 16:06
  • Zincerさん御丁寧にありがとうございます。
    アドバイスを受けやってみましたが、おっしゃる通りまだ工夫が必要なようで、思うようにはいきませんでした。
    tatsu99さんご親切にありがとうございます。以下がコードです。
    返信が遅れすみません。

    Sub rnsuu01()
    Dim i As Long
    Dim x()
    Dim y()
    Dim d
    Const Ld = 1000
    Const Ud = 9999
    Const Pd = 342
    ReDim x(1 To Ud - Ld + 1)
    ReDim y(1 To Ud - Ld + 1)
    ReDim d(1 To Ud - Ld + 1,1 To 1)
    Randomize

      補足日時:2017/03/27 20:10
  • 続き

    For i = 1 To Ud - Ld + 1
    x(i) = Rnd()
    y(i) = i + Ld - 1
    Next i
    For i = 1 To Ud - Ld + 1
    d(i,1)=y(Application.Match(Application.Small(x,i),x,0))
    Next i
    Worksheets("sheet2").Range("B1:K54").ClearContents
    For i = 1 To Pd
    Range("B1:K54").Value = RAND()*
    Next i
    End Sub

    よろしくお願い致します。

      補足日時:2017/03/27 20:10

A 回答 (6件)

ちょっと拝見させていただきました。



本題は、よく見ると、#4さんご指摘のように、乱数の重複を出さないという目的の元に作られたものでしょう。

ただ、ご質問者さんのコードで、つまらないことを言いますが、Lisp とかではありませんから、関数のネストはやめたほうがよいです。かなり可読性が落ちます。ネストの中で、Double型の数値を取り扱っていますから、実際にも不安を感じさせます。

今回、Int(Rnd()*(Ud-Ld+1)) + Ld  も、そのままというわけにもなかなか行かないのは、もう#4さんのコードで実証済みですね。

この他にも、Collectionを使った技法があります。今回は、前々から懸念のメルセンヌ・ツイスターを導入して使ってみました。このレベルでは特に変化があるわけではありませんが、それでも、あまり、Microsoft のPRNのRand()/Rnd() に依存していくこともできないと思います。あまりにも、過去、信用をなくしましたからね。
なお以下、不手際がありましたら、臨機応変にお願いします。

注意:シート2をお使いなら、シート2をアクティブシートにしてお使いください。
'//
Sub RandomGeneration_02()
 Dim i As Long, j As Long
 Dim m As Long, n As Long
 Dim x()
 Dim y()
 Dim d()
 Const Ld = 1000
 Const Ud = 9999
 Const Pd = 342 'これはSize違い(不要)
 Dim k As Long
 Dim a As Long
 Dim xa As Double 'Double型の不安は残る
 
 k = Ud - Ld + 1
 ReDim x(1 To k)
 ReDim y(1 To k)
 '貼付け用の変数 "B1:K54"
 ReDim d(1 To 54, 2 To 11)
 Randomize
 For i = 1 To k
  x(i) = Rnd() '*<-> genrandm() 'メルセンヌ・ツイスタ
  y(i) = i + Ld - 1
 Next i
 a = 1 'カウンター変数として
 For m = 2 To 11 'B:K
  For n = 1 To 54 '1:54
   xa = Application.Small(x(), a)
   j = Application.Match(xa, x(), 0)
   d(n, m) = y(j)
   a = a + 1
  Next
 Next
 Range("B1:K54").Value = d()
 MsgBox "Finish!"
End Sub
    • good
    • 0

No.4です。



前回のコードで間違いがありました。

>myNum = Int((9999 - 1000) * Rnd + 1000)

>myNum = Int((9999 - 1000 + 1) * Rnd + 1000)
に変更してください。

そうしないと最大の「9999」が出現しないと思います。m(_ _)m
    • good
    • 0

こんばんは!



横からお邪魔します。
重複なしに表示するようにしてみました。

Sub Sample1()
Dim c As Range, myNum As Long
Dim myFlg(1000 To 9999) As Boolean
For Each c In Range("B1:K54")
Do
myNum = Int((9999 - 1000) * Rnd + 1000)
Loop Until myFlg(myNum) = False
c = myNum
myFlg(myNum) = True
Next c
End Sub

こんな感じではどうでしょうか?m(_ _)m
    • good
    • 0

かなり余分な処理があるので書き直しました。


以下のようになります。
------------------------------------
Option Explicit
Sub rnsuu01()
Dim row, col As Long
Const Ld = 1000
Const Ud = 9999
Randomize
Worksheets("sheet2").Range("B1:K54").ClearContents
'1行~54行まで繰り返し
For row = 1 To 54
'B列~K列まで繰り返し
For col = 2 To 8
'1000~9999の乱数を発生
Worksheets("sheet2").Cells(row, col) = Int(Rnd * (Ud - Ld + 1)) + Ld
Next
Next
End Sub
-------------------------------------------------
Worksheets("sheet2").Range("B1:K54").ClearContents
はなくても構いません。(B1:K54に乱数が設定されるので)
    • good
    • 0

あなたが作成したマクロを画像ではなく、コピペして、補足として投稿して頂けますか。


投稿時、複数の空白が1つにまとめられるため、インデントがずれますが、それは気にする必要はありません。
そうすれば、私のほうで、正しく修正することができます。
画像のままでは、こちらでは修正できません。
    • good
    • 0
この回答へのお礼

tatsu99さんご親切にありがとうございます。以下がコードです。
返信が遅れすみません。

Sub rnsuu01()
Dim i As Long
Dim x()
Dim y()
Dim d
Const Ld = 1000
Const Ud = 9999
Const Pd = 342
ReDim x(1 To Ud - Ld + 1)
ReDim y(1 To Ud - Ld + 1)
ReDim d(1 To Ud - Ld + 1,1 To 1)
Randomize

お礼日時:2017/03/27 20:12

Range("B1:K54")


は領域を示しています。
そこにd(i,1)に格納されている値を代入しようとするからエラーが発生しています。
表示するセルを、1個の値に付き1つに設定しないといけません。
例:B列に順に表示するなら、
cells(i,2)=d(i,1)
等に変更してみてください。
※「B1」から「K54」のように行や列を途中で変更したければ、もう一工夫必要です。
尚、乱数の発生アルゴリズムはチェックしていません。
    • good
    • 0

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