Excel宏-查找源的决策

Excel宏-查找源的决策,excel,vba,Excel,Vba,仍然不是很好的VBA,正在努力学习。问题是我是否应该创建一个带有TypeArray项的用户表单,询问他们哪些项转到哪个端口摘要标题,然后创建一个新的TypeArray,或者只是试着让程序以某种方式重新配置自己,以及如何重新配置 我从大量的CSV文件中获得了这些数据这是一个片段,实际包含60-250行,以及5个或更多标记列-我们将此范围称为1: ╔════════════════════════════════╦══════════════════╦══════════════╦═════════

仍然不是很好的VBA,正在努力学习。问题是我是否应该创建一个带有TypeArray项的用户表单,询问他们哪些项转到哪个端口摘要标题,然后创建一个新的TypeArray,或者只是试着让程序以某种方式重新配置自己,以及如何重新配置

我从大量的CSV文件中获得了这些数据这是一个片段,实际包含60-250行,以及5个或更多标记列-我们将此范围称为1:

╔════════════════════════════════╦══════════════════╦══════════════╦══════════════════╦══════════════╦══════════════════╦══════════════╗ ║ CSV File Name ║ Marker 1 ft/freq ║ Marker 1 dBm ║ Marker 2 ft/freq ║ Marker 2 dBm ║ Marker 3 ft/freq ║ Marker 3 dBm ║ ╠════════════════════════════════╬══════════════════╬══════════════╬══════════════════╬══════════════╬══════════════════╬══════════════╣ ║ TestSite_ALPHA_850_1_DTFL.csv ║ 113.82 ║ (42.88) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_1_DTFS.csv ║ 113.82 ║ (43.96) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_1_DTFWS.csv ║ 113.82 ║ (12.72) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_1_RLL.csv ║ 824.04 ║ (31.87) ║ 848.97 ║ (34.09) ║ 869.04 ║ (30.19) ║ ║ TestSite_ALPHA_850_1_RLS.csv ║ 824.04 ║ (23.49) ║ 848.97 ║ (22.61) ║ 869.04 ║ (23.86) ║ ║ TestSite_ALPHA_850_1_RLWS.csv ║ 824.04 ║ (3.43) ║ 848.97 ║ (3.44) ║ 869.04 ║ (3.53) ║ ║ TestSite_ALPHA_850_1_DTFL.csv ║ 113.82 ║ (42.88) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_2_DTFS.csv ║ 113.82 ║ (43.96) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_2_DTFWS.csv ║ 113.82 ║ (12.72) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_ALPHA_850_2_RLL.csv ║ 824.04 ║ (31.87) ║ 848.97 ║ (34.09) ║ 869.04 ║ (30.19) ║ ║ TestSite_ALPHA_850_2_RLS.csv ║ 824.04 ║ (23.49) ║ 848.97 ║ (22.61) ║ 869.04 ║ (23.86) ║ ║ TestSite_ALPHA_850_2_RLWS.csv ║ 824.04 ║ (3.43) ║ 848.97 ║ (3.44) ║ 869.04 ║ (3.53) ║ ║ TestSite_BETA_850_1_DTFL.csv ║ 113.82 ║ (42.88) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_BETA_850_1_DTFS.csv ║ 113.82 ║ (43.96) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_BETA_850_1_DTFWS.csv ║ 113.82 ║ (12.72) ║ N/A ║ N/A ║ N/A ║ N/A ║ ║ TestSite_BETA_850_1_RLL.csv ║ 824.04 ║ (31.87) ║ 848.97 ║ (34.09) ║ 869.04 ║ (30.19) ║ ║ TestSite_BETA_850_1_RLS.csv ║ 824.04 ║ (23.49) ║ 848.97 ║ (22.61) ║ 869.04 ║ (23.86) ║ ║ TestSite_BETA_850_1_RLWS.csv ║ 824.04 ║ (3.43) ║ 848.97 ║ (3.44) ║ 869.04 ║ (3.53) ║ ╚════════════════════════════════╩══════════════════╩══════════════╩══════════════════╩══════════════╩══════════════════╩══════════════╝ 我从CSV文件名值的末尾获取以下测试类型,并将它们分配给TypeArray。测试类型可能存在一些差异,例如,称为RLS的测试类型可能是RL短的:

