【问题标题】:Mapping table with multiple items具有多个项目的映射表
【发布时间】:2021-09-07 18:33:36
【问题描述】:

我有一个映射表,用于匹配两个单独工作表(Sheet1 和 Sheet2)的标题。 但是如果我有这样的东西(左侧 3 列,右侧 2 列)怎么办:

  • 基本上我希望 POS1 2019 EMP1 等于 HR DEPARTMAENT Employee1 等等。 Sheet1, Sheet2, Mapping 有什么想法我该怎么做? 先感谢您! :)

     Public Sub test()
       Application.ScreenUpdating = False
       stack "Sheet1", "Sheet2", "Mapping"
       Application.ScreenUpdating = True
     End Sub
     Public Sub stack(ByVal Sheet1 As String, ByVal Sheet2 As String, ByVal 
     Mapping As String)
     Dim rng As Range, trgtCell As Range, src As Worksheet, trgt As 
     Worksheet, helper As Worksheet
    
     Dim rngSrc As Range, rngDest As Range
     Dim sht As Worksheet
    
     Set src = Worksheets("Sheet1")
     Set trgt = Worksheets("Sheet2")
     Set helper = Worksheets("Mapping")
    
     With src
         For Each rng In Intersect(.Rows(3), .UsedRange).SpecialCells(xlCellTypeConstants)
             Dim lkup As Variant
             With helper
                 lkup = Application.VLookup(rng.Value, .Range("D13:E" & .Cells(.Rows.Count, "D").End(xlUp).Row), 2, False)
             End With
             If Not IsError(lkup) Then
    
             Set trgtCell = trgt.Range("$B$2:$F$7").Find(lkup, LookIn:=xlValues, lookat:=xlWhole)
    
             If Not trgtCell Is Nothing Then
                 .Range(rng.Offset(1), .Cells(.Rows.Count, rng.Column).End(xlUp)).Copy
                 With trgt
                     .Range(Split(trgtCell.Address, "$")(1) & 3).PasteSpecial
                 End With
             End If
         End If
     Next rng
    

    结束于 结束子

【问题讨论】:

  • 我无法理解您的问题,抱歉。我读了两遍,但仍然不清楚。您能解释一下(用语言映射是什么意思吗?我记得我可以从您那里看到另一个类似情况的问题,我问为什么要使用带有参数的Sub,因为您没有使用任何参数。上面的代码是你自己写的,还是你从网上弄来的,不太了解它的工作原理?
  • @FaneDuru 你好!对不起,我的解释很糟糕,我是新手。这是来自互联网的代码,但我已经根据我的情况对其进行了调整。好吧,我有两张纸,每张纸都有一个带有标题的不同表格(但标题是由 3 或 2 个单元格垂直组成的,看起来像另一个小表格),我想匹配它们,并将标题下方的值从 Sheet2 复制到 Sheet1 .假设工作表 1 有一个表,其标题来自 B1:F3。和表 2,B1:F2。我想使用映射表将 B1:F3 (Sheet1) 与 B1:F2(Sheet2) 匹配。还不清楚吗?
  • 也许我很累,但仍然不清楚(对我来说......)。如果您将编辑您的问题并发布另一张显示您想要完成的图片,我可能会理解它......
  • 完成。我已经在这两张纸上添加了一些带有表格的图片

标签: vba dictionary header mapping match


【解决方案1】:

请尝试下一个修改后的代码。

Public Sub test()
  Application.ScreenUpdating = False
   stack "Sheet1", "Sheet2", "Mapping"
  Application.ScreenUpdating = True
End Sub

Public Sub stack(ByVal Sheet1 As String, ByVal Sheet2 As String, ByVal Mapping As String)
Dim rng As Range, trgtCell As Range, src As Worksheet, trgt As Worksheet, helper As Worksheet
            
Dim rngSrc As Range, rngDest As Range
Dim sht As Worksheet
            
Set src = Worksheets(Sheet1)
Set trgt = Worksheets(Sheet2)
Set helper = Worksheets(Mapping)
        
With src
    For Each rng In Intersect(.Rows(3), .UsedRange).SpecialCells(xlCellTypeConstants)
        Dim lkup As Variant

        With helper
            lkup = Application.VLookup(rng.Value, .Range("C2:E" & .Cells(.Rows.Count, "C").End(xlUp).Row), 3, False)
        End With
        If Not IsError(lkup) Then
                    
            Set trgtCell = trgt.Range("$B$2:$F$7").Find(lkup, LookIn:=xlValues, lookat:=xlWhole)
             Debug.Print trgtCell.Address
            If Not trgtCell Is Nothing Then
                With trgt
                    .Range(trgtCell.Offset(1), .Cells(.Rows.Count, trgtCell.Column).End(xlUp)).Copy
                End With
                .Range(Split(trgtCell.Address, "$")(1) & 4).PasteSpecial
           End If
        End If
    Next rng
End With
End Sub

请同时更正调用第二个的子。你在那里混合了“Shee2”和“Sheet1”......

请进行测试并发送一些反馈。

【讨论】:

  • 是的,这不是我真正需要的。这是工作簿drive.google.com/file/d/1fitQqjw2snOYlxzxXsL29oEmXwLLPVQJ/… 的链接,如果您有时间看一看,我很感激。我把宏放在那里,这样你就可以运行它了。
  • 我的代码仅适用于只有 2 列的映射表。但我希望它与其他具有多列的映射表(A1:E6)一起使用:)。我真的希望现在更清楚了
  • @Dodoi 你给我发了什么?您没有发送您要处理的工作簿吗?如果我看不到这些多列包含的内容,如何帮助您做一些我无法理解的事情?现在我要离开我的办公室了。当我在家时,我会看看你的真实工作簿。假设您将发送另一个...
  • 我再次编辑了我的帖子。我在整个 Sheet1、Sheet2 和 Mapping Sheet 中放了一些图片,您也可以使用适用于小型映射表的代码。我将我的工作簿放在云端硬盘中,以便您可以通过该链接访问它。我给了你许可,所以我真的不知道为什么它不起作用。再次感谢您
  • 我现在正在开车。几个小时后,我会在家时发布答案。
