2010-12-07 4 views
2

geschrieben Ich habe diese Formel in einer Zelle:Excel VBA Formel, aus einer Zelle genannt wird, stoppt die Verarbeitung VBA, oder trifft eine App-Defined Fehler, wenn ein Arbeitsblatt-Zelle zu

=GetData("Channel_01","Chicago") 

Welche diesen Code ausführt :

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 

Das Problem auf dieser Linie tritt:

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

Ist Einstellung dieser Aufruf einer Tabelle rec alc, der den ausführenden VBA-Thread oder etwas ähnliches beendet? Ich dachte, so, also habe ich versucht diese, bevor sie eine Ausgabe zu schreiben:

Application.Calculation = xlCalculationManual 

Aber jetzt auf der gleichen Zeile Code erhalte ich: Anwendungs ​​definiert oder Objekt definierte Fehler.

Schreiben von einer VBA-Funktion auf das gleiche Arbeitsblatt, von dem die VBA-Funktion aufgerufen wird, nur nicht zulässig?

+0

Einstellung was? .. –

Antwort

3

Dies ist nur das integrierte Verhalten von Excel. Funktionen, die aus dem Arbeitsblatt aufgerufen werden (in der Terminologie von Excel oft als benutzerdefinierte Funktionen bezeichnet), können nichts mit dem Arbeitsblatt tun, außer einen Wert zurückgeben.

In Ihrem Code oben scheint jedoch ein weiterer Fehler zu sein.

sollte fehlschlagen, weil Sie die Syntax zum Festlegen einer Objektvariablen auf eine Objektreferenz verwenden. Wenn Sie dort einen Fehler-Handler hatten, würde es den Fehler abfangen. (Excel beendet nur jede UDF, dass ein Fehler geht nicht behandelte können.) Die Linie sein soll:

destination.Value = ChannelCode 

jedoch Ihre Routine immer noch an diesem Punkt scheitern, weil die Regel über UDF keine Nebenwirkungen auf Zellen. Beachten Sie, dass selbst wenn Sie einen Error-Handler hätten, dies nicht bemerkt würde. VBA verursacht keinen Fehler, wenn ein UDF versucht, eine Zelle zu ändern; Es stoppt nur die UDF und gibt einen #WERT zurück! Error.

In Ihrem Fall sieht es so aus, als könnten Sie Ihre Funktion so umschreiben, dass sie ein Array mit den gewünschten Werten zurückgibt, anstatt zu versuchen, Zellen rechts und unterhalb der aufrufenden Zelle zu ändern. (Sie können auch Ihre Funktion von einem Makro anstelle eines UDF nennen.)

EDIT:

Was das Array zurückkehrt, gibt es eine ADO-Methode - GetRows - die man von einem RecordSet zurück:

code critique - am I creating a Rube Goldberg machine?

+2

Schlüsselpunkte: 1. Excel beendet alle UDF, die einen Fehler unbehandelt lassen können; 2. VBA löst keinen Fehler aus, wenn ein UDF versucht, eine Zelle zu ändern, es stoppt nur die UDF und gibt einen #VALUE zurück! Error. 3. Schreiben Sie Ihre Funktion neu, um ein Array zurückzugeben, das die gewünschten Werte enthält. – tbone

+0

Um beim Debugging von benutzerdefinierten Funktionen zu helfen, tendiere ich dazu, einen kleinen Test-Sub zu erstellen, der die benutzerdefinierte Funktion einfach von VBA aufruft. Kopieren Sie einfach die Formel, die Sie in Excel verwenden, und fügen Sie sie in ein neues Unterverzeichnis ein. Alle Bereiche, auf die es verweist, müssen von 'Range ("xxx") umgeben sein. Auf diese Weise funktioniert die normale VBA-Fehlerbehebung, wenn ein Fehler generiert wird. – steveo40

Verwandte Themen