Как создать новые листы на основе списка?

Я пытаюсь создать новые рабочие книги для каждой группы, найденной на листе 10, на основе списка имен групп из другого листа с именем GroupFileNames.

Чтобы упростить устранение неполадок, текущий код создает новые рабочие листы вместо рабочих книг. У меня уже есть код, необходимый для создания книг.

Моя проблема в том, что мой код не будет перебирать список имен групп. Он создает лист для первой группы (ABC Corp) и копирует соответствующие данные, но никогда не создает лист для следующей группы (XYZ Corp).

Я пробовал разные способы зацикливания, используя «До», «Для каждого» и т. д.

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. На каждом новом листе должны быть все столбцы, принадлежащие их группе.

Это список имен групп, которые мой код использует для сравнения с именами групп на Листе 10.

Это можно сделать проще с помощью фильтра.

freeflow 24.12.2020 19:32

Вы называете свою таблицу Excel базой данных. Я думаю, что инструмент, который вам действительно нужен, — это база данных. Вы пытаетесь сделать представления из данных. Не изменяйте данные, чтобы создать представление. Пробовали войти в MS Access?

HackSlash 24.12.2020 20:32
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
2
102
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 выделена после ошибки. Что может быть причиной этой ошибки?

SonicTheHedgeHog 28.12.2020 16:48

Вам нужно добавить ссылку на среду выполнения сценариев Microsoft (Tools.References) или изменить New Scripting.Dictionary на CreateObject("Scripting.Dictionary"). Первый позволяет IntelliSense из-за раннего связывания, второй не предлагает IntelliSense, так как связывается поздно. Если вы новичок в VBA или Scripting.DIctionaries, я бы рекомендовал первый подход.

freeflow 28.12.2020 17:56

Я добавил ссылку на среду выполнения сценариев, как вы советовали, но теперь есть новая ошибка. Ошибка выполнения '91': переменная объекта или переменная блока не установлена. Выделенная строка — это строка 15, которая читается как myWS.Name = myGroup.

SonicTheHedgeHog 28.12.2020 23:00

Используйте окно locals, чтобы посмотреть значения переменных в затронутом методе. Это должно помочь вам понять, что происходит. Код отлично работал на моем ПК с использованием предоставленного вами примера набора данных.

freeflow 29.12.2020 05:23

Я просмотрел ваш код и заметил, что myWs = Nothing. Выданное пришло из публичной функции CreateSheetForGroupName. Переменная myHeadingRow не инициализируется значением. Поэтому оператор If запускается, а затем выходит из функции, устанавливающей myWs = Nothing. Я добавил Set myHeadingRow = ActiveSheet.Range("A1:L1") после объявления, и все работает отлично! БОЛЬШОЕ СПАСИБО за потраченное время и усилия! С НОВЫМ ГОДОМ!

SonicTheHedgeHog 31.12.2020 19:27

Другие вопросы по теме