【问题标题】:How to create new sheets based on list?如何根据列表创建新工作表?
【发布时间】:2020-12-24 18:14:31
【问题描述】:

我正在尝试根据另一个名为 GroupFileNames 的工作表中的组名列表为 sheet10 中找到的每个组创建新工作簿。

为了更轻松地进行故障排除,当前代码会创建新工作表而不是工作簿。我已经有了创建工作簿所需的代码。

我的问题是我的代码不会遍历组名列表。它为第一组 (ABC Corp) 创建一个工作表并复制其相应的数据,但它从不为下一个组 (XYZ Corp) 创建工作表。

我尝试了使用 Do Until、For Each 等不同的循环方式。

Sub CreateWkBookByGroupName()
    
    
    Dim Transaction() As Variant
    Dim GroupNameTransactions() As Variant
    Dim TransactionCounter As Long
    Dim GpnTransactionCounter As Long
    Dim Counter As Long
    Dim i As Integer
    Dim gfn As Worksheet
    Set gfn = ThisWorkbook.Sheets("GroupFileNames")
    Dim groupName As String
    
    
    i = 1
    groupName = gfn.Range("A" & i)
    
    'Store entire database in the Transaction array
    Transaction = Range("A1").CurrentRegion
    'Starting in the i row of the database loop through each transaction
    
    For TransactionCounter = i To UBound(Transaction, 1)
       
        'If the thirteenth column contains a value equal to groupName...
        If Transaction(TransactionCounter, 13) = groupName Then
            '...increase the GpnTransactionCounter by 1
            GpnTransactionCounter = GpnTransactionCounter + 1
            
            'Redimension the GroupNameTransaction array with each instance _
            of a GroupName transaction.
            ReDim Preserve _
              GroupNameTransactions(1 To 13, 1 To GpnTransactionCounter)
            'Start a counter to populate the GroupNameTransactions array
            For Counter = 1 To 13
                'The GroupNameTransactions array equals the current transaction
                GroupNameTransactions(Counter, GpnTransactionCounter) _
                  = Transaction(TransactionCounter, Counter)
            Next Counter
        End If
    Next TransactionCounter
    'Add a new sheet
    Worksheets.Add
    'Add the headings in the first row of the Transactions array
    Range("A1:M1") = Transaction
    'Transpose the GroupNameTransaction array onto the new sheet
    Range("A2", Range("A2").Offset(GpnTransactionCounter - 1, 12)) _
    = Application.Transpose(GroupNameTransactions)
    'Autofit columns
    Columns.AutoFit
    
End Sub

此数据应生成两个新工作表,一个用于 ABC Corp,另一个用于 XYZ Corp。每个新工作表都应包含属于其组的所有列。

这是我的代码用来与 Sheet10 上的组名进行比较的组名列表。

【问题讨论】:

  • 使用过滤器可以更轻松地完成。
  • 您将 Excel 表称为数据库。我认为您真正需要的工具是数据库。您正在尝试从数据中创建视图。不要更改数据以创建视图。您是否尝试过访问 MS Access?

标签: excel vba


【解决方案1】:

如果您确实需要创建作为分组数据子集的新工作表,那么嵌套脚本字典是一种有用的数据结构。

Option Explicit

Sub CreateWkBookByGroupName()

    Dim myTransactionsGroupedByName As Scripting.Dictionary
    Set myTransactionsGroupedByName = PopulateTransactionsByGroupName
    
    Dim myGroup As Variant
    Dim myWS As Excel.Worksheet
    For Each myGroup In myTransactionsGroupedByName
    
        With myTransactionsGroupedByName
        
            Set myWS = CreateSheetForGroupName(.Item(myGroup))
            myWS.Name = myGroup
        End With
        
    Next
    
End Sub


Public Function CreateSheetForGroupName(ByVal NamedGroup As Scripting.Dictionary) As Excel.Worksheet

    Static myHeadingRow As Excel.Range
    
    If myHeadingRow Is Nothing Then
    
        Set myHeadingRow = NamedGroup.Item(0)
        Set CreateSheetForGroupName = Nothing
        Exit Function
        
    End If
    
    Dim myWS As Excel.Worksheet
    Set myWS = ThisWorkbook.Worksheets.Add
    
    myWS.Range("A1").Value = myHeadingRow
    myHeadingRow.Copy Destination:=myWS.Range("A1")
    Dim myTransaction As Variant
    For myTransaction = 0 To NamedGroup.Count - 1
    
        NamedGroup(myTransaction).Copy Destination:=myWS.Range("A" & CStr(myTransaction + 2))
    
    Next
    
    Set CreateSheetForGroupName = myWS
    
End Function


Public Function PopulateTransactionsByGroupName() As Scripting.Dictionary

    Const GroupNameColumn As Long = 13 'Column number for Group Names
    Dim myTransaction As Variant
    
    Dim myGroupedByName As Scripting.Dictionary
    Set myGroupedByName = New Scripting.Dictionary
    For Each myTransaction In Range("A1").CurrentRegion.Rows
    
        Dim GroupName As String
        GroupName = myTransaction.Columns(GroupNameColumn).Cells(1, 1).Value
        
        With myGroupedByName
        
            If Not .exists(GroupName) Then
            
                ' First entry will be the heading rows with a key of "GroupName"
                .Add GroupName, New Scripting.Dictionary
                
            End If
            
            With .Item(GroupName)
            
                .Add .Count, myTransaction
                
            End With
        
        End With
    
    Next
    
    Set PopulateTransactionsByGroupName = myGroupedByName
    
End Function

【讨论】:

  • 感谢您的回复。当我尝试运行您的代码时,我收到编译错误:未定义用户定义的类型。错误后突出显示带有 Public Function CreateSheetForGroupName(ByVal NamedGroup As Scripting.Dictionary) As Excel.Worksheet 的行。什么可能导致此错误?
  • 您需要添加对 Microsoft Scripting Runtime (Tools.References) 的引用或将 New Scripting.Dictionary 更改为 CreateObject("Scripting.Dictionary")。前者由于早期绑定而允许智能感知,后者不提供智能感知,因为它是后期绑定如果您是 VBA 或 Scripting.DIctionaries 的新手,我会推荐前一种方法。
  • 我按照您的建议添加了脚本运行时参考,但现在出现了一个新错误。运行时错误“91”:对象变量或未设置块变量。突出显示的行是第 15 行,内容为 myWS.Name = myGroup.
  • 使用本地窗口查看受影响方法中的变量值。这应该可以帮助您了解正在发生的事情。使用您提供的示例数据集,该代码在我的 PC 上运行良好。
  • 我浏览了您的代码并注意到 myWs = Nothing。发出来自公共函数 CreateSheetForGroupName。 myHeadingRow 变量未使用值初始化。因此,If 语句运行然后退出设置 myWs = Nothing 的函数。我在声明后添加了 Set myHeadingRow = ActiveSheet.Range("A1:L1") ,一切正常!非常感谢您付出的所有时间和精力!新年快乐!
猜你喜欢
  • 2016-02-12
  • 2022-12-18
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 2023-02-14
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多