╔══════╦══════╦═══════╦═════╦═════╦══════╗ ║ DTFL ║ DTFS ║ DTFWS ║ RLL ║ RLS ║ RLWS ║ ╚══════╩══════╩═══════╩═════╩═════╩══════╝ 我还创建了一个唯一端口的PortArray减去TypeArray值和.csv-一个PortArray,例如TestSite_ALPHA_850_1、TestSite_ALPHA_850_2、TestSite_Beta_850_1等-请参见底部的图片

我的问题涉及到如何计算下一部分:我需要将上述数据汇总为以下内容-我们称之为Range2:

╔══════════════════════╦══════════╦═════════╦═════════╦═══════════╦═══════════╦═══════════╦═══════════╦════════╦════════╦═════════╗ ║ Port ║ DTFWS PK ║ DTFL PK ║ DTFS PK ║ RLL RX PK ║ RLL TX PK ║ RLS RX PK ║ RLS TX PK ║ RWS PK ║ RWS VY ║ RWS TTL ║ ╠══════════════════════╬══════════╬═════════╬═════════╬═══════════╬═══════════╬═══════════╬═══════════╬════════╬════════╬═════════╣ ║ TestSite_ALPHA_850_1 ║ (12.72) ║ (42.88) ║ (43.96) ║ (34.09) ║ (30.19) ║ (22.61) ║ (23.86) ║ (3.44) ║ (3.53) ║ 3.49 ║ ║ TestSite_ALPHA_850_2 ║ (12.78) ║ (43.42) ║ (43.58) ║ (33.89) ║ (29.33) ║ (22.73) ║ (23.45) ║ (2.55) ║ (2.90) ║ 4.33 ║ ║ TestSite_BETA_850_1 ║ (12.51) ║ (42.59) ║ (43.77) ║ (33.50) ║ (29.67) ║ (22.26) ║ (23.12) ║ (2.45) ║ (3.23) ║ 4.24 ║ ║ TestSite_BETA_850_2 ║ (12.26) ║ (42.74) ║ (43.50) ║ (33.68) ║ (29.52) ║ (21.81) ║ (23.24) ║ (3.29) ║ (2.95) ║ 3.79 ║ ║ TestSite_GAMMA_850_1 ║ (12.06) ║ (42.78) ║ (43.74) ║ (33.10) ║ (29.61) ║ (22.21) ║ (23.13) ║ (2.86) ║ (2.82) ║ 4.34 ║ ║ TestSite_GAMMA_850_2 ║ (12.51) ║ (42.79) ║ (43.79) ║ (33.11) ║ (29.60) ║ (22.59) ║ (23.68) ║ (3.10) ║ (3.37) ║ 3.90 ║ ╚══════════════════════╩══════════╩═════════╩═════════╩═══════════╩═══════════╩═══════════╩═══════════╩════════╩════════╩═════════╝ 注意:RWS标题对应于本例中的RLWS测试类型-Range2标题不会有太大变化,但测试类型值名称可能会有变化

我使用带有6种测试类型的TypeArray和PortArray来填写端口摘要区域,我需要:

