View Single Post
  #13   Report Post  
Posted to microsoft.public.excel.worksheet.functions
Leo Heuser Leo Heuser is offline
external usenet poster
 
Posts: 266
Default Non updatable Unique Random Number

"Max" skrev i en meddelelse
...

Great sub, Leo !

Is there a simple way to bring over to Excel screen via say, an inputbox,
so
that we can define the clickable ranges and the numeric limits below in
Excel
itself ?



Thanks Max!

Here's ver.2 with more options.

The Rand data is now set up in a named table in the proper worksheet(s).
The random numbers are still fetched by doubleclicking a cell, but you now
have a choice of filling one cell or all cells.

The name must be "RandTable" (without quotes) and it must be local, so
in sheet1 the name is sheet1!RandTable, in sheet2 the name is
sheet2!RandTable etc.

For example my named range is H2:L12 (H1:L1 contains headings).

Not all rows in the range need to be filled, but blank rows must not exist
between filled rows. H2:L6 could contain definitions with empty cells in
H7:L12, which is OK.
H2:L6 and H9:L9 containing definitions and H7:L8 being empty is
not allowed.

The table has 5 columns with these headings:
Column 1: Range
Column 2: First number
Column 3: Last number
Column 4: Step
Column 5: All cells

Examples:

B2:B6 2 60 2 yes
G20:K100 5 1000 3

B2:B6 will be filled with even numbers in the range 2 - 60 (inclusive).
Step 2 means, that the random numbers will be 2,4,6,8,10,.....,60.
The "yes" in column 5 means, that doubleclicking a cell in B2:B6 will
fill all cells at once. If the cell in column 5 is empty, a click will only
fill the clicked cell.
The "yes" could have been anything (true, 1 etc). As long as the cell
is *not empty*, all cells in the range will be filled immediately.

The second example has a pool of random numbers consisting of
5,8,11,14,17,.........
Doubleclicking a cell in G20:K100 will only fill this cell.

Doubleclicking a filled cell, will ask you, if you want a new number(s).

There's no limit to the number of RandRanges.

The below sub "Worksheet_BeforeDoubleClick" is inserted by copying
the code, rightclicking the sheet tab and paste to the righthand window.

The same code can be inserted from more sheets at the same time.
The important thing is, that the RandTables are named *locally* as
described above.


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, _
Cancel As Boolean)
'Leo Heuser, 20 Sep. 2006, ver. 2
Dim Answer As Variant
Dim Cell As Range
Dim Counter As Long
Dim Counter1 As Long
Dim DummyRange As Range
Dim RandData As Variant
Dim RandRange As Range
Dim RandTableRange As Range
Dim RandTableValue As Variant
Dim RandTableName As String

RandTableName = "RandTable"

Set RandTableRange = Range(ActiveSheet.Name & "!" & RandTableName)
Set RandTableRange = RandTableRange. _
Resize(Application.CountA(RandTableRange.Columns(1 )))

RandData = RandTableRange.Value

For Counter = LBound(RandData, 1) To UBound(RandData, 1)
Set RandRange = Range(RandData(Counter, 1))

If Not Intersect(Target, RandRange) Is Nothing Then
If Target.Cells.Count 1 Then Exit Sub

Cancel = True

If Not (IsEmpty(Target)) Then
Answer = MsgBox("Do you want a new random number(s)?", _
vbDefaultButton2 + vbYesNo)
If Answer < vbYes Then Exit Sub
End If

If IsEmpty(RandData(Counter, 5)) Then
Set DummyRange = Target
Else
RandRange.ClearContents
Set DummyRange = RandRange
End If

For Each Cell In DummyRange.Cells
Cell.Value = NewRandNum(RandRange, _
RandData(Counter, 2), _
RandData(Counter, 3), _
RandData(Counter, 4))
Next Cell

Exit Sub
End If
Next Counter
End Sub


The code below is inserted in a general module.
(<Alt<F11, Insert Module)


Function NewRandNum(RandRange As Range, FirstNum As Variant, _
LastNum As Variant, StepValue As Variant) As Variant
'Leo Heuser, 20 Sep. 2006, ver. 2
'When a number is inserted in a cell, it's not updated ever,
'and it is removed from the random number pool of that range.
'If a number is deleted from a cell, it's automatically added
'to the pool of that range.
Dim Counter As Double
Dim Counter1 As Long
Dim RandCol As New Collection
Dim RandNum As Long
Dim RandRangeValue As Variant

Randomize

RandRangeValue = RandRange.Value

On Error Resume Next

If LastNum < FirstNum Then
StepValue = -Abs(StepValue)
Else
StepValue = Abs(StepValue)
End If

For Counter = FirstNum To LastNum Step StepValue
RandCol.Add Item:=Counter, key:=CStr(Counter)
Next Counter

For Counter = 1 To UBound(RandRangeValue, 1)
For Counter1 = 1 To UBound(RandRangeValue, 2)
If Not (IsEmpty(RandRangeValue(Counter, Counter1))) Then
RandCol.Add Item:=RandRangeValue(Counter, Counter1), _
key:=CStr(RandRangeValue(Counter, Counter1))
If Err.Number < 0 Then
RandCol.Remove _
CStr(RandRangeValue(Counter, Counter1))
Err.Number = 0
End If
End If
Next Counter1
Next Counter

RandNum = Int(Rnd() * RandCol.Count) + 1

NewRandNum = RandCol(RandNum)

On Error GoTo 0

End Function


Cheers
Leo
















--
Best regards
Leo Heuser

Followup to newsgroup only please.