Excel:根据第一列

时间:2018-04-02 12:35:25

标签: excel excel-vba vba

Hullo那里。

我有一张不同设备的备件表。 A列包含设备名称,后续列包含部件的详细信息。如果备件通过多个设备共享,则所有这些设备都在A列中命名(例如,列A可能为红色"设备A,设备B,设备C")。

有没有办法创建一个命名范围,其中包含特定设备名称出现在A列中的所有行? (例如,包含设备B的所有备件细节的命名范围?)它需要是动态的,因此如果为设备添加或删除部件,命名范围将更新以反映这一点。

更新:对不起如果我在这里有点神秘,那只是我不能包含精算表,因为数据是敏感的。这是一个示例表,用于尝试说明我的问题:Example table

所以我正在寻找的是为设备B的所有备件创建命名范围的方法 - 即第2,3,6,8,10行。我希望它包括设备B最后的任何新零件,或者如果我们在第3排插入新的零件号1235,则可以容纳它。希望这样可以使它更清晰。

1 个答案:

答案 0 :(得分:0)

我有兴趣了解如何做到这一点。我最终不得不使用辅助函数。

我首先执行了 Ctrl + F3 来打开名称管理器并添加了一个动态命名范围DeviceData,它捕获了除标题之外的所有设备数据:< / p>

Data and named range

RefersTo公式为:

=OFFSET(Sheet1!$A$2,0,0,COUNTA(Sheet1!$A$2:$A$1048576),COUNTA(Sheet1!$1:$1))

然后在标准模块中的以下代码生成名为范围组的设备:

Option Explicit

Public Sub CreateNameRanges()

    Dim dict As Object
    Dim ws As Worksheet

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Set dict = CreateObject("Scripting.Dictionary")

    Dim arr()
    'DeviceData is a dynamic named range in sheet1

    With ws.Range("DeviceData").Columns(1)
        arr = .Value                             'change as appropriate

        Dim currValue As Long

        For currValue = LBound(arr, 1) To UBound(arr, 1)

            If Not dict.exists(arr(currValue, 1)) Then
                dict.Add arr(currValue, 1), .Cells(currValue).Row
            Else
                dict(arr(currValue, 1)) = dict(arr(currValue, 1)) & ":" & .Cells(currValue).Row
            End If

        Next currValue

        Dim key As Variant
        Dim rng As Range

        For Each key In dict.keys
            ThisWorkbook.Names.Add Name:=Replace$(key, Chr(32), vbNullString), RefersTo:=GetRowRange(ws, dict(key))
        Next key

    End With

End Sub

Public Function GetRowRange(ByVal ws As Worksheet, ByVal dictkey As String) As Range

    Dim i As Long
    Dim unionRng As Range
    Dim arr() As String
    arr = Split(dictkey, ":")

    For i = LBound(arr) To UBound(arr)
        If Not unionRng Is Nothing Then
            Set unionRng = Union(unionRng, ws.Rows(arr(i)))
        Else
            Set unionRng = ws.Rows(arr(i))
        End If
    Next i

    If Not unionRng Is Nothing Then Set GetRowRange = unionRng
End Function