循环遍历Range2中的每个端口行 循环浏览Range2标头中每个端口的每列 在Range1 CSV文件名中搜索与PortArray匹配的文件&_& 类型数组 根据范围2中的航向拉动: 标记1 dbm列的值或 标记2 dbm列的值或 标记3 dbm列的值或 标记2 dbm列的值+标记3 dbm列的值除以-2 我挂断了第3步,不知道如何确保我的TypeArray被分配到正确的端口摘要标题,以确保它们没有无序-例如,如果Range1中的文件名不是alpha顺序怎么办?我的TypeArray从该列表中自上而下填充,可以是RLL、RLS、RLWS、DTFL等,而我的Range2标题保持不变,我如何使用相同的数组项两次-即在转到RLS之前使用TypeArray项RLL查找Range2标题项RLL RX和RLL TX

当前示例图像:

我使用以下方法创建Range2:

Function FillSummary()
Dim i As Integer
Dim lastrow As Integer
Dim rowSrc As Integer, colSrc As Integer 'These variables hold the row/column number for getting data
    rowSrc = 1
    colSrc = 1
Dim rowDest As Integer, colDest As Integer ' These variables hold the row/column number for data entry
    colDest = 1
Dim rngSrc As Range, rngDest As Range 'These variables hold where the info is copied from/pasted to
'=======================
Dim tmpPort As String, tmpSweep As String, trimPort As String, trimSweep As String
Dim portArr() As String
Dim sweepArr() As String
Dim swpHeadArr() As Variant
    swpHeadArr() = Array("DTFWS PK", "DTFL PK", "DTFS PK", "RLL RX PK", "RLL TX PK", _
        "RLS RX PK", "RLS TX PK", "RWS PK", "RWS VY", "RWS TTL")
'=========================================================

    'Find the last row of sweep data ======================
    With ActiveSheet 'find and set the location of the last row of sweep files
        lastrow = .Cells(.Rows.Count, "A").End(xlUp).row
    End With
    Set rngSrc = Range(Cells(1, 1), Cells(lastrow, 1)) 'Set the range for our source to include all sweep files
    rowDest = lastrow + 2 'make our "rowSrc" variable one down from the last row of data
    '======================================================
    'Fill out the fields for our header info
    Cells(rowDest, colDest).Value = "Port"
    For i = LBound(swpHeadArr) To UBound(swpHeadArr)
        colDest = colDest + 1 'increment column for sweep headers
        Cells(rowDest, colDest).Value = swpHeadArr(i) 'input the sweep header value
    Next  'increment next array item and loop
    '===================
    'Format the header row
    Set rngDest = Range(Cells(rowDest, 1), Cells(rowDest, colDest))
        With rngDest
            .HorizontalAlignment = xlCenter
            .Font.Bold = True
            .Font.Size = 12
            .Interior.ThemeColor = xlThemeColorDark1
            .Interior.TintAndShade = -0.249977111117893
        End With
        '===============
        'Ensure the colum widths for sweeps are "11" (readable)
        Set rngDest = Range(Cells(rowDest, 3), Cells(rowDest, colDest))
        With rngDest
            .EntireColumn.ColumnWidth = 11
        End With

    '======================================================
    'Start populating the arrays with each line/port & sweep type so it can be entered below
    For Each cell In rngSrc
        If Right(cell, 4) = ".csv" Then 'if the cell contains sweep data identified by ".csv" file type
            trimPort = Left(cell, InStrRev(cell, "_") - 1) 'will cut off sweep type & "_" before it
            trimSweep = Mid(cell, InStrRev(cell, "_") + 1, InStr(cell, ".csv") - 1 _
                - Len(Left(cell, InStrRev(cell, "_")))) 'will cut out everything but the sweep type
            ' ^^^^^^^^^^
            ' basically, take the middle of the cell starting at the last "_",
            ' for a length equal to position in the cell of ".csv", minus 1, minus
            ' the length of the cell contents to the point of the last "_"
            '===========
                'If (cell <> "") And (InStr(temp, cell) = 0) Then 'empty cell error handling
                If (InStr(tmpPort, trimPort) = 0) Then 'if the stuff we trimmed above doesn't equal our temp string
                  tmpPort = tmpPort & trimPort & "|" 'then add that stuff to our temp string with a delimiter
                End If
                If (InStr(tmpSweep, trimSweep) = 0) Then 'if the stuff we trimmed above doesn't equal our temp string
                  tmpSweep = tmpSweep & trimSweep & "|" 'then add that stuff to our temp string with a delimiter
                End If

         End If
    Next cell
    '===================
    'Write the strings "tmpPort" & "tmpSweep" gathered above into our arrays
    If Len(tmpPort) > 0 Then tmpPort = Left(tmpPort, Len(tmpPort) - 1)
    portArr = Split(tmpPort, "|")
    If Len(tmpSweep) > 0 Then tmpSweep = Left(tmpSweep, Len(tmpSweep) - 1)
    sweepArr = Split(tmpSweep, "|")
    '===================
    'Start filling in cells in column "A" with ports from the port array
    rowDest = rowDest + 1
    colDest = 1
    For i = LBound(portArr) To UBound(portArr)
        Cells(rowDest, 1).Value = portArr(i) 'input the marker value
        rowDest = rowDest + 1 'increment column for markers
    Next  'increment next array item and loop

    '======================================================
    'Here is where I would search for each port's sweep info 
    'and plug it into the appropriate column in Range2
    '======================================================

