[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『10桁のランダムな数字をそれまでに発生していない数字で、』(MSCL)
ある列のセルに10桁の乱数を発生させていきたいのですが、セル範囲を選んでその範囲のセルに重複しない数字を埋めるというのではなく、最初は、何も埋まっていない状態から、都度重複しない数字を発生させていくには、どうしたらよいでしょうか…
完全にくれくれに近い質問で申し訳ありません。
例えば、今、『採番』のボタンを押すと、A1のセルだけに10桁のランダムな数字を発生させます。
次に、『採番』のボタンを押すと、A2のセルにランダムな10桁の数字を発生させますが、A1と重複しないようにしたい、
さらに次、『採番』を押すと、A3には、A1,A2のどちらとも重複しない10桁のランダムな数字を発生、
…『採番』を押すと、A4に、A1,A2,A3のいずれとも重複しない10桁のランダムな数字を発生させたい…
…A5に、A1,A2,A3,A4のいずれとも重複しない10桁のランダムな数字を発生させたい…
(列は、1列だけで構いません。)
ということをひたすら繰り返すということなのですが、可能でしょうか。
要するに『採番』できるVBAです。よろしくお願いします。
< 使用 Excel:Excel2010、使用 OS:Windows7 >
(隠居じーさん) 2019/05/22(水) 12:15
そして、どうしても乱数にしたいならば、重複しても良いから乱数を発生させてみて、それが過去の数値と重複していないか調べて、重複していたらやり直しループするようなロジックで十分ではないでしょうか。 10桁もあるなら、そうそう重複はしないでしょうし。
(???) 2019/05/22(水) 13:14
乱数を生成した後でその数を検索して、
見つかれば(重複があれば)ループする、
というロジックになりますね。
'フォームコントロールのボタンのマクロ Sub 採番_Click() Dim tarCell As Range If Cells(1, 1) = "" Then Set tarCell = Cells(1, 1) Else Set tarCell = Cells(Rows.Count, 1).End(xlUp).Offset(1) End If
Randomize
Dim minNum As Double, maxNum As Double minNum = 1000000000# maxNum = 9999999999#
Dim Num As Double Do Num = Int((maxNum - minNum + 1) * Rnd + minNum) If Range(Cells(1, 1), tarCell).Find(Num, LookAt:=xlWhole) Is Nothing Then tarCell.Value = Num Exit Do End If Loop End Sub
(hatena) 2019/05/22(水) 13:25
Private Sub CommandButton1_Click() Dim iw As Double Dim iNum As Long
Randomize iNum = 1
While 0 < iNum iw = WorksheetFunction.RandBetween(1000000000#, 9999999999#) iNum = WorksheetFunction.CountIf(Range("A:A"), iw) DoEvents Wend Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Value = iw End Sub (???) 2019/05/22(水) 13:38
いや〜様々な方法があるのですね〜配列がオーバーフローするので どうかな〜とか悩んでいました。Int、が使えるか心配でしたが何とか?
Sub OneInstance() Dim RdNum As Currency Dim D As Object Randomize Set D = CreateObject("Scripting.Dictionary") Do Until D.Count > 9 '乱数=Int((最大値 - 最小値 +1 ) * Rnd + 最小値) RdNum = Int((9999999999# - 1000000000 + 1) * Rnd + 1000000000) If Not D.Exists(RdNum) Then D.Add RdNum, RdNum End If Loop MsgBox Join(D.keys, ",") End Sub (隠居じーさん) 2019/05/22(水) 14:07
あれ、RandBetween でもいけましたよ?
あら、普通にいけますね。
よく見たら、RndBetween となってるわ。タイプミスでした(汗)。
(hatena) 2019/05/22(水) 15:46
数値ということで、せっかくご回答頂きましたが、文字列にする必要が出てきて、
でも、数値は数値で、とても勉強になりました。
先頭にアルファベット、途中にハイフォンを付加して…
主に、hatenaさんのコードを利用させて頂き、最終的には、下のような形になりました。
序盤の部分もどなたかのを利用させて頂いてます…自分では、ほとんど理解できておらず…
VBA初心者なのでおかしなところがあるかも知れません…致命的なことがあればご指導ください。
ありがとうございました。
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
Option Explicit
Private Const ALP As String = "A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z"
Private Const bNUM As String = "0,1,2,3,4,5,6,7,8,9"
Public Function GetRndStr()
Dim aryALP() As String Dim aryNUM() As String aryALP = Split(ALP, ",") aryNUM = Split(bNUM, ",") GetRndStr = aryALP(getRnd(0, 23)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) End Function
Private Function getRnd(ByVal lowerbound As Integer, ByVal upperbound As Integer)
getRnd = Int((upperbound - lowerbound + 1) * Rnd + lowerbound) End Function
Sub 採番します_Click()
Dim tarCell As Range If Cells(6, 3) = "" Then Set tarCell = Cells(6, 3) Else Set tarCell = Cells(Rows.Count, 3).End(xlUp).Offset(1) End If
Randomize
Dim aryALP() As String Dim aryNUM() As String
aryALP = Split(ALP, ",") aryNUM = Split(bNUM, ",")
Dim NUM As String Do NUM = aryALP(getRnd(0, 23)) & "-" & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & "-" & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) & aryNUM(getRnd(0, 9)) If Range(Cells(6, 3), tarCell).Find(NUM, LookAt:=xlWhole) Is Nothing Then tarCell.Value = NUM Exit Do End If Loop End Sub
(MSCL) 2019/05/22(水) 17:44
Sub test() Const ALP = "ABCDEFGHJKLMNPQRSTUVWXYZ" Dim tarCell As Range Dim cw As String Dim iNum As Long
If Cells(6, 3) = "" Then Set tarCell = Cells(6, 3) Else Set tarCell = Cells(Rows.Count, 3).End(xlUp).Offset(1) End If
iNum = 1
While 0 < iNum cw = Mid(ALP, WorksheetFunction.RandBetween(1, Len(ALP)), 1) & _ "-" & Format(WorksheetFunction.RandBetween(0, 99999), "00000") & _ "-" & Format(WorksheetFunction.RandBetween(0, 99999), "00000") iNum = WorksheetFunction.CountIf(Range("A:A"), cw) Wend
tarCell.Value = cw End Sub (???) 2019/05/22(水) 18:07
iNum = 1
While 0 < iNum
が相変わらず理解できてませんが(苦笑)。
Rangeは『"C:C"』ですかね…
たびたび、ありがとうございます。利用させていただきます。
(MSCL) 2019/05/22(水) 18:24
Option Explicit '------------------------ Public Function GetRndStr() Const ALP As String = "ABCDEFGHJKLMNPQRSTUVWXYZ" GetRndStr = Mid(ALP, getRnd(1, Len(ALP)), 1) & Format(getRnd(0@, 9999999999@), "-00000-00000") End Function '------------------------ Private Function getRnd(ByVal lowerbound As Currency, ByVal upperbound As Currency) As Currency getRnd = Int((upperbound - lowerbound + 1) * Rnd + lowerbound) End Function '------------------------ Sub 採番します_Click() Dim tarCell As Range If Cells(6, 3) = "" Then Set tarCell = Cells(6, 3) Else Set tarCell = Cells(Rows.Count, 3).End(xlUp).Offset(1) End If Randomize Dim RndStr As String
Do RndStr = GetRndStr() If Range(Cells(6, 3), tarCell).Find(RndStr, LookAt:=xlWhole) Is Nothing Then tarCell.Value = RndStr Exit Do End If Loop End Sub
(hatena) 2019/05/22(水) 20:00
while文を使っているのは、生成した文字列が既に何個あるか(あっても1つですが)をチェックし、0個だったら採用、というロジックだからです。 そして、ループ前に1にしているのは、整数型変数のデフォルト値は0のため、初回は文字列を作る前に終わってしまうからです。 初期値を0以外にすることで、必ず1回は文字列生成させている訳ですね。
重複判定は、普通に考えると、今までに生成した文字列全てと一致するかForループ等で順次比較するのですが、インタプリンタでループするより、Excelの内部機能で文字列を探す方が簡単で速いです。(Findだと文字列検索1回ですし、CountIfだと何件一致するかカウント1回です)
隠居じーさんさんのロジックは、辞書化することで、ループして比較する時間を無くしています。 ただし、辞書を作る時間がかかってしまうので、速度的には不利ですね。
MSCLさんのロジックの場合、GetRndStrからgetRndを呼んでいますが、これをGetRndStrとGetRndNumのように、文字列と数字の2つの関数に分けて、更に桁数を引数とすれば、汎用的になって判りやすくなります。 更に進めると、GetRndを1つだけ用意し、選択肢の文字列と桁数の2つを引数にすれば、共通関数1つで済みますね。 以下のように使いますが、これなら判りやすいと思いますよ。
cw = GetRnd(ALP, 1) & "-" & GetRnd(NUM, 5) & "-" & GetRnd(NUM, 5) (???) 2019/05/23(木) 09:37
今回もまた、たくさん勉強させて頂きました。
私は、まだまだ勉強しなきゃ…ですね…。ありがとうございました。
(MSCL) 2019/05/23(木) 10:27
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.