2017-08-11 153 views
2

我正在计算出用户选择显示在工作表按钮I.e旁边工作表顶部的行数。按钮显示“生成电子邮件”,旁边显示“已选择x项”。VBA Rows.Count in Selection

由于这是每次更新的选择改变时,我有以下代码:

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    Sheet1.Range("E1") = Target.Rows.Count & " items selected" 
End Sub 

此工作正常,如果用户选择连续行,对于例如7:10返回4.

我的问题是如果用户选择了行7和10.它只会返回1(选择的第一部分中的行)。

从我发现,没有办法从属性中获取这个值,但我无法得到我的头周围如何遍历选择/目标的所有部分,并计算行的总和。那么也有可能用户选择说A7,C7和A10。 A7和C7涉及相同的项目,所以这应该只能真正被视为一个,而不是两个,我认为我的假设代码会做...

有没有人试图实现这一点,并已成功或可能点我在一些可能有所帮助的房产方向?我尝试了一个单独的功能来实现它,但那也不起作用。

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    Sheet1.Range("E1") = getRowCount(Target) & " items selected" 
End Sub 

Function getRowCount(selectedRanges As Ranges) 
    rowCount = 0 
    For Each subRange In selectedRanges 
    rowCount = rowCount + subRange.Rows.Count 
    Next 

    getRowCount = rowCount 
End Function 
+0

Esperadoce - 感谢编辑格式,我只是下载了应用程序,希望添加格式,但你击败了我! –

回答

2

我认为这会工作。 (没有当我尝试了。)

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    'Create a range containing just column A 
    Dim subRange As Range 
    Dim r As Range 
    For Each subRange In Target.Areas 
     If r Is Nothing Then 
      Set r = subRange.EntireRow.Columns(1) 
     Else 
      Set r = Union(r, subRange.EntireRow.Columns(1)) 
     End If 
    Next 
    'Count how many cells in the combined column A range 
    Sheet1.Range("E1") = r.Cells.Count & " items selected" 
End Sub 
+0

我打算将其标记为答案,因为它是我已经整合的第一个,并且它的工作很快。这不是我曾经想过的方式,但是作为一种简单的方法来进行计算对我来说是有意义的。接下来的这一部分不是我原来的问题的一部分,但是向前移动,是否有一种方法可以遍历r(?)以获取每行中各列的数据? –

+0

@OliBarton在我的代码中,'r'与原始选择完全无关,只是它指向每一行的列A.所以如果你的选择是'B5:B10,D8:D12,C15:J20',那么'r'就是'A5:A12,A15:A20'。所以如果你在'D5:D12,D15:D20'之后,你可以遍历'r'中的每个单元并使用'Offset(0,3)'到达相应的D列(或者只是遍历'r。 EntireRow.Coumns(“D”)'),但如果你只对'D8:D12,D15:D20'感兴趣,则需要遍历'Intersect(r.EntireRow.Columns(“D”),Target)'' 。 – YowE3K

0

您需要计算用户选择的每个Area中的行。
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-areas-property-excel

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 

    Dim rArea As Range 
    Dim lCount As Long 

    For Each rArea In Selection.Areas 
     lCount = lCount + rArea.Rows.Count 
    Next rArea 

    Sheet1.Range("E1") = lCount 

End Sub 
+0

你打我20秒! :D(PS)关于如何避免在多个领域出现重复计数行的任何建议?在OP的情况下可能不是问题,但如果您有任何明智的想法,仍然可以很好地知道以供将来参考) – YowE3K

+0

在我读你的第一条评论之前,我没有考虑过重复计算。现在想想它。 –

+0

而且,在重新阅读这个问题时,听起来好像在**的情况下会发生**( – YowE3K

0
Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
Dim cell As Range 
Dim i, currentRow As Long: i = 0 
'get row of first cell in range 
currentRow = Target.Cells(1, 1).row 

For Each cell In Target 
    'if row is different, then increase number of items, as it's next item 
    If Not currentRow = cell.row Then 
     i = i + 1 
     currentRow = cell.row 
    End If 
Next cell 

Range("E1").Value = i 

End Sub 
+0

您可以选择不按顺序,然后下一个单元格不一定低于前一个单元格 – Wolfie

1
Sub NumberOfRowsSelected() 
Dim vMatch As Variant, aRows() As Long, r As Range, x As Long 

ReDim Preserve aRows(x) 
aRows(x) = 0 

For Each r In Selection.Cells 
    vMatch = Application.Match(r.Row, aRows, 0) 

    If IsError(vMatch) Then 
     x = x + 1 
     ReDim Preserve aRows(0 To x) 
     aRows(x) = r.Row 
    End If 
Next r 

MsgBox UBound(aRows) 

End Sub 

修改过的代码转换为功能

Sub NumberOfRowsSelected() 
    MsgBox RowsCount(Selection) 
End Sub 

Function RowsCount(rRange As Range) As Long 
Dim vMatch As Variant, aRows() As Long, r As Range, x As Long 

ReDim Preserve aRows(x) 
aRows(x) = 0 

For Each r In rRange.Cells 
    vMatch = Application.Match(r.Row, aRows, 0) 

    If IsError(vMatch) Then 
     x = x + 1 
     ReDim Preserve aRows(0 To x) 
     aRows(x) = r.Row 
    End If 
Next r 

RowsCount = UBound(aRows) 

End Function 
+0

您对'aRows'的设置使我困惑,您'ReDim'它使用未定义的'x'大小为0(为什么不仅仅是将它调整到合适的大小),然后为第0个元素赋值0,它默认情况下已经是默认值了......如果这是一个函数,那么它会更有用,返回值比调用魔鬼('MsgBox') – Wolfie

+0

默认情况下数组以零计数器开始。我开始使用零计数器数组,因为x也是零,我没有给x赋值,所以x默认为零。 aRows(x)在这意味着aRows(0)。在Excel中,行从1开始,在Excel中没有0行。所以aRows(x)= 0意味着我在说aRows(0_Counter)= 0作为行值来将aRows变量设置为数组。所以Match函数会将它视为数组,因为我已经在aRows数组中加载了一个0 Row值,所以不会抛出任何错误。 – Sixthsense

+0

啊好吧,考虑在未来的答案中加入一些评论来说明这样的点,这些点对于读者来说并不是立即显而易见的:)感谢 – Wolfie

1

一种不同的方法,建立检查行的字符串似乎相当直截了当,以避免双重计算。查看评论的详细信息:

Function getRowCount(rng As Range) As Long 
    Dim c As Range 
    ' Keep track of which rows we've already counted 
    Dim countedrows As String: countedrows = "," 
    ' Loop over cells in range 
    For Each c In rng 
     ' Check if already counted 
     If Not InStr(countedrows, "," & c.Row & ",") > 0 Then 
      ' Add to counted list 
      countedrows = countedrows & c.Row & "," 
     End If 
    Next c 
    ' Get number of rows counted 
    Dim rowsarr() As String: rowsarr = Split(countedrows, ",") 
    getRowCount = UBound(rowsarr) - LBound(rowsarr) - 1 
End Function 
+0

这会是一个问题,如果我们有例如'13,'然后'3,'算数?我的意见完全一样:) –

+0

你说得对,我只考虑了'1,'和'13'的情况!我编辑了我的答案,以确保每个数字的双方都有一个逗号,现在应该可以工作。 – Wolfie

+0

感谢您的回复,我很有信心这会在阅读时发挥作用,但我已经将它放到了我的工作簿中,并且令人生厌的是它正在计算重复的行= /只需检查,我是否应该简单地将它调用如下:Dim lCount As Long - 然后 - lCount = getRowCount(选择)? –