2016-08-05 10 views
0

定義された行列サイズを通り、セルをその範囲内でランダムに充填するVBAコードを書いています。VBA - ループでセルを充填している間重複をチェックする

私はstackoverflowのユーザーからコードを入手しましたが、テストした後、重複した塗りつぶしを避けるためには適していないことが分かりました。例えば5セルを塗りつぶすと、ランダム充填は、前に充填されたセルで働いた。

これは、私が働いているコードです:完璧に動作し、これと同じ正確なコードを使用して

Dim lRandom As Long 
Dim sCells As String 
Dim sRandom As String 
Dim rMolecules As Range 
Dim i As Integer, j As Integer 
Dim lArea As Long 


lArea = 400 '20x20 
'Populate string of cells that make up the container so they can be chosen at random 
For i = 1 To 20 
    For j = 1 To 20 
     sCells = sCells & "|" & Cells(i, j).Address 
    Next j 
Next i 
sCells = sCells & "|" 

'Color the molecules at random 
For i = 1 To WorksheetFunction.Min(5, lArea) 
    Randomize 
    lRandom = Int(Rnd() * 400) + 1 
    sRandom = Split(sCells, "|")(lRandom) 
    Select Case (i = 1) 
     Case True: Set rMolecules = Range(sRandom) 
     Case Else: Set rMolecules = Union(rMolecules, Range(Split(sCells, "|")(lRandom))) 
    End Select 
    sCells = Replace(sCells, "|" & sRandom & "|", "|") 
    lArea = lArea - 1 
Next i 

rMolecules.Interior.ColorIndex = 5 

、セルがある場合、コードはチェックなるようにすることを私は何を挿入することができ、私はWHEREをしますかすでに文字列や色で塗りつぶされていますか?

私が探しているこのコードは

rMolecules.Interior.ColorIndex = 5 

前に右であるべきかのように私は感じしかし、私は入力するかわからないんだけど。

EDIT 私はより具体的でなければならないことに気付きました。 ランダムにセルを青色(.ColorIndex = 5)で塗りつぶそうとしていますが、最初に確認する必要があるのは、ランダム化がセルを2回マークしていない場合です。この場合は、 5つの異なる細胞にマーキングすると、重複のためにそれらのうちの4つだけをマークし、したがって、青色を有する4つの細胞のみを満たす。私はそれを避け、マーク/記入する別のセルを選択させる必要があります。

ご協力いただきありがとうございます。

+0

あなたの主な質問の他に、ループから、そして関数全体からでも、「ランダム化」を削除する必要があります。一度だけ使用する必要があります - ブックが開かれるときが望ましいループで 'Randomize'を使うと、256個の値のセットからランダムな値が得られます。これは、VBAの開始以来そこにあった奇妙なバグです。 –

+0

私はあなたがしようとしていることを完全に理解していないと言わざるを得ない。ランダムな色でセルを塗りつぶす方法を探していますが、色を重複させたくないのですか? – Spurious

+0

@ Spurious:特定の色(この場合は青色)でランダムにセルを塗りつぶす方法を探していますが、セルを塗りつぶす前に、ランダム化がセルを2回マークしていないかどうかを確認する必要があります。 .ColorIndex = 5で塗りつぶすと、同じセルに再び塗りつぶされません。 – vbmolec

答えて

0

あなたはCollectionで使用する細胞を維持し、それらを削除します。

Sub FillRandomCells(targetRange As Range, numberOfCells As Long) 

    ' populate collection of unique cells 
    Dim c As Range 
    Dim targetCells As New Collection 

    ' make sure arguments make sense 
    If numberOfCells > targetRange.Cells.Count Then 
     Err.Raise vbObjectError, "FillRandomCells()", _ 
       "Number of cells to be changed can not exceed number of cells in range" 
    End If 

    For Each c In targetRange.Cells 
     targetCells.Add c 
    Next 

    ' now pick random 5 
    Dim i As Long, randomIndex As Long 
    Dim upperbound As Long 
    Dim lowerbound As Long 

    For i = 1 To numberOfCells 
     lowerbound = 1     ' collections start with 1 
     upperbound = targetCells.Count ' changes as we are removing cells we used 

     randomIndex = Int((upperbound - lowerbound + 1) * Rnd + lowerbound) 
     Set c = targetCells(randomIndex) 
     targetCells.Remove randomIndex ' remove so we don't use it again! 

     c.Interior.Color = 5   ' do what you need to do here 
    Next 

End Sub 

Sub testFillRandomCells() 
    FillRandomCells ActiveSheet.[a1:t20], 5 
    FillRandomCells ActiveSheet.[b25:f30], 3 
End Sub 

EDITを:目標範囲と関数の引数として、設定変更されたセルの数を作るために変更しました。また、エラーチェックを追加しました(常にそうしてください!)。

+0

ありがとうございます@Loganリード、私はこれを試しますが、スプリアスのコードも働いたが。あなたのコードのために2つありがとう、あなたは非常に役立ってきました。とても有難い。 – vbmolec

+0

@vbmolecスプリアスのコードは間違いなく動作します。私の解決策では、重複を完全にチェックする必要がなくなります。これはやや効率的です。また、ループの繰り返しごとに配列を分割するのは避けるべきです。非常に効率的ではありません(最初は一度行い、変数として保持します)。 –

+0

私は自分の既存のコードをあなたのものに置き換えると思う。私はそれを動的にする必要があります - ユーザーは2つの変数に格納されている次元を選択し、コードはその2つの数値(100x100または15x15)内でのみ動作するはずです。この行では:For Each c ActiveSheet。[a1:t20] .Cells '20x20 range? – vbmolec

0

乱数のリストを作成してScripting.Dictionaryに配置しないと、辞書のExistメソッドを使用して重複を検出し、十分なものが得られるまでループして、独自のコードを確実に入力できます。リスト。あなたは、ランダムなセルを埋めるよう

+0

私は、なぜ誰もが 'Scripting.Dictionary'との唯一の違いは、あなたが値を入れた後でキーを取得できないということです。他のすべては、標準のVBAメソッド(組み込みではありませんが、あなた自身で書くことができます)で実現できます。 –