Excel VBA - 是否可以在多个工作表之间增加索引?(一次递增一行,从每张纸中索引一行)

Excel VBA - Is it possible to increment index across multiple sheets? (incrementing one row at a time, indexing one row from each sheet)

提问人:Carrot 提问时间:9/20/2023 最后编辑:Black catCarrot 更新时间:9/25/2023 访问量:63

问:

我在另一个工作簿中有 4 张纸和一个数据表。我想增加我在 4 张纸中检索的每一行的索引数字,正如您在我插入的图片中看到的那样。(索引一次递增一行,从每张纸中依次索引一行) 这是我的代码,它只能增加工作表中的行。

    Sub IncrementIndexesAcrossSheets()
    Dim ws As Worksheet
    Dim dataRange As Range
    Dim rowIndex As Long
    Dim lastRowIndex As Long
    
    ' Initialize rowIndex to 1
    rowIndex = 1
    
    ' Loop through all sheets in the workbook
    For Each ws In ThisWorkbook.Sheets
        ' Skip sheets without data
        If WorksheetFunction.CountA(ws.Cells) > 0 Then
            ' Set the dataRange to the appropriate column (Column B in this case)
            Set dataRange = ws.Range("B2:B" & ws.Cells(Rows.Count, 2).End(xlUp).Row)
            
            ' Loop through each cell in the dataRange
            For Each cell In dataRange
                ' Set the value of the Index column (Column A) to the current rowIndex
                cell.Offset(0, -1).Value = rowIndex
                ' Increment the rowIndex
                rowIndex = rowIndex + 1
            Next cell
            
            ' Update lastRowIndex with the last used index on the current sheet
            lastRowIndex = rowIndex - 1
        End If
    Next ws
End Sub

以下是示例数据:

enter image description here

这是我想要的输出: 表1:

enter image description here

表2:

enter image description here

表3:

enter image description here

表4:

enter image description here

我是 VBA 的新手,我尝试过搜索多个解决方案,但都归结为在工作表内递增或仅在多个工作表的单元格中递增。请帮忙,因为我真的很想学习如何在 VBA 中编写这样的任务。我之前的问题已经关闭,所以我正在打开一个新问题,更加清晰。

Excel VBA 增量

评论

0赞 Notus_Panda 9/20/2023
你的床单是如何建造的?例如,在 sheet3 中,您希望它是第 9 行,但在示例数据中,第 9 行与“39000 credit”/“AKJ”完全不同?或者它只是遍历您的工作表数量 1 -> 2 -> 3- >等,直到每行都按上述顺序有一个数字?如果工作表 1 有 10 行,而其他工作表只有 5 行怎么办?它是否一直获得 1+4*i 的增量?
0赞 Carrot 9/20/2023
在工作表 3 中,“信用”列通常是样本数据中信用的每个唯一批次的总和。工作表 2 和 3 的工作原理是,它只占用每个唯一批次的第 1 行(在某种程度上表示批次)。工作表 1 基于宏运行,在这种情况下,第 1 次运行时间表示为 1,如果后续运行,则采用上次使用的数字,如果我们假设对宏进行第 2 次运行,它将表示为从工作表 4 最后数据行 49 开始的 50 增量。我不确定这是否能解释。
0赞 FunThomas 9/20/2023
这个问题和 stackoverflow.com/questions/77131596/ 有什么不同吗?
0赞 Carrot 9/20/2023
它被关闭了,我真的被困在这部分。我是新来的,从我所看到的封闭问题来看,没有人能真正回答
0赞 Notus_Panda 9/20/2023
好的,我们很清楚,无论数据来自哪里,它都会进入工作表 1 -> 工作表 2 ->工作表 3 ->工作表 4(并返回步骤 1)。但是,如果任何一张纸的行数较少,那么它是否会转到工作表 1 - >工作表 2 ->工作表 3 ->工作表 1(因为 4 的行数较少)基本上跳过 4,所以你不能应用我提到的“1+4*i”的逻辑?

答:

0赞 tnavidi 9/20/2023 #1

将 rowIndex 初始化为 1 + max(rowIndex) 而不是 1

RowIndex = 1 + WorksheetFunction.Max(Worksheets(1).Range("A:A"), Worksheets(2).Range("A:A"), Worksheets(3).Range("A:A"), Worksheets(4).Range("A:A"))

在开始(循环之前)和循环中使用RowIndex = RowIndex + 1

1赞 Notus_Panda 9/20/2023 #2

我确信有一种不那么复杂的方法可以做到这一点,但这是我的尝试,没有考虑到您的手动编辑,该编辑在行号背后没有逻辑。

这将检查行索引的总数是多少,并遍历(有用的)工作表,直到达到行总数。

