VBA - 如何从一列中随机选择 10% 的行,确保它们不同并将 Y 放在 B 列中?

Posted

技术标签:

【中文标题】VBA - 如何从一列中随机选择 10% 的行,确保它们不同并将 Y 放在 B 列中?【英文标题】:VBA - How do I randomly select 10% of rows from a column, ensuring they are different and put a Y in column B? 【发布时间】:2021-10-30 06:12:28 【问题描述】:

我希望随机选择 10% 的由不同用户完成的任务(“发起人”P 列),并在 B 列中放置一个 Y,以便检查员对工作进行 QC。如果 10% 不是整数,那么我需要四舍五入,即 0.8 需要 1 行,1.3 需要 2 行。

我是编码新手,我已经能够添加代码来过滤行以在 P 列中显示所需的日期和“发起者”,然后将此范围命名为“用户名”。我不知道如何编码来选择随机的 10%。我已将我正在努力解决的部分更改为下面的粗体。

Sub randomSelection()

Dim dt As Date
dt = "20/08/2021"


Dim lRow As Long


'Format date
    Range("J:J").Select
    Selection.NumberFormat = "dd/mm/yyyy"
    
 'Select User Grogu

    ActiveSheet.Range("$A$1:$W$10000").AutoFilter 10, Criteria1:="=" & dt
    ActiveSheet.Range("$A$1:$W$10000").AutoFilter Field:=16, Criteria1:= _
        "SW\Grogu"
        
'Name range "userNames"
  With ActiveSheet
  
  lRow = .Cells(Rows.Count, 16).End(xlUp).Row
  If lRow < 3 Then Exit Sub
  
  .Cells(1, 16).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
  End With

 Selection.Name = "userNames"
 
**'Randomly select 10% of rows from originator and put a Y in column B**
 
'remove all defined names

    On Error Resume Next
    ActiveWorkbook.Names("userNames").Delete

 'Select User Finn

    ActiveSheet.Range("$A$1:$W$10000").AutoFilter 10, Criteria1:="=" & dt
    ActiveSheet.Range("$A$1:$W$10000").AutoFilter Field:=16, Criteria1:= _
        "SW\Finn"
        
'Name range "userNames"
  With ActiveSheet
  
  lRow = .Cells(Rows.Count, 16).End(xlUp).Row
  If lRow < 3 Then Exit Sub
  
  .Cells(1, 16).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
  End With

 Selection.Name = "userNames"
 
'remove all defined names

    On Error Resume Next
    ActiveWorkbook.Names("userNames").Delete
    
    'Formate Date back
    Range("J:J").Select
    Selection.NumberFormat = "yyyy-mm-dd"

End Sub

【问题讨论】:

如果可能,首先在工作表中的每一行添加=RAND(),然后按该列排序。这将为您提供更简单的选择方法。 定义的名称用于不同的东西。相反,您应该使用变量来创建对范围的引用:Dim rg As Range: Set rg = ActiveSheet.Cells(1, 16).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible)。现在你可以做 Dim cCount As Long: cCount = Int(rg.Cells.Count / 10): If rg.Cells.count Mod 10 &gt; 0 Then cCount = cCount + 1 。现在您可以继续使用函数here 来解决“随机业务”。了解如何避免 Select 和任何形式的 Active... 如VBasic2008所述,请阅读answer,了解如何避免使用Select 【参考方案1】:

我有一些空闲时间,编写了一个示例程序,它复制定义的一组行的 10%,然后将其粘贴到不同的工作表中。我添加了一些 cmets 来帮助解释每个部分的目标。

Sub Example()
    'Define the Start and End of the data range
    Const STARTROW As Long = 1
    Dim LastRow As Long
    LastRow = Sheet1.Cells(Sheet1.Rows.Count, 1).End(xlUp).Row
    
    'Create an Array - Length = Number of Rows in the data
    Dim RowArr() As Long
    ReDim RowArr(STARTROW To LastRow)
    
    'Fill the Array - Each element is a row #
    Dim i As Long
    For i = LBound(RowArr) To UBound(RowArr)
        RowArr(i) = i
    Next i
    
    'Shuffle the Row #'s within the Array
    Randomize
    Dim tmp As Long, RndNum As Long
    For i = LBound(RowArr) To UBound(RowArr)
        RndNum = WorksheetFunction.Floor((UBound(RowArr) - LBound(RowArr) + 1) * Rnd, 1) + LBound(RowArr)
        tmp = RowArr(i)
        RowArr(i) = RowArr(RndNum)
        RowArr(RndNum) = tmp
    Next i
    
    'Calculate the number of rows to divvy up
    Const LIMIT As Double = 0.1 '10%
    Dim Size As Long
    Size = WorksheetFunction.Ceiling((UBound(RowArr) - LBound(RowArr) + 1) * LIMIT, 1)
    If Size > UBound(RowArr) Then Size = UBound(RowArr)
    
    'Collect the chosen rows into a range
    Dim TargetRows As Range
    For i = LBound(RowArr) To LBound(RowArr) + Size
        If TargetRows Is Nothing Then
            Set TargetRows = Sheet1.Rows(RowArr(i))
        Else
            Set TargetRows = Union(TargetRows, Sheet1.Rows(RowArr(i)))
        End If
    Next i
    
    'Define the Output Location
    Dim OutPutRange As Range
    Set OutPutRange = Sheet2.Cells(1, 1) 'Top Left Corner
    
    'Copy the randomly chosen rows to the output location
    TargetRows.Copy Destination:=OutPutRange.Resize(TargetRows.Rows.Count).EntireRow
    
End Sub

【讨论】:

我不是一个数学家,所以我不知道我的随机数洗牌是否有偏见。但在我的简短测试中,它显得足够随机。

以上是关于VBA - 如何从一列中随机选择 10% 的行,确保它们不同并将 Y 放在 B 列中?的主要内容,如果未能解决你的问题,请参考以下文章

如何从一列中选择不同的类别数据?

如何从一列中查找每个值并使用“;”返回电子邮件地址分隔器

Excel vba将公式从一列自动填充到Excel中的最后一列

EXCEL函数 如何删除某一列中不含某一元素的行

如何编写sql查询以选择一列中具有最大值的行

从一列中选择值的所有组合