End Function

将数据加载到已经完成的Range1和Range2之后,可以使用Vlookup从Range1返回标记信息。例如,如果您要将其放入示例中的单元格B40中:

=VLOOKUP($A40 & "_" & LEFT(B$39,FIND(" ",B$39)-1) & ".csv", $A$18:$M$37, 3, FALSE)
VLookup中的第三个参数是列,因此在本例中,将从第三列返回值:Marker 1 dBm。
您的第4步并不具体,但您可以更改第三个参数,以适合您希望从哪个列获取数据。

我对此进行了相当多的处理,而我的主Sub调用的函数的整个部分对我来说仍然非常非常笨拙-我非常感谢任何注释/mail/IM,以使其不那么不稳定

我为回答我的问题而添加的内容在“新建”部分

    Function FillSummary()
    Dim i As Integer, j As Integer
    Dim lastrow As Integer
    Dim rowSrc As Integer, colSrc As Integer 'These variables hold the row/column number for getting data
        rowSrc = 1
        colSrc = 1
    Dim rowDest As Integer, colDest As Integer ' These variables hold the row/column number for data entry
        colDest = 1
    Dim rngSrc As Range, rngDest As Range 'These variables hold where the info is copied from/pasted to
    '=======================
    Dim tmpPort As String, tmpSweep As String, trimPort As String, trimSweep As String
    Dim portArr() As String
    Dim sweepArr() As String
    Dim swpHeadArr() As Variant
        swpHeadArr() = Array("DTFWS PK", "DTFL PK", "DTFS PK", "RLL RX PK", "RLL TX PK", _
            "RLS RX PK", "RLS TX PK", "RLWS PK", "RLWS VY", "RLWS TTL") 'Had to change RWS with RLWS to match CSV names
    Dim markColArr() As Variant
        markColArr() = Array(3, 4, 4, 12, 14, 12, 14, 4, 6, 6) 'Tells where to find the value of each test type
    Dim headColRng As Range 'hold the header columns
    Dim swpHead As String 'hold the type of test from the current column's header in the summary area
    Dim arrPos As Integer 'to hold the value of the position of the array item when we look it up
    Dim lookupRng As Range 'to hold the position of our CSV file name find
    '=========================================================

        'Find the last row of sweep data ======================
        With ActiveSheet 'find and set the location of the last row of sweep files
            lastrow = .Cells(.Rows.Count, "A").End(xlUp).row
        End With
        Set rngSrc = Range(Cells(1, 1), Cells(lastrow, 1)) 'Set the range for our source to include all sweep files
        rowDest = lastrow + 2 'make our "rowDest" variable one down from the last row of data
        '======================================================
        'Fill out the fields for our header info
        Cells(rowDest, colDest).Value = "Port"
        For i = LBound(swpHeadArr) To UBound(swpHeadArr)
            colDest = colDest + 1 'increment column for sweep headers
            Cells(rowDest, colDest).Value = swpHeadArr(i) 'input the sweep header value
        Next  'increment next array item and loop
        '===================
        'Format the header row
        Set headColRng = Range(Cells(rowDest, 1), Cells(rowDest, colDest))
            With headColRng
                .HorizontalAlignment = xlCenter
                .Font.Bold = True
                .Font.Size = 12
                .Interior.ThemeColor = xlThemeColorDark1
                .Interior.TintAndShade = -0.249977111117893
            End With
            '===============
            'Ensure the colum widths for sweeps are "11" (readable)
            Set headColRng = Range(Cells(rowDest, 3), Cells(rowDest, colDest))
            With headColRng
                .EntireColumn.ColumnWidth = 11
            End With
        Set headColRng = Range(Cells(rowDest, 2), Cells(rowDest, colDest))

        '======================================================
        'Start populating the arrays with each line/port & sweep type so it can be entered below
        For Each cell In rngSrc
            If Right(cell, 4) = ".csv" Then 'if the cell contains sweep data identified by ".csv" file type
                trimPort = Left(cell, InStrRev(cell, "_") - 1) 'will cut off sweep type & "_" before it
                trimSweep = Mid(cell, InStrRev(cell, "_") + 1, InStr(cell, ".csv") - 1 _
                    - Len(Left(cell, InStrRev(cell, "_")))) 'will cut out everything but the sweep type
                ' ^^^^^^^^^^
                ' basically, take the middle of the cell starting at the last "_",
                ' for a length equal to position in the cell of ".csv", minus 1, minus
                ' the length of the cell contents to the point of the last "_"
                '===========
                    'If (cell <> "") And (InStr(temp, cell) = 0) Then 'empty cell error handling
                    If (InStr(tmpPort, trimPort) = 0) Then 'if the stuff we trimmed above doesn't equal our temp string
                      tmpPort = tmpPort & trimPort & "|" 'then add that stuff to our temp string with a delimiter
                    End If
                    If (InStr(tmpSweep, trimSweep) = 0) Then 'if the stuff we trimmed above doesn't equal our temp string
                      tmpSweep = tmpSweep & trimSweep & "|" 'then add that stuff to our temp string with a delimiter
                    End If

             End If
        Next cell
        '===================
        'Write the strings "tmpPort" & "tmpSweep" gathered above into our arrays
        If Len(tmpPort) > 0 Then tmpPort = Left(tmpPort, Len(tmpPort) - 1)
             portArr = Split(tmpPort, "|")
        If Len(tmpSweep) > 0 Then tmpSweep = Left(tmpSweep, Len(tmpSweep) - 1)
             sweepArr = Split(tmpSweep, "|")
        '===================
        'Start filling in cells in column "A" with ports from the port array
        rowDest = rowDest + 1
        colDest = 1
        For i = LBound(portArr) To UBound(portArr)
            Cells(rowDest, 1).Value = portArr(i) 'input the marker value
            rowDest = rowDest + 1 'increment column for markers
        Next  'increment next array item and loop
        '======================================================

        '======================================================
        'New section ==========================================
    'As a stop-gap, just to get something going, I've implemented the following code to get the summary.
    'However, if the rows of file names are not in alpha order, or one is missing, or anything else goes wrong
    '   this will fail out.
    rowDest = lastrow + 3
    '===================
    ' 1) Cycle through each row of ports
    For i = LBound(portArr) To UBound(portArr)
        colDest = 2
        j = 0
        '===============
        ' 2) Cycle through each column of each of those rows
        For Each cell In headColRng
            '===========
            ' 3) Check active column header row for type of test (string up to the space) & copy that type
            swpHead = Left(cell, InStr(cell, " ") - 1) 'will cut off everything after the type
            '===========
            ' 4) Check sweepArr for the type we copied and return the index ("i")
            arrPos = Application.Match(swpHead, sweepArr, False) - 1
                '=======
                'purely for testing - remove later
                'Cells(rowDest, colDest).Value = portArr(i) & "_" & sweepArr(arrPos)
                '=======
                '=======
                ' 5) search the Range1 CSV File names for a match to [current row Port] &"_"& sweepArr(arrPos)
                Set lookupRng = rngSrc.Find(What:=portArr(i) & "_" & sweepArr(arrPos), LookIn:=xlValues, _
                        LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                        MatchCase:=False, SearchFormat:=False)
                If Not lookupRng Is Nothing Then
                    rowSrc = lookupRng.row
                Else
                    MsgBox ("Can't find the sweep for value" _
                        & vbCrLf & portArr(i) & "_" & sweepArr(arrPos) _
                        & vbCrLf & "Please check that this sweep exists")
                    Cells(rowDest, colDest).Value = "NoSweep"
                    GoTo NextJ
                End If
            '===========
            ' 6) return the value from the column "#" columns to the right
            ' & plug that value into the current row/column
            If colDest < 11 Then
                Cells(rowDest, colDest).Value = Cells(rowSrc, markColArr(j)).Value
                With Cells(rowDest, colDest)
                    .NumberFormat = "0.00_);[Red](0.00)"
                End With
            Else 'unless we're at RLWS "total", then we use a formula
                Cells(rowDest, colDest).Value = (Cells(rowDest, colDest - 1).Value + _
                    Cells(rowDest, colDest - 2).Value) / -2
                With Cells(rowDest, colDest)
                    .NumberFormat = "0.00_);[Red](0.00)"
                End With
            End If