Sub IncrementIndexesAcrossSheets()
    Dim ws As Worksheet, shIndex As Long, totalShts As Long
    Dim rowIndex As Long, totalRows As Long, lRow As Long
    Dim dict As Object
    
    With ThisWorkbook
        totalShts = .Sheets.Count
        Set dict = CreateObject("Scripting.Dictionary")
        ' Loop through all sheets in the workbook
        For Each ws In .Sheets
            shIndex = shIndex + 1
            ' Skip sheets without data
            If WorksheetFunction.CountA(ws.Cells) > 0 Then
                ' Set the dataRange to the appropriate column (Column B in this case)
                totalRows = totalRows + ws.Cells(Rows.Count, 2).End(xlUp).Row - 1 'taking account for headers
            End If
            dict(shIndex) = shIndex 'adding the sheet indexes to a dictionary to keep track which ones
                                    'are to be used without having to recheck
        Next ws
        shIndex = 1
        Do While rowIndex < totalRows
            If Not dict.Exists(shIndex) Then 'Don't want to accidentally add it with that weird dictionary "bug"
            Else
                With .Sheets(shIndex)
                    lRow = .Range("A" & Rows.Count).End(xlUp).Row
                    If .Range("A" & lRow).Offset(1, 1) <> "" Then
                        rowIndex = rowIndex + 1
                        .Range("A" & lRow).Offset(1).Value = rowIndex
                    Else
                        dict.Remove shIndex 'sheet is all filled out
                    End If
                End With
            End If
            shIndex = shIndex + 1
            If shIndex > totalShts Then shIndex = 1 'don't go over the Sheets.Count
        Loop
    End With
End Sub

如果实际上有任何具体的逻辑可以使它在 sheet4 上为 4-> 7,我将尝试实现它。

编辑:在与 OP 来回一番之后,得到了一些逻辑来实现 sheet4 上的延续,然后再使用分布号返回其原始顺序:

Sub IncrementIndexesAcrossSheets()
    Dim ws As Worksheet, shIndex As Long, totalShts As Long
    Dim rowIndex As Long, totalRows As Long, lRow As Long
    Dim dict As Object
    Dim distriNum
    
    With ThisWorkbook
        totalShts = .Sheets.Count
        Set dict = CreateObject("Scripting.Dictionary")
        ' Loop through all sheets in the workbook
        For Each ws In .Sheets
            shIndex = shIndex + 1
            ' Skip sheets without data
            If WorksheetFunction.CountA(ws.Cells) > 0 Then
                ' Set the dataRange to the appropriate column (Column B in this case)
                totalRows = totalRows + ws.Cells(Rows.Count, 2).End(xlUp).Row - 1 'taking account for headers
            End If
            distriNum = Application.Match("Distribution Number*", ws.Rows(1), 0)
            If IsError(distriNum) Then distriNum = 0 'If it is 0 = no Distribution Number, otherwise column number
            dict(shIndex) = distriNum 'adding the sheet indexes to a dictionary to keep track which ones
                                    'are to be used without having to recheck
        Next ws
        shIndex = 1
        Do While rowIndex < totalRows
            If Not dict.Exists(shIndex) Then 'Don't want to accidentally add it with that weird dictionary "bug"
            Else
                With .Sheets(shIndex)
                    lRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
                    distriNum = dict(shIndex)
                    If .Range("A" & lRow).Offset(0, 1) <> "" Then
                        Do While distriNum > -1
                            rowIndex = rowIndex + 1
                            .Range("A" & lRow).Value = rowIndex
                            If distriNum = 0 Then
                                distriNum = -1
                            ElseIf .Cells(lRow + 1, distriNum).Value = 1 Or .Cells(lRow + 1, distriNum).Value = "" Then
                                distriNum = -1
                            Else
                                lRow = lRow + 1
                            End If
                        Loop
                    Else
                        dict.Remove shIndex 'sheet is all filled out
                    End If
                End With
            End If
            shIndex = shIndex + 1
            If shIndex > totalShts Then shIndex = 1 'don't go over the Sheets.Count
        Loop
    End With
End Sub

现在,这将检查工作表中是否有带有“分发编号”的列,并继续处理该工作表,直到下一个分发编号变回 1 并从那里向前移动。使用预先存在的字典传递分布逻辑的可能列号。

评论

0赞 Carrot 9/25/2023
在业务上下文中,有提供者和接收者。因为前 2 行是有关提供程序的信息,接下来的 2 行是接收器。我被告知一些接收者没有输入他们的帐户信息,这就是为什么有重复的原因。但是,如果您仔细观察,重复的行会切换值(借方 ->贷方和帐户第 1 个值和第 5 个值)。由于 4 行仍在相同的批号 1 中,因此该编号被标记为 4 -> 7。然后,这将对每个批次进行。希望这个解释有所帮助。
0赞 Notus_Panda 9/25/2023
我确实在您编辑的行中看到了切换值,但我没有看到根据提供者/接收者正确自动执行输出的方法,您如何查看哪个是哪个,什么去哪里等。
0赞 Carrot 9/25/2023
代码是否有可能检测到分发编号然后在其中递增?由于每个批次从分发编号的 1 开始。
0赞 Notus_Panda 9/25/2023
嗯,所以我们需要在标题中搜索“分发号”,如果找到,请考虑这一点。它会一直这样称呼吗?
0赞 Carrot 9/25/2023
是的,它将是那个标题。