【解决方案2】:

我认为字典是最适合这类问题的数据结构。 请注意,要在 VBA 中使用字典,您需要设置对脚本运行时库的引用。

工具->参考-> Microsoft Scripting Runtime

下面是一些适用于您提供的示例的代码:

Public Sub test()
  Application.ScreenUpdating = False
  stack2 "Sheet1", "Sheet2", "Mapping"
  Application.ScreenUpdating = True
End Sub


Public Sub stack(ByVal Sheet1 As String, ByVal Sheet2 As String, ByVal Mapping As String)
Dim rng As Range, src As Worksheet, trgt As Worksheet, helper As Worksheet
Dim sht As Worksheet
Dim dctCol As Dictionary, dctHeader As Dictionary
Dim strKey1 As String, strKey2 As String
Dim strItem As String, col As Integer

Set src = Worksheets(Sheet1)
Set trgt = Worksheets(Sheet2)
Set helper = Worksheets(Mapping)
        
'build a dictionary to lookup column based on 3 rows of headers
Set dctCol = New Dictionary
arr1 = src.Range("A1:F7") 'arrays are way faster than ranges
For j = 2 To UBound(arr1, 2) 'loop over data from columns B-F
    strKey1 = Trim(arr1(1, j)) & "," & Trim(arr1(2, j)) & "," & Trim(arr1(3, j)) 'comma delimit string
    dctCol(strKey1) = j 'j is the column number
Next

'build a dictionary to translate 2 headers to 3 headers
Set dctHeader = New Dictionary
arrHelp = helper.Range("A2:E6")
For i = 1 To UBound(arrHelp)
    strKey2 = Trim(arrHelp(i, 4)) & "," & Trim(arrHelp(i, 5)) '2 header key
    strItem = Trim(arrHelp(i, 1)) & "," & Trim(arrHelp(i, 2)) & "," & Trim(arrHelp(i, 3))
    dctHeader(strKey2) = strItem
Next

'update sheet2 with numbers from sheet1
arr2 = trgt.Range("A1:F6")
For j = 2 To 5
    'work backwards to find the column
    strKey2 = Trim(arr2(1, 2)) & "," & Trim(arr2(2, j)) '2 headers
    strKey1 = dctHeader(strKey2)
    col = dctCol(strKey1)
    
    'update the data for arr2
    For i = 3 To 6
        arr2(i, j) = arr1(i + 1, col)
    Next
Next

'write it back to spreadsheet
trgt.Range("M10").Resize(UBound(arr2), UBound(arr2, 2)) = arr2
End Sub

【讨论】:

  • 哇,这太完美了!也感谢 cmets,他们真的很有帮助。我很难解释这一点。现在我只需要弄清楚如何使行标题也可以使用,因为这两个月已经切换。但是你一直很有帮助。再次感谢楼主
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多