Extraire nombre "lié" à un symbole
Bonjour à la communauté.
J'aimerais savoir si il serait possible de réaliser une macro capable d'extraire d'une cellule des nombres liés à leur symbole et de les placer dans "leur" cellule.
Exemple : C6H6O dans la cellule "à extraire" ==> 6 dans une cellule à droite d'une autre contenant C, 6 dans celle à droite de H et 1 dans celle à droite de O. En sachant qu'il y aurait d'autre symbole dont certains de deux lettres (F, N, Br ...)
En vous remerciant d'avance
Bonjour,
Un fichier ?
J'ai édité mon premier message.
Bonsoir,
En attendant mon infirmière (
Function NBELEMMOL(elem As String, mol As String)
Dim h%, n%
Application.Volatile
h = InStr(1, mol, elem, vbBinaryCompare)
If h > 0 Then
n = Val(Right(mol, Len(mol) - h))
NBELEMMOL = IIf(n > 0, n, 1)
Else
NBELEMMOL = ""
End If
End FunctionUtilisation simple : en F4 tu tapes =NBELEMMOL(E4;$I$3) et la formule renvoie 6.
Tu la tires sur la colonne et elle renvoie la valeur pour l'élément figurant en E. Elle renvoie une chaîne vide si l'élément n'est pas trouvé.
Dans la foulée, ayant encore un peu de temps, je me suis penché sur ton calcul de la masse moléculaire (un peu artisanal
Pour l'améliorer, il fallait d'abord compléter la Table, j'ai donc ajouté une colonne à gauche pour les symboles. Et je l'ai nommée Table pour faciliter son utilisation.
A ce stade, une formule de recherche permet de faire le calcul par élément. Il suffit d'en additionner les résultats ensuite. Mais calculer en seule formule, serait mieux...
Cette idée m'a conduit à une nouvelle fonction, personnalisée, qui à partir de la formule moléculaire opérerait la décomposition en 2 colonnes : éléments présents dans la molécule et nombre pour chacun. Fonction matricielle.
Et une fois cette fonction établie, une nouvelle fonction pourrait l'utiliser pour opérer le calcul de la masse directement à partir de la formule moléculaire.
J'ai dû attendre un certain temps après le passage de mon infirmière pour finaliser tout cela...
Function DECOMPMOL(mol As String)
Dim elm(), mlm, c, i%, m%, n As Boolean
Application.Volatile
For i = 1 To Len(mol)
c = Mid(mol, i, 1)
If c Like "[A-Z]" Then
If n Then
mlm = mlm & " " & 1 & " " & c
Else
mlm = mlm & " " & c: n = True
End If
ElseIf c Like "[a-z]" Then
mlm = mlm & c
ElseIf c Like "[0-9]" Then
If n Then
mlm = mlm & " " & c
Do
m = m + 1
c = Mid(mol, i + m, 1)
If c Like "[0-9]" Then
mlm = mlm & c
Else
m = m - 1: Exit Do
End If
Loop While i + m + 1 <= Len(mol)
i = i + m: n = False: m = 0
Else
DECOMPMOL = CVErr(xlErrValue): Exit Function
End If
Else
DECOMPMOL = CVErr(xlErrValue): Exit Function
End If
Next i
If n Then mlm = mlm & " " & 1
mlm = Split(Replace(mlm, " ", "", 1, 1))
ReDim elm(UBound(mlm) \ 2, 1)
For i = 0 To UBound(elm, 1)
elm(i, 0) = mlm(i + m)
m = m + 1: elm(i, 1) = CInt(mlm(i + m))
Next i
DECOMPMOL = elm
End FunctionCette fonction est matricielle. On sélectionne une plage comportant autant de lignes qu'il y a d'éléments dans la molécule (ce qui s'évalue rapidement en observant la formule moléculaire) et 2 colonnes.
On tape la formule : =DECOMPMOL(I3) I3 contenant : C6H6O, on a donc sélectionné préalablement une plage de 3 lignes et 2 colonnes. On valide la formule par la combinaison de touches Ctrl+Maj+Entrée et les éléments sont listés dans la plage en 1re colonne avec leur nombre en 2e colonne.
La formule renvoie #VALEUR! si la formule moléculaire à décomposer n'est pas strictement conforme : respect de la casse (majuscule/minuscule), les symboles doivent avoir la première lettre majuscule, la seconde minuscule s'il y a lieu...
Dernière fonction pour calculer la masse moléculaire :
Function MASSMOL(mol As String)
Dim elm(), mm, i%, e%
Application.Volatile
elm = DECOMPMOL(mol)
On Error GoTo noelm
With [Table]
For i = 0 To UBound(elm, 1)
e = WorksheetFunction.Match(elm(i, 0), .Columns(1), 0)
mm = mm + elm(i, 1) * .Cells(e, 3)
Next i
End With
MASSMOL = mm
Exit Function
noelm:
MASSMOL = CVErr(xlErrNA)
End FunctionCette fonction utilise la précédente pour décomposer la molécule en éléments, elle recueille le tableau (qui est affecté à une plage de cellules lorsqu'on utilise la fonction en feuille de calcul). Elle peut alors récupérer les masses unitaires dans la Table et opérer le calcul.
En tapant : =MASSMOL(I3) on obtient directement le renvoi de la masse moléculaire.
Si un élément ne peut être calculé la formule renvoie #N/A.
Nb: La fonction qui renvoie la composition de la molécule ne contrôle pas l'existence des éléments. Il est donc tout à fait possible d'avoir un symbole (dont l'écriture est conforme) mais ne correspondant à aucun élément... Dans un tel cas, l'élément n'étant pas trouvé dans la Table, le calcul de la masse n'aboutira pas.
Cordialement.
Merci à tous les deux de vous être occupé de mon problème.
Ca marche du tonnerre !
Pour jpbt84, la formule prend seulement en compte les chiffres 1 à 9, mais pas les nombres, peut-être une petite chose à modifier ?
Pour MFerrand, j'ai l'impression que je dois remercier l'infirmière d'avoir été en retard ou bien vous qui aimait être en avance
Merci à tous les deux.
Bonne continuation.
Me signaler si des bogues apparaissent...
Finalement j'ai un petit souci de "compatibilité".
J'ai copié toutes les fonctions personnalisées dans ma feuille Excel qui est composée de plusieurs tableaux.
Pour la fonction permettant de dénombrer chacun des éléments, aucun problème. En revanche je n'arrive pas à faire fonctionner celle qui me permet de calculer la masse. Je pense que la fonction n'arrive pas à retrouver le tableau à utiliser. J'ai essayé de modifier, mais quelque chose m'échappe visiblement. Le tableau est compris entre K4:M4 et K119:M119 en sachant qu'il y a l'entrée Symbol en K3.
Je déteste ma méconnaissance des langages informatique
Si ta table est en K4:M119, tu nommes cette plage Table.
Ou tu la nommes autrement, mais tu modifies en conséquence le nom dans le code de la fonction (il n'apparaît qu'une fois).
C'est bon à force de me d'essayer tout ce qui était imaginable j'ai enfin réussi XD
Merci encore.
Ces deux lignes sont inutiles :
Dim Table()
Table = Sheets("Calculs").Range("K4:M119").Valueet conduisent à des erreurs !
réfère à un nom de plage, nommée Table dans le classeur.
Tu affectes le contenu de plage à un tableau nommé Table. Cela ne correspond plus !
Supprime ces deux lignes et nomme la plage.
NB- Il est recommandé de placer les déclarations de variables systématiquement en tête de procédure. Les diluer dans le corps du code exécutable est un moyen de ne pas s'y retrouver par la suite !
Cordialement.
C'est bon, c'est réglé, merci MFerrand