Пользовательская функция работает в VBA и возвращает #VALUE «неправильный тип данных» при вызове в ячейке Excel - PullRequest
0 голосов
/ 05 января 2019

У меня есть UDF, который подсчитывает, сколько клиентов и обслуживающего работника имеет, или сколько обслуживающего персонала у клиента, за данную неделю. Данные представлены в двух разных диапазонах: один отсортирован по работникам службы, а другой - по клиенту, чтобы избежать необходимости сортировки в первую очередь.

Код создает массив для записи ссылок на строки строк недели, которые я ищу, а затем просматривает последние экземпляры работника или клиента. Код работает в VBA и возвращает #VALUE в Excel, а «Проверка ошибок» в Excel указывает на неправильный тип данных. При использовании разрывов код завершается ошибкой, когда он попадает в создание диапазона, это может быть связано с созданием массив, который принимает ссылки на строки из диапазона или нет.

Мне интересно, если я кое-как пытаюсь изменить «состояние Excel». Мысли о проблеме и как ее исправить?

Public Function clientOrServiceWorkerCount(startWeek As Integer, endWeek As 
Integer, searchID As Long, outputType As Integer, sheetName As Variant) As 
Integer

    clientOrServiceWorkerCount = 0

    Dim WSMod111 As Worksheet
    Set WSMod111 = sheetName


    Dim rowOffset As Integer
    rowOffset = 3
    Dim endIndex As Integer
    endIndex = WSMod111.Cells(WSMod111.Rows.count, 13).End(xlUp).row - 
    rowOffset

    Dim tempRange As Range
    Set tempRange = WSMod111.Range("U4:Z" & endIndex)

    Dim tempArray() As Integer
    Dim weekNow As Integer
    Dim weekNext As Integer
    Dim ClientIDNow As Long
    Dim ClientIDNext As Long
    Dim serviceWorkerIDNow As Integer
    Dim serviceWorkerIDNext As Integer
    Dim arrayID As Integer
    Dim serviceWorkerCount As Integer
    Dim cLCount As Integer
    Dim colOffset As Integer
    Dim arrayCount As Integer

    arrayCount = 0

    ' Offset which columns to refer to based on the outputType value. 1 = 
    search for client then service workers
    ' 2 = search for service workers and then clients
    If outputType = 1 Then
        colOffset = 0
    End If

    If outputType = 2 Then
        colOffset = 3
    End If

    'Build the array for the week range of interest, defined by startWeek 
and endWeek
    For i = 0 To endIndex - 1
        weekNow = tempRange(i + 1, 1 + colOffset)
        arrayID = tempRange(i + 1, 2 + colOffset)

        If weekNow >= startWeek And weekNow <= endWeek And arrayID = 
        searchID Then
            ReDim Preserve tempArray(arrayCount)
            tempArray(arrayCount) = i + 1
            arrayCount = arrayCount + 1

            'Print the results to the worksheet to check answers
            tempRange.Cells(arrayCount, 8) = tempArray(arrayCount - 1)
        End If
    Next i

   For n = 0 To arrayCount - 1

        weekNow = tempRange(tempArray(n), 1 + colOffset)
        serviceWorkerIDNow = tempRange(tempArray(n), 2 + colOffset)
        ClientIDNow = tempRange(tempArray(n), 3 + colOffset)

        'Debugging printing

        'tempRange.Cells(1 + n, 9) = weekNow
        'tempRange.Cells(1 + n, 11) = serviceWorkerIDNow
        'tempRange.Cells(1 + n, 13) = ClientIDNow

        If n < arrayCount - 1 Then

            weekNext = tempRange(tempArray(n + 1), 1 + colOffset)
            serviceWorkerIDNext = tempRange(tempArray(n + 1), 2 + colOffset)
            ClientIDNext = tempRange(tempArray(n + 1), 3 + colOffset)

            'Debugging printing
            tempRange.Cells(1 + n, 10) = weekNext
            tempRange.Cells(1 + n, 12) = serviceWorkerIDNext
            tempRange.Cells(1 + n, 14) = ClientIDNext

        End If

        If outputType = 1 Then
            If ClientIDNow <> ClientIDNext Or n = arrayCount - 1 Then
                cLCount = cLCount + 1
            End If
        End If

        If outputType = 2 Then
            If serviceWorkerIDNow <> serviceWorkerIDNext Or n = arrayCount - 
            1 Then
                serviceWorkerCount = serviceWorkerCount + 1
            End If
        End If
    Next

    'Return the count of either the clients (outputType=1) or the serviceWorkerinators (outputType=2)
    If outputType = 1 Then
        clientOrServiceWorkerCount = cLCount
    End If

    If outputType = 2 Then
       clientOrServiceWorkerCount = serviceWorkerCount
    End If

End Function

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Dy.Lee, я закомментировал мою отладочную печать, используя ваше предложение:

    For n = 0 To arrayCount - 1

        weekNow = tempRange(tempArray(n), 1 + colOffset)
        serviceWorkerIDNow = tempRange(tempArray(n), 2 + colOffset)
        ClientIDNow = tempRange(tempArray(n), 3 + colOffset)

        'Debugging printing
        'tempRange.Cells(1 + n, 9) = weekNow
        'tempRange.Cells(1 + n, 11) = serviceWorkerIDNow
        'tempRange.Cells(1 + n, 13) = ClientIDNow

        If n < arrayCount - 1 Then

            weekNext = tempRange(tempArray(n + 1), 1 + colOffset)
            serviceWorkerIDNext = tempRange(tempArray(n + 1), 2 + colOffset)
            ClientIDNext = tempRange(tempArray(n + 1), 3 + colOffset)

            'Debugging printing
            'tempRange.Cells(1 + n, 10) = weekNext
            'tempRange.Cells(1 + n, 12) = serviceWorkerIDNext
            'tempRange.Cells(1 + n, 14) = ClientIDNext

