Формула VBA Excel, вызванная из ячейки, останавливает обработку VBA или обнаруживает ошибку, определяемую приложением, при записи в ячейку листа - PullRequest
2 голосов
/ 07 декабря 2010

У меня есть эта формула в ячейке:

=GetData("Channel_01","Chicago")

, которая выполняет этот код:

Public Function GetData(ChannelCode As String, Key As String) As String
    Dim sql As String
    Dim cmd As New ADODB.Command
    Dim outputTo As Range
    Set outputTo = Application.Caller    
    sql = "select * from ChannelData WHERE ChannelCode = ? AND Key1 = ?"
    Set cmd = getCommand(sql, ChannelCode, Key)
    Dim rs As ADODB.Recordset
    Set rs = cmd.Execute
    WritePivotRecordset ChannelCode, rs, outputTo.Offset(1, 0)
End Function

Public Sub WritePivotRecordset(ChannelCode As String, rs As ADODB.Recordset, destination As Range)
    Dim i As Integer
    '*** WHEN THIS LINE OF CODE IS REACHED AND EXECUTES, PROCESSING STOPS
    Set destination.Value = ChannelCode
    For i = 1 To rs.Fields.Count - 1    'skip first field
        destination.Offset(0, i).Value = rs.Fields(i).Name
    Next
    destination.Offset(1, 0).CopyFromRecordset rs
End Sub

Проблема возникает в этой строке:

'*** WHEN THIS LINE OF CODE IS REACHED AND EXECUTES, PROCESSING STOPS
    Set destination.Value = ChannelCode

Установка этого вызывает вызов перезаписи электронной таблицы, который завершает выполнение потока VBA или что-то в этом роде?Я так и думал, поэтому попробовал это перед тем, как написать какой-либо вывод:

Application.Calculation = xlCalculationManual

Но теперь в той же строке кода я получаю: Ошибка приложения или объекта.

Запись из функции VBA в тот же рабочий лист, с которого вызывается функция VBA, только не разрешена?

1 Ответ

3 голосов
/ 07 декабря 2010

Это просто встроенное поведение Excel.Функции, вызываемые из рабочего листа (часто называемые пользовательскими функциями в терминологии Excel - определяемые пользователем функции), не могут ничего делать с рабочим листом, кроме как возвращать значение.

В приведенном выше коде, похоже, есть еще одна ошибка.

Set destination.Value = ChannelCode 

должно произойти сбой, потому что вы используете синтаксис для установки переменной объекта для ссылки на объект.Если бы у вас там был обработчик ошибок, он бы поймал ошибку.(Excel просто завершает работу с любой пользовательской функцией, которая позволяет ошибке остаться без обработки.) Строка должна быть:

destination.Value = ChannelCode 

Однако ваша процедура все равно не будет выполнена в этот момент из-за правила о том, что пользовательские функции не имеют побочных эффектов в ячейках,Обратите внимание, что даже если у вас есть обработчик ошибок, он не поймает это.VBA не выдает ошибку, когда UDF пытается изменить ячейку;он просто останавливает UDF и возвращает # ЗНАЧЕНИЕ!ошибка.

В вашем случае похоже, что вы можете переписать свою функцию, чтобы вернуть массив, содержащий нужные значения, вместо того, чтобы пытаться изменить ячейки справа и снизу от вызывающей ячейки.(Или вы можете вызвать вашу функцию из некоторого макроса вместо UDF.)

EDIT:

Что касается возврата массива, существует метод ADO - GetRows - который вернетодин из RecordSet:

критика кода - я создаю машину Rube Goldberg?

...