Excel宏 - 查询源

时间:2015-10-10 19:53:00

标签: excel-vba vba excel

VBA仍然不太好,试图学习。问题是我是否应该使用TypeArray项目创建一个用户表单,询问他们哪些项目去哪个"端口摘要"标题,然后创建一个新的TypeArray,或者只是尝试让程序以某种方式重新配置(以及 - 如何?)?

我从大量的CSV文件中获取了这些数据(这是一个片段,实际包含60 - 250行,以及5个或更多" Marker"列) - 让&#39 ; s称之为Range1:

╔════════════════════════════════╦══════════════════╦══════════════╦══════════════════╦══════════════╦══════════════════╦══════════════╗
║         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 Header对应于此示例中的RLWS测试类型 - Range2标题不会发生太大变化,但测试类型值名称可能会更新)

我使用" TypeArray"使用(6)测试类型和" PortArray"填写Port Summary区域,我需要:

  1. 循环浏览Range2中的每个Port行
  2. 遍历每个端口的每个列(Range2标头)
  3. 搜索Range1 CSV文件名以匹配PortArray&" _"& TypeArray
  4. 拉(基于Range2中的标题):
    • Marker 1 dbm列的值或
    • Marker 2 dbm列的值或
    • Marker 3 dbm列的值或
    • (Marker 2 dbm列的值+ Marker 3 dbm列的值)除以-2
  5. 我在第3步被挂了,并且不知道如何确保我的TypeArray被分配到正确的Port Summary标题(他们不会出现故障 - 例如什么如果Range1中的文件名不按字母顺序排列?我的TypeArray从该列表自上而下填充,可能是RLL,RLS,RLWS,DTFL等,而我的Range2标题保持不变)和< / strong>我如何使用相同的数组项两次 - 即使用TypeArray项&#34; RLL&#34;找到Range2标题项&#34; RLL RX&#34;和&#34; RLL TX&#34;在继续进行&#34; RLS&#34;?

    之前

    当前示例图片: Example

    我使用以下方法创建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
    

2 个答案:

答案 0 :(得分:0)

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

=VLOOKUP($A40 & "_" & LEFT(B$39,FIND(" ",B$39)-1) & ".csv", $A$18:$M$37, 3, FALSE)

VLookup中的第三个参数是列,因此在这种情况下将从第3列返回值:Marker 1 dBm。
您的步骤4不是特定的,但您可以更改第三个参数以适合您想要数据的列。

答案 1 :(得分:0)

我对此非常困惑,整个部分(我的主要Sub调用的一个函数)看起来仍然非常(非常)对我来说很笨拙 - 我绝对会感谢任何评论/邮件/即时通讯可能会使这种情况不那么摇摇欲坠。

我为回答我的问题而添加的内容在标注的部分中,&#34;新部分&#34;。

    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