И все работает отлично. Я также обновил ссылку на лист (""), которую вы указали, и больше не получаю сообщение об ошибке компиляции. Я понятия не имел, что мой код отладки нарушает правило «функция, на которую ссылается ячейка, не может изменить ничего, кроме этой ячейки», - поскольку я не знал, что это правило существует. Огромное спасибо за вашу помощь, я неделями ломал голову над столом, пытаясь понять, что случилось. С уважением, Антоний

0 голосов
/ 05 января 2019

Вы хотите использовать пользовательскую функцию на листе, но в вашей пользовательской функции есть содержимое, которое изменяет значение ячейки. Это невозможно сделать, применяя функцию непосредственно к листу, поэтому возникает ошибка.

    'Debugging printing
    tempRange.Cells(1 + n, 10) = weekNext
    tempRange.Cells(1 + n, 12) = serviceWorkerIDNext
    tempRange.Cells(1 + n, 14) = ClientIDNext

Использование вашей функции внутри процедуры работает, как показано ниже.

Sub test()
    Dim c As Integer
    c = clientOrServiceWorkerCount(2, 3, 1, 1, "Sheet2")
    Range("r1") = c

End Sub

Если вы закомментируете свой проблемный код, результат хорошо работает на листе.

Public Function clientOrServiceWorkerCount( _
        startWeek As Integer, _
        endWeek As Integer, _
        searchID As Long, _
        outputType As Integer, _
        sheetName As Variant) As Integer

    clientOrServiceWorkerCount = 0

    Dim WSMod111 As Worksheet
    Set WSMod111 = Sheets(sheetName)'<~~ Your code should change like this.


    Dim rowOffset As Integer
    rowOffset = 3
    Dim endIndex As Integer
    endIndex = WSMod111.Cells(WSMod111.Rows.Count, 13).End(xlUp).Row - rowOffset

    Dim tempRange As Range
    Set tempRange = WSMod111.Range("U4:Z" & endIndex)

    Dim tempArray() As Integer
    Dim weekNow As Integer
    Dim weekNext As Integer
    Dim ClientIDNow As Long
    Dim ClientIDNext As Long
    Dim serviceWorkerIDNow As Integer
    Dim serviceWorkerIDNext As Integer
    Dim arrayID As Integer
    Dim serviceWorkerCount As Integer
    Dim cLCount As Integer
    Dim colOffset As Integer
    Dim arrayCount As Integer

    arrayCount = 0

    ' Offset which columns to refer to based on the outputType value. 1 = search for client then service workers
    ' 2 = search for service workers and then clients
    If outputType = 1 Then
        colOffset = 0
    End If

    If outputType = 2 Then
        colOffset = 3
    End If

    'Build the array for the week range of interest, defined by startWeek and endWeek
    For i = 0 To endIndex - 1
        weekNow = tempRange(i + 1, 1 + colOffset)
        arrayID = tempRange(i + 1, 2 + colOffset)

        If weekNow >= startWeek And weekNow <= endWeek And arrayID = searchID Then
            ReDim Preserve tempArray(arrayCount)
            tempArray(arrayCount) = i + 1
            arrayCount = arrayCount + 1

            'Print the results to the worksheet to check answers
            'tempRange.Cells(arrayCount, 8) = tempArray(arrayCount - 1)
        End If
    Next i

   For n = 0 To arrayCount - 1

        weekNow = tempRange(tempArray(n), 1 + colOffset)
        serviceWorkerIDNow = tempRange(tempArray(n), 2 + colOffset)
        ClientIDNow = tempRange(tempArray(n), 3 + colOffset)

        'Debugging printing

        'tempRange.Cells(1 + n, 9) = weekNow
        'tempRange.Cells(1 + n, 11) = serviceWorkerIDNow
        'tempRange.Cells(1 + n, 13) = ClientIDNow

        If n < arrayCount - 1 Then

            'weekNext = tempRange(tempArray(n + 1), 1 + colOffset)
            'serviceWorkerIDNext = tempRange(tempArray(n + 1), 2 + colOffset)
            'ClientIDNext = tempRange(tempArray(n + 1), 3 + colOffset)

            'Debugging printing
            'tempRange.Cells(1 + n, 10) = weekNext
            'tempRange.Cells(1 + n, 12) = serviceWorkerIDNext
            'tempRange.Cells(1 + n, 14) = ClientIDNext

        End If

        If outputType = 1 Then
            If ClientIDNow <> ClientIDNext Or n = arrayCount - 1 Then
                cLCount = cLCount + 1
            End If
        End If

        If outputType = 2 Then
            If serviceWorkerIDNow <> serviceWorkerIDNext Or n = arrayCount - 1 Then
                serviceWorkerCount = serviceWorkerCount + 1
            End If
        End If
    Next

    'Return the count of either the clients (outputType=1) or the serviceWorkerinators (outputType=2)
    If outputType = 1 Then
        clientOrServiceWorkerCount = cLCount
    End If

    If outputType = 2 Then
       clientOrServiceWorkerCount = serviceWorkerCount
    End If

End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...