[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『範囲の中からランダムに5カ所白文字にしたい』(ポコペン)
Sub test()
Dim v
Dim i As Long
Dim n As Long
Range("D3:M12").ClearContents
v = Range("D3:M12").Value
For i = 1 To 5
n = Int((UBound(v, 1) * UBound(v, 2)) * Rnd + 1)
Range("D3:M12").Item(n).Value = "白文字"
Next
End Sub
Sub test2()
Dim myRng As Range
Dim i As Long
Dim n As Long
Set myRng = Range("D3:M12")
myRng.ClearContents
For i = 1 To 5
With myRng
n = Int((.Columns.Count * .Rows.Count) * Rnd + 1)
.Item(n).Value = "白文字"
End With
Next
End Sub
マナさん わたしの拙い文章にお応え頂きありがとうございました。 的確な例題ありがとうございました、無事にでぎました。 下のように直して使わせ頂きます。
Dim v
Dim i As Long
Dim n As Long
Range("D3:M12").Font.ColorIndex = 1
v = Range("D3:M12").Value
For i = 1 To 5
n = Int((UBound(v, 1) * UBound(v, 2)) * Rnd + 1)
Range("D3:M12").Item(n).Font.ColorIndex = 2
Next
(ポコペン)
< n = Int((UBound(v, 1) * UBound(v, 2)) * Rnd + 1) 5回繰り返すと、5個の数値の中には同じものが出てきそうな気がします。 変化させるセル数は4個以下になったりしませんか? (Hatch)
ポコペンさん、ごめんなさい。 Hatchさん、こういう場合どうするのでしょう?教えてください。
自分でも考えてみます。
>こういう場合どうするのでしょう?教えてください。
いろいろ方法があるんだろうね。こちらでやっているトランプめくりでは 1.めくった数をDictionaryにでも格納しておいて、格納済みの数なら採用しない とか 2.今回の場合はちょっと面倒になるけど、たとえば全体のめくるべきセルアドレスをCollectionやDictionaryにいれておいて たとえばその要素数が100個なら、最初に1〜100で値を取得して、取得した値をインデックスとして 抜き出した後、その要素をRemove。次に1〜99で値を取得して・・・・
といった方法を使ったりしている。
(ぶらっと)
修正版です。ポコペンさん見てるといいんだけど。 Hatchさんも、ご指摘ありがとうございました。
Sub test3()
Dim myRng As Range
Dim i As Long
Dim n As Long
Dim dic As Object
Dim cnt As Long
Set dic = CreateObject("Scripting.Dictionary")
Set myRng = Range("D3:M12")
myRng.Font.ColorIndex = 1
Do
With myRng
n = Int((.Columns.Count * .Rows.Count) * Rnd + 1)
If Not dic.exists(n) Then
dic(n) = Empty
cnt = cnt + 1
.Item(n).Font.ColorIndex = 2
End If
End With
Loop Until cnt = 5
Set myRng = Nothing
Set dic = Nothing
End Sub
私はこんなものを考えていました。
ダブりがあるか心配でしたので、一応1000回のループで5個となるのは確認しました。
組み合わせのランダム性などまでは考えていません(汗)
マナさんの.Item(n)を利用しています。 (Hatch)
Sub test_h()
Dim i As Long, j As Long, cnt As Long
Dim x(1 To 100)
Dim y(1 To 100) As Integer
Dim z(1 To 100) As Integer
Randomize
For i = 1 To 100
x(i) = Rnd()
y(i) = i
Next i
For i = 1 To 100
z(i) = y(Application.Match(Application.Small(x, i), x, 0))
Next i
With Range("D3:M12")
.Font.ColorIndex = 1
For i = 1 To 5
.Item(z(i)).Font.ColorIndex = 2
Next i
End With
End Sub
なるほど、こうするといいんですね。 Rndで同じものが出ない限り、問題ありませんね。 大変、勉強になりました。
凹ペンです、続けて不備があり見てました。 マナさん、Hatchさん、ぶらっとさん、ありがとうございます。 考えに抜けているところがありとっても困っています。 "D3:M12"の中からFont.ColorIndex = 1になった5カ所のセルの内容を P3から下のセルへと書き出したいのです。 もう一度お知恵をお貸しください。
For i = 1 To 5
.Item(z(i)).Font.ColorIndex = 2
Range("P" & i + 2).Value = .Item(z(i)).Value '★追加
Next i
じゃ、別案で。
Sub Sample()
Dim myClct As Collection
Dim i As Long
Dim x As Long
Dim n As Long
Application.ScreenUpdating = False
Set myClct = New Collection
For i = 1 To 100
myClct.Add i
Next
With Range("D3:M12")
For i = 1 To 5
x = Int((100 - i + 1) * Rnd + 1)
n = myClct(x)
.Cells(n).ClearContents
myClct.Remove x
Next
End With
Set myClct = Nothing
Application.ScreenUpdating = True
MsgBox "ランダムに5つのセルを空白にしました"
End Sub
(ぶらっと)
なるほど使用した要素は削除。とてもわかりやすいです。 大変勉強になります。
Sub Sample2()
Dim myClct As Collection
Dim i As Long
Dim x As Long
Dim n As Long
Application.ScreenUpdating = False
Set myClct = New Collection
For i = 1 To 100
myClct.Add i
Next
With Range("D3:M12")
.Font.ColorIndex = 1
For i = 1 To 5
x = Int((100 - i + 1) * Rnd + 1)
n = myClct(x)
.Cells(n).Font.ColorIndex = 2
Range("P" & i + 2).Value = .Cells(n).Value
myClct.Remove x
Next
End With
Set myClct = Nothing
Application.ScreenUpdating = True
End Sub
別案で
Sub test()
Dim r As Range, i As Long
Randomize
Range("d3:m12").Font.ColorIndex = xlAutomatic
With CreateObject("System.Collections.SortedList")
For Each r In Range("d3:m12")
.Item(Rnd) = r.Address
Next
For i = 0 To 4
Range(.GetByIndex(i)).Font.Color = vbWhite
Range("p3")(i + 1) = Range(.GetByIndex(i)).Value '<- 追加
Next
End With
End Sub
(seiya)
と思って過去ログ検索したら結構ありますね。 自分のものに出来るよう勉強してみます。seiyaさん、ありがとうございました。
ところでポコペンさん解決したかな〜。 私にはとてもありがたい回答を沢山いただけたんだけど もしポコペンさんを混乱させただけだったら、ごめんなさい。
横やり失礼します。
System.Collections.SortedList は .Net のオブジェクトなので Vista 以降では標準で使える ようになりましたが XP ではまだデフォルトではなかったので、すべての PC で使える オブジェクトとは考えない方がよいように思います。 http://officetanaka.net/excel/vba/tips/tips98.htm
質問者さんの環境がXPだったので、一応ご参考までに。 (Mook)
>Excel2003,WindowsXP 見落としました Objectを使用しない方法で
Sub test()
Dim a(), i As Long
With Range("d3:m12")
.Font.ColorIndex = xlAutomatic
ReDim a(1 To .Count, 1 To 2)
Randomize
For i = 1 To .Count
a(i, 1) = .Cells(i).Address
a(i, 2) = Rnd
Next
VSortM a, 1, .Count, 2
For i = 1 To 5
Range(a(i, 1)).Font.Color = vbWhite
Range("p3")(i).Value = Range(a(i, 1)).Value
Next
End With
End Sub
Private Sub VSortM(ary, LB, UB, ref)
Dim M As Variant, temp As Variant
Dim i As Long, ii As Long, iii As Long
i = UB: ii = LB
M = ary(Int((LB + UB) / 2), ref)
Do While ii <= i
Do While ary(ii, ref) < M: ii = ii + 1: Loop
Do While ary(i, ref) > M: i = i - 1: Loop
If ii <= i Then
For iii = LBound(ary, 2) To UBound(ary, 2)
temp = ary(ii, iii): ary(ii, iii) = ary(i, iii)
ary(i, iii) = temp
Next
ii = ii + 1: i = i - 1
End If
Loop
If LB < i Then VSortM ary, LB, i, ref
If ii < UB Then VSortM ary, ii, UB, ref
End Sub
(seiya)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.