У меня есть устаревшая таблица, в которой есть листы для каждого члена команды.
Рабочие листы имеют несколько столбцов, меня интересуют столбцы A и B, у A есть название работы, а у B указано общее количество часов, которые человек отработал над этой работой.

На другом листе (называемом «Консолидация») у меня есть столбец A, в котором также указано название задания, и столбец H, в котором необходимо указать общее количество часов, отработанных всеми людьми над проектом.

В настоящее время у меня есть следующий код:

'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

Я вызываю его из столбца H3 с помощью =getSummary(A3). Тогда H3 равно #VALUE !, и я понятия не имею, почему ... Как вы, вероятно, можете сказать из кода, я не эксперт по VBA, и я не знаю, с чего начать, поскольку, похоже, нет много средств отладки ...

ОБНОВЛЕНИЕ : Благодаря Дэвиду и 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
0
forquare 14 Май 2014 в 17:29

2 ответа

Лучший ответ

myCell является объектом Range, но функция Find_First ожидает аргумент String.

Итак, вы должны изменить это:

Set job = Find_First(i, myCell)

К этому:

Set job = Find_First(i, myCell.Address)

Вам также нужно будет изменить оператор return так, чтобы возвращаемое значение соответствовало type данных, ожидаемых в переменной job (Range), вам понадобится ключевое слово Set в этом назначении:

Set Find_First = Rng

Или вам нужно изменить объявленный тип job на что-то другое, кроме объекта Range. Я не совсем уверен, что вы ожидаете вернуть, но поскольку все ваши типы данных ненормальные, трудно рекомендовать точное решение.

Точно так же ваше объявление Value как объекта Range не может принимать job.Offset(0, 1).Value (который возвращает строку) без возникновения ошибки несоответствия. Итак, вам нужно либо изменить объявление этой переменной, либо изменить назначение объекта.

В противном случае это может оказаться полезным:

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

3
Community 8 Май 2018 в 21:48

Функция Find_First(sht, cell) возвращает значение в "Rng", а НЕ сам объект. Для возврата объекта используйте оператор «Установить». См. Правку ниже:

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

Это разрешено, потому что ваша частная функция возвращает вариант, а не диапазон. Для ясности я бы также изменил это:

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
1
CodeJockey 14 Май 2014 в 14:15