2

我有一列包含 .cpp 文件名列表,另一列表示测试用例。我想搜索工作表中与测试用例字符串匹配的所有行并从该行打印文件名。

column 1        column2 
--------       ------------    
file1.cpp      testcase1   
file2.cpp      testcase1   
file3.cpp      testcase3    
...             .......    
....            .......     

所以最后我想要一个看起来像这样的输出:

Testcase1   Testcase2     
file4.cpp   file5.cpp    
file9.cpp   file8.cpp     
file5.cpp   file13.cpp  

这是vba代码:

Function fileToTest(Search_string As String, _
Search_in_col As Range)

Dim result As String   
Dim i As Long   
Dim j As Long   
Dim rArray(20) As String    
Dim rCnt As Long   
Dim rTmp As String   
Dim found As Long   
Dim testCases, Value As Variant   
Dim currentRow As Long    
Dim fCnt As Long    

  For i = 1 To Search_in_col.Count 'search each test case column    
     testCases = Split(Search_in_col.Cells(i, 1), ";")    
     For Each Value In testCases    
         If Search_string = Value Then    

        ActiveCell.Value = Search_in_col.Cells(i, 2).Value    
         ' write the next row after active cell. not sure how to do this
        End If   
      Next Value   
   Next i   


End Function   

当我尝试写入 ActiveCell.Value 时函数失败

4

1 回答 1

0

您面临的问题是-根据您的评论-您想要一个用户定义的函数-然后尝试修改工作表。这是不可能的,因为 UDF 的体系结构是您不能对工作表进行任何更改,而只能使用您的函数返回一个值 - 然后显示该值。此外,在 UDF 中,除了作为参数传递的单元格之外,通常不允许读取任何其他单元格的值 - 否则这将导致 Excel 认为某处存在循环引用。

因此,我看到以下三个选项:

  1. 修改你的 UDF
  2. 创建一个宏,一次填充所有单元格
  3. 仅使用 Excel 公式

以下是详细信息:

1.修改你的UDF

假设您在 A1 中输入“testcase1”,构建一个可以这样调用的 UDF:

=FileToTestCase(A1,1,SourceSheet!A2:A100,SourceSheet!B2:B100)

UDF 的 VBA 定义将是这样的:

Public Function FileToTestCase(sTestCaseName as String, iElementNumber as Integer, _
    rngFileNames as Range, rngTestcases as Range) as String
    CodeToFigure out the iElementNumer_th entry for sTestCaseName
    FileToTestCase = YourResult
 End Function

然而,这种方法非常低效,因为您每次都需要解析源列表。您可以使用在第一次调用中初始化并稍后使用的一些内部、模块范围的变量来加速此过程 - 但是您需要注意检测更改。或者,您可以在一个大数组公式中执行此操作。但是,这两种方法都相当费力。

2.创建一个宏,一次填充所有单元格

您可以使用一个宏来一次性填充所有单元格,而不是 UDF。如果要自动更新内容,请从 Worksheet_Change 事件调用宏 - 每次源数据更改时。

这段代码应该这样做:

Sub FillTestcases(rngFiles As Range, rngTestcases As Range, rngStartResult As Range)
    Dim d As New Scripting.Dictionary
    Dim lRow As Long
    Dim sTestCase As Variant
    Dim sFile As Variant
    Dim rngResult As Range
    Const csSeparator As String = "|"

    For lRow = 1 To rngFiles.Rows.Count
        sTestCase = rngTestcases(lRow, 1).Value
        sFile = rngFiles(lRow, 1).Value
        If d.Exists(sTestCase) Then
            d(sTestCase) = d(sTestCase) & csSeparator & sFile
        Else
            d.Add sTestCase, sFile
        End If
    Next

    Set rngResult = rngStartResult
    For Each sTestCase In d.Keys
        rngResult.Value = sTestCase
        rngResult.Font.Bold = True
        lRow = 1
        For Each sFile In Split(d(sTestCase), csSeparator)
            rngResult.Offset(lRow) = sFile
            lRow = lRow + 1
        Next sFile
        Set rngResult = rngResult.Offset(, 1)
    Next sTestCase
End Sub

请注意,您需要添加对Microsoft Scripting Runtime的引用才能使用 Dictionary 类。另请注意,此代码不会合并重复项,因此您可能需要对其进行调整。

3. 只使用 Excel 公式

假设您的文件名在 A1:A10 中,B1:B10 中的测试用例和测试用例名称列表在第 1 行,从 F 列开始,在 F2 中使用此公式:

=IFERROR(INDEX($A$1:$A$10,-INT((大(($B$1:$B$10=F$1)-ROW($B$1:$B$10)/10000,ROW(F1)) -1)*10000)),"")

这是一个数组公式,所以用Ctrl- Shift-输入Enter

于 2013-02-14T23:13:14.360 回答