【问题标题】:VBA/Macro for multiple condition用于多种条件的 VBA/宏
【发布时间】:2016-07-15 07:00:25
【问题描述】:

我需要帮助才能从具有特定条件的另一个工作簿中获取随机数据:

这是我的数据在rawdata.xlsx中的样子

如果我点击一个按钮/运行一个宏,我应该得到 4 个随机样本 for all rows that has "AU", 1 个随机样本 for all rows that has "FJ", 1 个随机样本 for all rows that has "NC"3 个随机样本 for all rows that has "NZ",和1 个随机样本 for all rows that has "SG12" ...

... FROM rawdata.xlsx "Sheet1" sheet 并将其粘贴到 tool.xlsm "Random Sample" sheet.

一切都应该一键完成。

这是我目前的代码:

        Option Explicit

Sub MAIN()
Dim key As String
Dim nKeyCells As Long, nRndRows As Long, rOffset As Long
Dim nRowsArr As Variant, keyArr As Variant
Dim i As Integer
Dim dataRng As Range, helperRng1 As Range, helperRng2 As Range
Dim rawDataWs As Worksheet, randomSampleWs As Worksheet

Set rawDataWs = Workbooks("rawdata.xlsx").Worksheets("Sheet1")
Set randomSampleWs = Workbooks("tool.xlsm").Worksheets("Random Sample")

keyArr = Array("AU", "FJ", "NC", "NZ", "SG12") '<== set your keywords
nRowsArr = Array(4, 1, 1, 3, 1) '<== set the n° of random rows to be associated to its correspondant keyword

With rawDataWs
    Set dataRng = .Range("B2:" & .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft).Column).Address) '<== adapt it to your needs. keywords are assumed to be in the firts column of this range
    Set dataRng = Intersect(.UsedRange, dataRng)
End With

Set helperRng1 = dataRng.Resize(, 1).Offset(, dataRng.Columns.Count + 1) '<== here will be placed "1"s to mark rows to be copied and pasted: they'll be cleared at the end
For i = 0 To UBound(keyArr)
    nRndRows = CInt(nRowsArr(i))
    key = CStr(keyArr(i))
    nKeyCells = WorksheetFunction.CountIf(dataRng.Resize(, 1), key)
    Set helperRng2 = helperRng1.Offset(, 1).Resize(nRndRows) '<== here will be pasted random numbers: they'll be cleared at the end
    Call Unique_Numbers(1, nKeyCells, nRndRows, helperRng2)
    With helperRng1
        .Formula = "=IF(AND(RC" & dataRng.Columns(2).Column & "=""" & key & """,countif(" & helperRng2.Address(ReferenceStyle:=xlR1C1) & ",countif(R" & dataRng.Rows(1).Row & "C" & dataRng.Columns(2).Column & ":RC" & dataRng.Columns(2).Column & ",""" & key & """))>0),1,"""")"
        .value = .value
        Intersect(.EntireRow, dataRng).Copy Destination:=randomSampleWs.Range("A2").Offset(rOffset)
        rOffset = rOffset + nRndRows
        .EntireColumn.Resize(, 2).Clear
    End With
Next i

End Sub


Sub Unique_Numbers(Mn As Long, Mx As Long, Sample As Long, refRange As Range)
Dim tempnum As Long
Dim i As Long
Dim foundCell As Range
' adapted from https://support.microsoft.com/en-us/kb/213290

If Sample > Mx - Mn + 1 Then
    MsgBox "You specified more numbers to return than are possible in the range!"
    Exit Sub
End If

Set refRange = refRange.Resize(Sample, 1)

Randomize
refRange(1) = Int((Mx - Mn + 1) * rnd + Mn)
For i = 2 To Sample
    Set foundCell = Nothing
    Do
       Randomize
       tempnum = Int((Mx - Mn + 1) * rnd + Mn)
       Set foundCell = refRange.Find(tempnum)
    Loop While Not foundCell Is Nothing
    refRange(i) = tempnum
Next

End Sub

