2010-12-07 31 views
2

J'ai cette formule dans une cellule:formule Excel VBA, appelé à partir d'une cellule, VBA de traitement arrête ou rencontre une erreur App-définie, lorsqu'une cellule de feuille de calcul est écrit à

=GetData("Channel_01","Chicago") 

qui exécute ce code :

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 

Le problème se produit sur cette ligne:

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

réglage est-il cette invocation d'une feuille de calcul rec alc, qui termine le thread VBA en cours d'exécution ou quelque chose comme ça? Je pensais, donc j'ai essayé cela avant d'écrire une sortie:

Application.Calculation = xlCalculationManual 

Mais maintenant, sur cette même ligne de code que je reçois: application défini ou un objet défini erreur.

L'écriture d'une fonction VBA dans la même feuille de calcul à partir de laquelle la fonction VBA est appelée n'est-elle pas autorisée?

+0

Définition de quoi? –

Répondre

3

Ceci est juste le comportement intégré d'Excel. Les fonctions appelées à partir de la feuille de calcul (souvent appelées fonctions UDF dans la terminologie Excel - fonctions définies par l'utilisateur) ne peuvent rien faire à la feuille de calcul si ce n'est de renvoyer une valeur.

Dans votre code ci-dessus, il semble y avoir une autre erreur.

Set destination.Value = ChannelCode 

doit échouer car vous utilisez la syntaxe pour définir une variable objet sur une référence d'objet. Si vous aviez un gestionnaire d'erreur, il attraperait l'erreur. (Excel termine juste une UDF qui laisse une erreur aller non prise en charge.) La ligne devrait être:

destination.Value = ChannelCode 

Cependant, votre routine toujours pas à ce moment-là en raison de la règle sur les UDFs ne pas avoir des effets secondaires sur les cellules. Notez que même si vous avez un gestionnaire d'erreurs, il ne l'attraperait pas. VBA ne génère pas d'erreur lorsqu'un UDF tente de modifier une cellule; il arrête juste l'UDF et renvoie un #VALUE! Erreur. Dans votre cas, il semble que vous pouvez réécrire votre fonction pour retourner un tableau contenant les valeurs que vous voulez, au lieu d'essayer de modifier les cellules à droite et en dessous de la cellule appelante. (Ou vous pouvez appeler votre fonction de certains macro au lieu d'une UDF.)

EDIT:

En ce qui concerne le retour du tableau, il existe une méthode ADO - GetRows - qui renverra un d'un RecordSet:

code critique - am I creating a Rube Goldberg machine?

+2

Points clés: 1. Excel met fin à toute fonction définie par l'utilisateur qui laisse une erreur non traitée; 2. VBA ne déclenche pas d'erreur lorsqu'un UDF tente de modifier une cellule, il arrête simplement l'UDF et renvoie un #VALUE! Erreur. 3. réécrire votre fonction pour retourner un tableau contenant les valeurs que vous voulez – tbone

+0

Pour aider au débogage des fonctions UDF, j'ai tendance à créer un petit sous-test qui appelle simplement l'UDF de VBA lui-même. Copiez simplement la formule que vous utilisez dans Excel et collez-la dans un nouveau sous-marin. Toutes les plages qu'il référence devront être entourées de 'Range ("xxx"). De cette façon, s'il génère une erreur, le trapping d'erreur VBA normal fonctionnera. – steveo40