1

我在 Excel (Table1) 中有一个表格,其中包含以下列标题:员工姓名、州许可和许可状态。该表的示例是:

John Adams  NY  Active
John Adams  PA  Active
John Adams  NJ  Inactive
Ralph Ames  MS  Active
Ed Turner   MS  Pending

我想设置一个摘要选项卡,每个员工有一行,其中有一列用于活动许可证、待处理许可证和非活动许可证,并且这些单元格将显示一个逗号分隔的适当状态代码列表。例如:

Name        Active   Pending   Inactive
John Adams  NY, PA             NJ
Ralph Ames  MS
Ed Turner            MS

我只是好奇进入这个自定义列表的最佳方式。我编写了下面的函数,它似乎工作正常,它的运行速度比我预期的要快,但它似乎效率低下,因为它每次都遍历整个表,并且我已将引用此函数的公式粘贴到几百个单元格:

Function comma_state_list(the_name As String, the_status As String) As String
    Dim ws As Worksheet
    Dim oLo As ListObject
    Dim oCol As ListColumns

    Set ws = Worksheets("State Licenses")
    Set oLo = ws.ListObjects("Table1")
    Set oCol = oLo.ListColumns

    For i = 1 To oLo.ListRows.Count
        If oLo.Range(i, 1).Value = the_name And oLo.Range(i, 3) = the_status Then
            comma_state_list = comma_state_list & oLo.Range(i, 4) & ", "
        End If
    Next i

    If Len(comma_state_list) = 0 Then
        comma_state_list = ""
    Else
        comma_state_list = Left(comma_state_list, Len(comma_state_list) - 2)
    End If
End Function

有没有办法可以使用 VBA 对表运行类似 SQL 的查询,所以我只是循环遍历 SQL 结果而不是每次都遍历整个表?我在想这也有助于按字母顺序排列摘要列表。或者也许还有其他更好的方法我没有想到。

4

1 回答 1

1

好的,这是一个使用脚本字典的示例。

我在一张工作表上有这张表:

按州列出的许可证状态初始表列表

并且输出应该生成一个带有摘要数据的新工作表,例如:

每个员工姓名输出一行汇总数据

我试图把它记录得非常彻底,但如果您对此有任何疑问,请告诉我。

Option Explicit
Sub Test()

Dim wsCurr As Worksheet: Set wsCurr = ActiveSheet
Dim wsNew As Worksheet 'output container'
Dim rowNum As Long 'row number for output'

'Scripting dictionaries:'
Dim inactiveDict As Object
Dim activeDict As Object
Dim key As Variant

'Table variables'
Dim rng As Range 'table of data'
Dim r As Long 'row iterator for the table range.'

'information about each employee/row'
Dim empName As String
Dim state As String
Dim status As String

'Create our dictionaries:'
Set activeDict = Nothing
Set inactiveDict = Nothing
Set activeDict = CreateObject("Scripting.Dictionary")
Set inactiveDict = CreateObject("Scripting.Dictionary")

Set rng = Range("A1:C6") 'better to set this dynamically, this is just an example'

For r = 2 To rng.Rows.Count
    empName = rng(r, 1).Value
    state = rng(r, 2).Value
    status = rng(r, 3).Value

    Select Case UCase(status)
        Case "ACTIVE"
            AddItemToDict activeDict, empName, state

        Case "INACTIVE"

            AddItemToDict inactiveDict, empName, state

    End Select
Next

'Add a new worksheet with summary data'

Set wsNew = Sheets.Add(After:=wsCurr)
With wsNew
    .Cells(1, 1).Value = "Name"
    .Cells(1, 2).Value = "Active"
    .Cells(1, 3).Value = "Inactive"

    rowNum = 2

    'Create the initial table with Active licenses'
    For Each key In activeDict
        .Cells(rowNum, 1).Value = key
        .Cells(rowNum, 2).Value = activeDict(key)
        rowNum = rowNum + 1
    Next

    'Now, go over this list with inactive licenses'
    For Each key In inactiveDict
        If activeDict.Exists(key) Then
            rowNum = Application.Match(key, .Range("A:A"), False)
        Else:
            rowNum = Application.WorksheetFunction.CountA(wsNew.Range("A:A")) + 1
            .Cells(rowNum, 1).Value = key
        End If

        .Cells(rowNum, 3).Value = inactiveDict(key)
    Next
End With

'Cleanup:
Set activeDict = Nothing
Set inactiveDict = Nothing


End Sub


Sub AddItemToDict(dict As Object, empName As String, state As String)
'since we will use the same methods on both dictionary objects, '
' it would be best to subroutine this action:'
Dim key As Variant

'check to see if this employee already exists'
If UBound(dict.Keys) = -1 Then
    dict.Add empName, state
Else:
    If Not dict.Exists(empName) Then
    'If IsError(Application.Match(empName, dictKeys, False)) Then
        'employee doesn't exist, so add to the dict'
        dict.Add empName, state
    Else:
        'employee does exist, so update the list:'
        'concatenate the state list'
        state = dict(empName) & ", " & state
        'remove the dictionary entry'
        dict.Remove empName
        'add the updated dictionary entry'
        dict.Add empName, state
    End If
End If

End Sub
于 2013-04-01T18:15:44.560 回答