【问题讨论】:

    标签: excel vba random conditional-statements


    【解决方案1】:

    试试这个

    Option Explicit
    
    Sub MAIN()
    Dim key As String
    Dim nKeyCells As Long, nRndRows As Long, rOffset As Long
    Dim nRowsArr As Variant, keyArr As Variant
    Dim i As Integer
    Dim dataRng As Range, helperRng1 As Range, helperRng2 As Range
    Dim rawDataWs As Worksheet, randomSampleWs As Worksheet
    
    Set rawDataWs = Workbooks("rawdata.xlsx").Worksheets("Sheet1")
    Set randomSampleWs = Workbooks("tool.xlsm").Worksheets("Random Sample")
    
    keyArr = Array("AA", "BB", "CC", "DD") '<== set your keywords
    nRowsArr = Array(4, 1, 3, 1) '<== set the n° of random rows to be associated to its correspondant keyword
    
    With rawDataWs
        Set dataRng = .Range("A2:E200") '<== adapt it to your needs. keywords are assumed to be in the firts column of this range
        Set dataRng = Intersect(.UsedRange, dataRng)
    End With
    
    Set helperRng1 = dataRng.Resize(, 1).Offset(, dataRng.Columns.Count + 1) '<== here will be placed "1"s to mark rows to be copied and pasted: they'll be cleared at the end
    For i = 0 To UBound(keyArr)
        nRndRows = CInt(nRowsArr(i))
        key = CStr(keyArr(i))
        nKeyCells = WorksheetFunction.CountIf(dataRng.Resize(, 1), key)
        Set helperRng2 = helperRng1.Offset(, 1).Resize(nRndRows) '<== here will be pasted random numbers: they'll be cleared at the end
        Call Unique_Numbers(1, nKeyCells, nRndRows, helperRng2)
        With helperRng1
            .Formula = "=IF(AND(RC" & dataRng.Columns(1).Column & "=""" & key & """,countif(" & helperRng2.Address(ReferenceStyle:=xlR1C1) & ",countif(R" & dataRng.Rows(1).Row & "C" & dataRng.Columns(1).Column & ":RC" & dataRng.Columns(1).Column & ",""" & key & """))>0),1,"""")"
            .Value = .Value
            Intersect(.SpecialCells(xlCellTypeConstants).EntireRow, dataRng).Copy Destination:=randomSampleWs.Range("A2").Offset(rOffset)
            rOffset = rOffset + nRndRows
            .EntireColumn.Resize(, 2).Clear
        End With
    Next i
    
    End Sub
    
    
    Sub Unique_Numbers(Mn As Long, Mx As Long, Sample As Long, refRange As Range)
    Dim tempnum As Long
    Dim i As Long
    Dim foundCell As Range
    ' adapted from https://support.microsoft.com/en-us/kb/213290
    
    If Sample > Mx - Mn + 1 Then
        MsgBox "You specified more numbers to return than are possible in the range!"
        Exit Sub
    End If
    
    Set refRange = refRange.Resize(Sample, 1)
    
    Randomize
    refRange(1) = Int((Mx - Mn + 1) * Rnd + Mn)
    For i = 2 To Sample
        Set foundCell = Nothing
        Do
           Randomize
           tempnum = Int((Mx - Mn + 1) * Rnd + Mn)
           Set foundCell = refRange.Find(tempnum)
        Loop While Not foundCell Is Nothing
        refRange(i) = tempnum
    Next
    
    End Sub
    

    注意没有限制案例检查/处理

    【讨论】:

    • 我根据您的建议使用当前代码更新了帖子中的代码,但我仍然遇到问题。我收到错误 1004:未找到单元格,我被定向到这行代码:Intersect(.SpecialCells(xlCellTypeConstants).EntireRow, dataRng).Copy Destination:=randomSampleWs.Range("A2").Offset(rOffset )。有什么想法吗?
    • 正如我所概述的,我的答案没有限制案例检查/处理,您必须注意。其中一个可能会引发该错误:您可以输入 keyArr 一个关键字,该关键字在您的实际 dataRng 范围的第一列中不存在。或者Unique_Numbers sub 的参数可能不一致(Mx &lt;MnSample &gt; Mx - Mn + 1)。或其他(数据可能是讨厌的野兽......)。最后我指出我假设您在 dataRng 中的数据只是“常量”(无论是数字还是字符串):它们应该是(也是)公式,然后删除 .SpecialCells(xlCellTypeConstants
    • 哦。没看到。现在工作,但所有行都被复制。我注意到的一件事是我在 rawdata.xlsx 中有 932 行,但是当我在 tool.xlsm 中检查随机样本表时,我得到了 940。它怎么会超过?
    • 没有看到你的实际数据是不可能回答的,你可以发布它们。否则,如果您单步执行代码并查看每个语句的执行情况,您将自己获得所有答案。
    • 我在问题帖子中附上了我的数据的截图
    猜你喜欢
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2021-09-01
    相关资源
    最近更新 更多