Problème création fonction VBA
Bonjour,
J'essaie de créer une fonction sous VBA qui intègre une rechercheV.
Malheureusement elle ne fonctionne pas, voici le code :
Function TTC_l(CODE1, ht)
'CODE1 = ActiveCell.Offset(0, -3).Value
'ht = Range("CODE1").Offset(0, -1).Value
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
Ce code fonctionne très bien car pour l'instant je dois y mettre 2 arguments lorsque je rentre ma fonction dans Excel ! Or je ne voudrai rentrer qu'un seul argument (avec un décalage qui es toujours le même) voir 0 argument (en fonction de la cellule active) !
Je vous joins le fichier pour que vous y voyez plus clair ! c'est un fichier test le but est pour l'instant de juste calculer le Prix TTC !
Je vous remercie pour votre aide et espère avoir été clair..
Bonne journée
Stéphane Da Silva
Bonjour,
Ton code est protégé par mot de passe...
De ce que je vois sur ton post, il est inutile de demander des arguments dans ta fonction, puisque tu écrases ensuite leur valeur.
J'ai réussi à ouvrir ton code.
Première chose, je te déconseille de faire ta fonction sans argument, car elle ne s'appliquera que si elle est située à une position bien précise par rapport à tes données et a besoin d'une plage de cellule dans le classeur pour obtenir un résultat.
Autre chose, faire référence à la cellule active ne signifie pas faire référence à la cellule dans laquelle se trouve la formule (par exemple si tu entres ta formule dans une cellule et que tu l'étend vers le bas, la cellule active reste la première).
Le plus simple serait donc de ne pas passer par VBA pour faire ça (c'est d'ailleurs complètement inutile d'utiliser VBA si c'est pour faire exactement ce que tu peux faire dans Excel).
J'ai néanmoins retravaillé l'autre fonction de ton fichier (qui me semble moins susceptible d'être obsolète et présente l'avantage de ne pas nécessiter de données stockées directement dans ton classeur) :
Function TTC(ht As Single, code As String)
Dim Taux As Single
Taux = 0
Select Case code
Case "fr", "it"
Taux = 1.2
Case "be"
Taux = 1.21
Case "sp"
Taux = 1.19
Case "uk"
Taux = 1.17
Case "irl"
Taux = 1.16
End Select
If Taux = 0 Then TTC = "#ERREURCODE" Else TTC = ht * Taux
End FunctionMerci de ton aide et de ta réponse !
Merci d'avoir retravailler la select case effectivement il manquait la notion du "0" qui pouvait apparaître !
Je suis tout à fait d'accord avec toi sur le fait que ce que l'on peut faire sur Excel directement n'a rien à faire sur VBA ! néanmoins je m'entraine sur les fonctions et elles sont très pratiques pour réduire mes données si je peux réduire mon nombre de formule dans un fichier qui va donc s'alléger !
En effet si au lieu de 3 colonnes de formules j'en possède seulement 1 et bien je gagne par rapport à l'utilisation normale de Excel !
Dans le cas présent cette formule intègre la recherchev et la multiplication du prix ! Ceci n'est qu'un exemple mais si des gros fichiers utilisés dans le cadre de mon travail je pense pouvoir avoir une réelle plus-value !
Je comprends pour l'histoire des arguments et effectivement n'en avoir aucun serait dangereux !
J'espère que tu pourras quand même m'aider pour essayer d'avoir un seul argument ce qui est ma requête principale
Merci pour votre aide
Stéphane Da Silva
Tu allégeras ton fichier seulement si les fonctions sont bien écrites, et une RechercheV n'est pas la fonction la moins gourmande en ressources...
C'est évidemment pour cela que je demande de l'aide car j'ai encore beaucoup à apprendre en VBA !
Je pense que tu ne visualises pas bien les fichiers avec lesquels je travaille (Contrôle de gestion EDF) et celui-ci est un test pour le forum mais tu as l'air de t'y connaitre alors des recherchev sur des dizaines voir centaines de milliers de lignes rendent forcément le fichier compliqué à utiliser !
Ici je ne cherche pas un avis juste de l'aide pour que je puisse potentiellement l'adapter le jour venu ! Pas forcément sur un recherchev mais peut-être sur une autre !
Pourquoi mes lignes de codes ne fonctionnent pas !
Merci
Stéphane Da Silva
Dans une fonction Excel, tu ne peux pas mettre n'importe quoi dans les arguments. Par exemple, =MOYENNE("Patates";"Carottes") te renverras une erreur #VALEUR!. Avec une fonction personnalisée, c'est pareil, on doit déclarer le type de valeur attendue :
Function TTC_l(CODE1, ht)
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End FunctionSera donc préférable écrite ainsi :
Function TTC_l(CODE1 As String, ht As Single)
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End FunctionEn effet, tu cherches une valeur associée à une chaîne de caractères (string), résultat que tu multiplies par un nombre décimal (Single).
Pour ce qui est de l'autre tentative :
Function TTC_l()
CODE1 = ActiveCell.Offset(0, -3).Value
ht = Range("CODE1").Offset(0, -1).Value
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End FunctionTu n'as pas de plage nommée "CODE1". D'autre part, je ne sais pas quelle instruction permet de récupérer l'adresse de la cellule dans laquelle ce trouve la formule, car celle-ci n'est pas nécessairement la cellule active (donc "ActiveCell" est inadapté). Enfin, si tu places ta formule en colonne D, ActiveCell.Offset(0, -3) fait référence à la même ligne en colonne A (donc le montant et pas le code pays). Voilà qui serait mieux (mais je répète que le ActiveCell n'est pas adapté) :
Function TTC_l()
CODE1 = ActiveCell.Offset(0, -2).Value
ht = ActiveCell.Offset(0, -3).Value
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End FunctionMerci pour tes explications c'est très clair et je comprends mieux pourquoi tu me mettais en garde !
Effectivement l'utilisation de Activecell est complétement inutile donc le fait d'avoir 0 argument ne sera jamais adapté sauf pour une seule cellule de calcul...
Concernant le CODE1 sur cette ligne :
ht = Range("CODE1").Offset(0, -1).Value
Je pensais que VBA allait comprendre que c'est la cellule que l'on sélectionne pour l'utilisation de la formule avec un seul argument... or cela ne fonctionne pas !
Function TTC_Test(CODE1 As String)
ht = Range("CODE1").Offset(0, -1).Value
TTC_Test = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End Function
Ce code ci avec un argument ne foncitonne donc pas ! Il n'y a pas une certaine syntaxe à utiliser pour qu'il comprenne ?
oui il faut comme tu le suggères utiliser ce code avec les 2 arguments :
Function TTC_l(CODE1 As String, ht As Single)
TTC_l = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht
End Function
Merci en tout cas pour le temps que tu as pris et cela m'aura été très utile !
Merci à toi
Cordialement
Stéphane Da Silva
Function TTC_Test(CODE1 As String) ht = Range("CODE1").Offset(0, -1).Value TTC_Test = (Application.VLookup(CODE1, Range("MABASE"), 2, False) + 1) * ht End FunctionCe code ci avec un argument ne foncitonne donc pas ! Il n'y a pas une certaine syntaxe à utiliser pour qu'il comprenne ?
Range("CODE1") n'existe toujours pas ! Et même en nommant une plage avec ce nom, tu ne cherches que la valeur contenue dans la même ligne que ta formule. Donc la encore on bloque sur l'identification de la cellule concernée.
Et même si ce n'est qu'un exemple, je ne prendrais jamais le risque de coder une fonction personnalisée dans Excel qui utilises une table de valeur inscrite quelque part dans une feuille. Si tu renommes ou supprime cette table, ta fonction est inutilisable.
Dans ton exemple, il serait donc plus simple, plus sûr et aussi efficace d'écrire directement dans la cellule :
=(RECHERCHEV(B8;MABASE;2;0)+1)*A8
D'accord très bien c'est clair je te remercie pour toutes ces infos !!
Je peux donc cloturer
Merci
Cordialement
Avec plaisir !