NextJ:             'where a sweep-not-found error takes us
            j = j + 1 'increment array placeholder
            colDest = colDest + 1 'next column
        Next cell
        rowDest = rowDest + 1 'next row
    Next
        '======================================================
        '======================================================
    End Function

你的问题太描述性了。您能否举例说明,仅取一个示例案例,说明这些是输入,并且以这种方式,需要对其进行处理,最终输出是这种形式的。你可能会得到很多答案。建议编辑您的问题以使其更简单。我编辑了它-不确定如何提问。这里的问题不是关于数据或它们所代表的信息,而是如何处理数据。所以,我不理解你所展示的任何东西,我也不需要知道。对我来说,现在的问题是:有一个范围1,你想把它概括为范围2。据我所知,这里甚至没有一个编程问题,因此这个问题可能被发布到了错误的网站。如果没有,请发布到目前为止您拥有的代码以及您需要帮助的错误或错误。问题是我是否应该创建一个包含TypeArray项的用户表单,询问TypeArray中的哪些项转到哪个端口摘要头,然后创建一个新的TypeArray,或者只是尝试以某种方式重新配置程序本身。我不知道如何确保我的TypeArray项目被分配到正确的端口摘要标题,也不知道我如何两次使用相同的数组项目-即,在转到RLST之前,使用TypeArray项目RLL查找Range2标题项目RLL RX和RLL TX。这将起作用,但Range2是使用我迄今为止使用的代码创建的-在此之前不存在。我不知道如何使用代码将VLOOKUP放入我需要的单元格中。您好@JGR,这是如何使用VBA:rangeB40:K45.FormulaR1C1==VLOOKUPRC1&&LEFTR39C,FIND,R39C-1&.csv,R18C1:R37C13,3,FALSE添加此公式。或者,如果你想一个单元格一个单元格地添加值,而不是一个公式,可以像这样使用vlookup,使用相同的参数输入:rangeB40.value=worksheetfunction.VLookuparg1,arg2,arg3,arg4这将在我完成摘要信息后必须创建的下一个工作表中派上用场-谢谢。