VBA在多个工作表上搜索值并给出总计

时间:2014-05-14 13:29:31

标签: excel vba excel-vba

我有一个遗留电子表格,其中包含团队中每个人的工作表 工作表有多个列,我感兴趣的列是A和B,A有一个工作名称,B有一个人工作的总时数。

在另一张表(称为&#34; Consolidation&#34;)中,我有A列也有作业名,而H列则需要放置项目所有人共计工作的小时数。< / p>

目前,我有以下代码:

'Modified from: http://www.rondebruin.nl/win/s9/win006.htm
Private Function Find_First(ByVal sht As Integer, ByVal cell As String)
    Dim FindString As String
    Dim Rng As Range
    FindString = Sheets(sht).Range(cell).value
    If Trim(FindString) <> "" Then
        With Sheets(sht).Range("A:A")
            Set Rng = .Find(What:=FindString, _
                            After:=.Cells(.Cells.Count), _
                            LookIn:=xlValues, _
                            LookAt:=xlWhole, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlNext, _
                            MatchCase:=False)
            If Not Rng Is Nothing Then
                Find_First = Rng
            End If
        End With
    End If
End Function

Public Function getSummary(ByVal myCell As Range)
    Dim total As Integer

    For i = 1 To Sheets.Count
        ' Iterate over all the sheets

        If Sheets(i).Name = "Consolidation" Then
            ' If the sheet is "Consolidation" then skip to next element
            GoTo NextIteration
        End If

        Dim job As Range
        Dim value As Range

        Set job = Find_First(i, myCell)
        Set value = job.Offset(0, 1).value

        total = total + value

NextIteration:
    Next

    getSummary = total
End Function

我使用=getSummary(A3)从列H3调用它。然后H3等于#VALUE!,我不知道为什么......你可以从代码中看出来,我没有VBA专家,我也不知道从哪里开始似乎不太像调试工具那样......

更新 : 感谢David和CodeJockey,我有一些功能完全按照我的需要运行:

'Modified from: http://www.rondebruin.nl/win/s9/win006.htm
Private Function FindFirst(ByVal sht As Integer, ByVal cell As String) As Range
    Dim FindString As String
    Dim Rng As Range
    FindString = Sheets("Consolidation").Range(cell).value
    If Trim(FindString) <> "" Then
        With Sheets(sht).Range("A:A")
            Set Rng = .Find(What:=FindString, _
                            After:=.Cells(.Cells.Count), _
                            LookIn:=xlValues, _
                            LookAt:=xlWhole, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlNext, _
                            MatchCase:=False)
            If Not Rng Is Nothing Then
                Set FindFirst = Rng
            End If
        End With
    End If
End Function

Private Function getData(ByVal myCell As Range, ByVal offset As Integer)
    Dim total As Integer
    total = 0

    For i = 1 To Sheets.Count
        ' Iterate over all the sheets

        If Sheets(i).Name = "Consolidation" Then
            ' If the sheet is "Consolidation" then skip to next element
            GoTo NextIteration
        End If

        Dim job As Range
        Dim value As String

        Set job = FindFirst(i, myCell.Address)
        If Not job Is Nothing Then
            value = job.offset(0, offset).value
            If Not IsEmpty(value) And IsNumeric(value) Then
                total = total + value
            End If
        End If

NextIteration:
    Next

    getData = total
End Function

Function getBurnHours(ByVal myCell As Range)
    Application.Volatile
    getBurnHours = getData(myCell, 1)
End Function

Public Function getBurnDays(ByVal myCell As Range)
    Application.Volatile
    getBurnDays = getData(myCell, 2)
End Function

Public Function getActualHours(ByVal myCell As Range)
    Application.Volatile
    getActualHours = getData(myCell, 3)
End Function

Public Function getActualDays(ByVal myCell As Range)
    Application.Volatile
    getActualDays = getData(myCell, 4)
End Function

2 个答案:

答案 0 :(得分:3)

myCell是一个Range对象,但函数Find_First期待一个String参数。

所以你应该改变这个:

Set job = Find_First(i, myCell)

对此:

Set job = Find_First(i, myCell.Address)

您还需要更改return语句,以使返回值与type变量(Range)中预期的job数据匹配,您需要Set个关键字赋值:

Set Find_First = Rng

或者,您需要将声明的job类型更改为Range对象以外的其他类型。我不确定您希望返回什么,但由于您的数据类型都很糟糕,因此很难推荐精确的解决方案。

同样,您声明Value作为Range对象不能接受job.Offset(0, 1).Value(返回字符串),而不会引发不匹配错误。因此,您需要更改此变量的声明或更改对象的赋值。

否则,这可能有用:

http://www.cpearson.com/excel/DebuggingVBA.aspx

答案 1 :(得分:1)

函数Find_First(sht, cell)返回“Rng”中的值,而不是对象本身。要返回对象,请使用“Set”运算符。请参阅下面的编辑:

If Not Rng Is Nothing Then
     Set Find_First = Rng
End If

这是允许的,因为您的私有函数返回Variant而不是Range。为清楚起见,我也会改变这个:

Private Function Find_First(ByVal sht As Integer, ByVal cell As String)

到此:

Private Function Find_First(ByVal sht As Integer, ByVal cell As String) as Range