Fonction Mid

Bonjour,

J'aimerais que ma fonction Mid pointe vers une cellule contenant ma chaîne de caractère mais elle ne me retourne aucune valeur.

Si l'un de vous a une idée.

Merci d'avance.

68essaied.zip (8.34 Ko)

Bonjour Sadness,

replace B3 par Range("B3").Value.

cordialement

Salut,

La variable B3 ne valait rien, il faut écrire range("B3").value :

Ton exemple :

Sub Genere()
'Incrémenter num de facture

Dim TestString As String
Dim LResult As String

For i = 1 To 100
    LResult = Mid(Range("B3").Value, 5, 6)
    TestString = Mid(Range("B3"), 11, 2)
    MsgBox LResult & "/" & TestString & "/" & i
Next

End Sub

Damien

Bonjour patrick33, Bigdams

Merci à vous deux.

Si possible j'aimerais poser 2 questions :

  • J'aimerais afficher ce résultat dans une cellule et dans une Msgbox ( mes compétences s'arrétait dans une msgbox)
  • J'aimerais avoir une vérification avant la génération du numéro par rapport a un autre fichier si ce numéro existe déjà et si il existe qu'il l'incrémente
24essaied.zip (9.52 Ko)
Sub Genere()
'Incrémenter num de facture

Dim TestString As String
Dim LResult As String

For i = 1 To 100
    LResult = Mid(Range("B3").Value, 5, 6)
    TestString = Mid(Range("B3").Value, 11, 2)
    [F16] = LResult & "/" & TestString & "/" & i
Next

End Sub

J'ai réussi l'affichage dans la cellule mais maintenant il ne me reste que la vérification par rapport à un autre fichier si quelqu'un à une piste

Edit : Par contre je n'arrive pas à comprendre pourquoi il est directement à 100, il devrait s'incrémenter que lorsque j appuie sur le bouton

Bonjour,

Quand tu appuies sur le bouton tu lances la macro :

Par contre je n'arrive pas à comprendre pourquoi il est directement à 100, il devrait s'incrémenter que lorsque j appuie sur le bouton

Normal, tu as une boucles FOR. Donc dès que tu appuies cela vas compter de 0 a 100 et t'afficher 100.

Si tu veux que cela s'incremente a chaque click il faut que tu stock la valeur en cours quelque part (a la fin de la macro la valeur de i est reinitialisé.)

Mais, comme en plus tu veux vérifier que ce numéro existe déja et l'incrémenter si c'est le cas, le mieux c'est :

- Verifier la valeur de ce compteur au prélabale = > s'il existe i= compteur +1

=> s'il n'existe pas i= valeur en cours

pour vérifier une valeur dans un autre fichier, tu as plusieurs possibilité, cf un exemple

(A adapter en fonction de tes besoins)

Sub Genere()
'Incrémenter num de facture
Dim i As Long
Dim TestString As String
Dim LResult As String

LResult = Mid(Range("B3").Value, 5, 6)
TestString = Mid(Range("B3").Value, 11, 2)

'Retourne le numéro compteur courant cellule i2
i = Range("i2").Value
i = i + 1 'On incrémente le compteur

'Retourne le numéro de compteur d'un autre fichier et on le compare
valeur = retournevaleur("C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls", "Feuil1", "A1")
If valeur = i Then 'Si valeur compteur identique
    i = i + 1
End If

'On stocke le numéro de compteur courant
Range("i2").Value = i

'On affiche le résultat
MsgBox LResult & "/" & TestString & "/" & i
Range("F6").Value = LResult & "/" & TestString & "/" & i 'On affiche le résultat

End Sub

Function retournevaleur(nomfichier As String, nomonglet As String, cellule As String) As String
Application.ScreenUpdating = False

Dim mywrbk As Workbook
Dim mywrksheet As Worksheet

Set mywrbk = Workbooks.Open(nomfichier, , True) ' Ouverture en ReadOnly
Set mywrksheet = mywrbk.Worksheets(nomonglet)

retournevaleur = mywrksheet.Range(cellule).Value

mywrbk.Close False

Set mywrbk = Nothing
Set mywrksheet = Nothing

Application.ScreenUpdating = True
End Function

En esperant que cela t'aide.

damien

Re-bonjour bigdams,

Alors là je suis désolé mais je suis perdu au niveau de la fonction, j'ai tout compris avant mais je ne comprend pas la fonction.

J'ai testé le code en entier il marche bien même si je n'arrive pas à voir à quel moment il fait le contrôle sur l'autre fichier

Re,

Voici une version commentée en esperant que cela t'aide.

Function retournevaleur(nomfichier As String, nomonglet As String, cellule As String) As String
Application.ScreenUpdating = False 'Permet de ne plus afficher Excel :plus rapide / A commenter si tu veux

Dim mywrbk As Workbook   'Déclaration de l'objet mywrbk en tant que workbook (classeur excel)
Dim mywrksheet As Worksheet  'Déclaration de l'objet mywrksheet en tant que worksheet (onglet)

Set mywrbk = Workbooks.Open(nomfichier, , True) 'instancie l'objet : Ouverture en ReadOnly du fichier passé en paramètre, dans l'exemple
'c'est le fichier :"C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls"

Set mywrksheet = mywrbk.Worksheets(nomonglet) ''instancie l'objet : Potionne sur le nom de l'onglet dans l'exemple :"FEUIL1"

retournevaleur = mywrksheet.Range(cellule).Value 'renvoi la valeur de la cellule, dans l'exemple "A1"

mywrbk.Close False 'on ferme le fichier :"C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls"

Set mywrbk = Nothing 'non necessaire mais c'est plus propre
Set mywrksheet = Nothing 'non necessaire mais c'est plus propre

Application.ScreenUpdating = True 'CF Application.ScreenUpdating = False
End Function

Dans le code j'appelle la fonction comme suit :

valeur = retournevaleur("C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls", "Feuil1", "A1")
If valeur = i Then 'Si valeur compteur identique
   i = i + 1
End If

Sur la ligne

valeur = retournevaleur("C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls", "Feuil1", "A1")

la variable "Valeur" prend la valeur contenu dans la cellule A1 de l'onglet "FEUIL1" du fichier "Damien.xls"

Ensuite:

If valeur = i Then 'Si valeur compteur identique
   i = i + 1
End If

Si i (compteur) = valeur (valeur lu dans l'autre fichier alors j'incremente i (compteur) de 1.

C'est plus clair ?

cette méthode pour ouvrir et aller chercher une donnée est standard. (je pense, à moins que qqun sur le forum ait une meilleur solution)

Aide sur les fonctions :

https://www.excel-pratique.com/fr/vba/procedures_fonctions.php

Dis moi si c'est bon

Damien

Re,

Merci de ces explications je pense avoir compris.

Puis- je rajouter dans ta fonction ces lignes me permettant d'enregistrer chaque nouveau numéro

Set wb = Workbooks.Open("Z:\Historique_Facture.xls") ' Peut être inutile car les déclarations sont déjà faite dans la fonction
Set ws = wb.Worksheets(2012) ' Peut être inutile car les déclarations sont déjà faite dans la fonction

Range("F16").Select
Selection.Copy
Windows("Historique_Facture.xls").Activate
Range("A2").Select
ActiveSheet.Paste

Re,

Ne confondons pas function et sub.

Dans ton code tu a une procédure( sub genere() ) qui fait appelle a une fonction (retournevaleur) pour lire une données dans un autre classeur.

Ensuite le numéro de facture est validé dans la procédure via le code (et la fonction) et on ecrit le numero de dossier dans la cellule F6 :

Range("F6").Value = LResult & "/" & TestString & "/" & i 'On affiche le résultat

Ce que tu souhaites maintenant c'est archiver ce numéro dans un autre fichier Z:\Historique_Facture.xls

Donc le sub genere() doit être modifié comme suit :

Sub genere()

'AJOUT
Dim wsencours As Worksheet
Dim wb As Workbook
Dim ws As Worksheet
Set wsencours = ActiveWorkbook.ActiveSheet
'FIN AJOUT

'.... Le reste du code

Range("F6").Value = LResult & "/" & TestString & "/" & i 'On affiche le résultat

'AJOUT
Set wb = Workbooks.Open("Z:\Historique_Facture.xls")
Set ws = wb.Worksheets("2012")  'Entre guillement car la valeur est une chaine
'Deux solutons pour écrire le resultat dans le fichier :
ws.Range("A2").Value = wsencours.Range("F6") 'Ecrasera a chaque fois l'ancienne valeur en A2
'ou
ws.Range("A65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("F6") 'met la valeur dans la deniere ligne de la colonne A non utilisée

wb.Close True  'On ferme historique_facture en sauvegardant
'FIN AJOUT
End Sub

Tu me suis ?

Damien

Bonjour Bigdams, bonjour le forum

Désolé de cette réponse tardive, avec le déménagement j'ai pas vraiment eu le temps de répondre avant.

Merci de cette piqûre de rappel entre les "function" et les "sub", c'est vrai qu'il m'arrive encore de confondre les 2 même si c'est vrai qu'elles n'ont aucun rapport, la première retourne une valeur et l'autre permet de formater/exécuter celle-ci.

Merci pour le code je viens encore d'apprendre de nouvelles choses rien que ceci :

wb.Close True

pour pouvoir fermer le fichier et l'enregistrer.

J'aurais juste une dernière question et après je ne t'embête plus. J'ai 3 boutons sur 3 feuilles différentes qui lance cette macro mais j'ai remarqué qu'elles commençaient toutes le compteur à 1, existe t'il un moyen simple que les 2 derniers chiffres incrémentés s'incrémente sur toutes les feuilles en même temps.

Exemple :

Feuil1 == 002482/12/72

Feuil2 == 018067/12/01

Feuil3 == 011987/12/33

Merci encore pour tout l'aide apporté sur ce problème, je ne suis pas sur que je m'en serais sortis.

Bonjour,

Si j'ai bien compris ta demande tu veux un compteur globale pour plusieurs feuilles.

La macro aura la cinématique suivante:

  • >Click Bouton
  • >Recuperation du dernier numéro de facture dans une fichier de reference
  • >on incremente cette valeur
  • > on genere le numéro de facture avec ce nouveau numéro
  • > on l'affiche dans la page courante
  • > on le stock dans le fichier de reference.

De ce fait, a chaque lancement on se basera toujours sur le même numéro ?

Cf exemple en attaché

Si je suis a coté dis le moi.

Damien

28essaiedv2.zip (16.64 Ko)

Bonjour,

C'est presque ça la cinématique est la suivante :

==> Click bouton

==> Récupération du dernier numéro de facture dans une fichier de référence

==> On incrémente la dernière valeur

==> On génère le numéro de facture avec ce nouveau numéro

==> On l'affiche dans la page courante

==> On le stock dans le fichier de référence

Le changement de numéro change automatiquement toujours avec le champ 1, le contrôle devrait se faire juste sur les derniers chiffres qui s'incrémente si je ne suis pas clair je peux joindre de nouveau un fichier.

Bonsoir,

C'est ce que j'ai fait dans le fichier envoyé precedemment, teste le. => change les numéro du champs 1 dans la feuille 2 et fait le test.

damien

Ah oui j'étais resté bloqué a un problème de référence.

Ceci étant fait la macro marche magnifiquement bien.

Merci beaucoup du temps consacré sur mon problème. Je vais mettre ce sujet résolu même si ce soir je risque de te reposer une question juste pour que je comprenne un peu mieux la fonction utilisé car ça m'est toujours un peu abstrait de premier abord.

Merci encore

Merci le forum et a bientôt

Bonjour tout le monde,

Je pensais me débrouiller seul, mais malheureusement je pense que j'ai du oublié des choses

Sub Genere()
'Incrémenter num de facture
Dim i As Long
Dim TestString As String
Dim LResult As String
Dim fichierreferencefacture As String
Dim ongletreference As String
Dim colonnereference As String
'Dim cr As String

'Initialisation des valeurs necessaires pour contruire le numéro de facture
LResult = Mid(ActiveSheet.Range("C5").Value, 5, 6)
TestString = Mid(ActiveSheet.Range("C5").Value, 11, 2)

'Inititialisation du fichier de reference
fichierreferencefacture = "Z:\Aviation\historique_facture.xls"
If Dir(fichierreferencefacture) = "" Then
    MsgBox "Fichier de Reference non trouvé"
    Exit Sub
End If

ongletreference = "2012"
colonnereference = "A"

'Si on veut un compteur globale se basant sur le dernier numéro de facture contenu dans le
'fichier d'archivage de capture
tempstr = retournevaleur(fichierreferencefacture, ongletreference, colonnereference)

If tempstr = "" Then  'Si pas de valeur trouvé dans le fichier de reference le compteur commence a 1
    i = 1
Else  'Si on a une valeur avec un identifiant facture contenant un A alors on calcul l'ancienne reference
    tempstr = StrReverse(tempstr) 'Sinon le compteur commence a ancienne valeur +1
    tempstr = Split(tempstr, "/")(0)
    tempstr = StrReverse(tempstr)
    i = CLng(tempstr) + 1
End If

'On affiche le résultat
Range("G38").Value = LResult & "/" & TestString & "/" & i

'On écrit le resultat dans le fichier de reference
ecrirevaleurderniereligne fichierreferencefacture, ongletreference, colonnereference, LResult & "/" & TestString & "/" & i

'ecrirevaleurderniereligne fichierreferencefacture, ongletreference, cr, Range("A1")
'ecrirevaleurderniereligne fichierreferencefacture, ongletreference, Range("B65536").End(xlUp).Offset(1, 0).Value, Range("A1")

'ws.Range("B65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("A1")
'ws.Range("C65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C13")
'ws.Range("D65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C19")
'ws.Range("E65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("H5")
'ws.Range("F65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C5")
'ws.Range("G65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C32")
'ws.Range("H65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C33")
'ws.Range("I65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("C34")
'ws.Range("J65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("H14")
'ws.Range("K65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("H15")
'ws.Range("L65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("H21")
'ws.Range("M65536").End(xlUp).Offset(1, 0).Value = wsencours.Range("H23")

End Sub

En même temps que le numéro de facture j aimerais sauvegarder plusieurs données j'ai fait des essais que j ai laissé en commentaire, je ne dois pas avoir la bonne approche...

Un peu décu de faire aussi vite appel à vous

Re,

Regarde le fichier joint.

Par rapport a ton code ,tu utilises ws.range etc, mais tu n'as pas déclaré ws.

Petit rappel :

Exemple pour lire une données dans un autre onglet du même fichier:

Dim my_workbook As workbook ' => on déclare un objet my_workbook an tant que worbook (classeur,ou fichier excel)

Mais on n'a pas encore définit quel fichier on lui attribue.

Set my_workbook = ActiveWorkbook '=> On définit l'objet my_workbook comme étant le classeur excel en cours d'utilisation( celui qui a la fenêtre active au moment de l'instruction)

A ce moment on pourra interroger cette objet pour récuperer des infos tel que :

msgbox my_workbook.name ' donnera le nom du fichier excel

il en va de même pour les onglets :

Dim ws As Worksheet 'I on declare un objet worksheet (onglet)

'Mais on ne sait toujours pas quel onglet on utilise

set ws = my_workbook.worksheet("Feuil1") 'Ici ws est un objet de type worksheet(onglet) pointant sur l'onglet Feuil1

Donc

msgbox ws.range("A1").value ' renvoi la valeur de la cellule A1 de l'onglet Feuil1

Si on veut écrire la valeur de la cellule A1 de l'onglet FEUIL1 dans la cellule A1 de l'onglet Feuil2 on peut écrire :

Sub test()
Dim my_workbook As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet

Set my_workbook = ActiveWorkbook
Set ws1 = my_workbook.Worksheets("Feuil1")
Set ws2 = my_workbook.Worksheets("Feuil2")

ws2.Range("A1").Value = ws1.Range("A1")
End Sub

Si on veut écrire dans deux classeurs différents alors il faut déclarer 2 workbook :

On va aller chercher la valeur contenue dans la cellule A1 de l'onglet Feuil1 du classeur de reference puis mettre cette valeur dans la cellule A1 de l'onglet Feuil1 du classeur en cours :

Sub test()

Dim my_workbook As Workbook
Dim ref_workbook As Workbook

Dim ws1 As Worksheet
Dim ws2 As Worksheet

Set my_workbook = ActiveWorkbook
Set ref_workbook = Workbooks.Open("C:\Documents and Settings\7001107\Bureau\EXCEL\damien.xls", , True) 'ReadOnly

Set ws1 = my_workbook.Worksheets("Feuil1")
Set ws2 = ref_workbook.Worksheets("Feuil1")

ws1.Range("A1").Value = ws2.Range("A1")

ref_workbook.Close 'on ferme le fichier de reference

End Sub

En esperant t'avoir aidé.

Damien

11essaiedv3.zip (16.49 Ko)

Re,

Merci pour ces explications mais pourquoi le déclare t'on plutôt dans une fonction que dans le sub ?

Re,

On peut le déclarer soit dans le sub, soit dans une fonction.

On pourrait écrire un sub sans aucune fonction, mais cela serait moins lisible.

La fonction permet simplement une meilleur lisibilité ET AUSSI de ne pas repeter plusieurs ligne de code si on doit faire plusieurs fois la même chose.

Par contre si tu fais la declaration dans un sub : Tu ne peux pas utiliser cette déclaration dans le code de ta fonction. Et réciproquement.

(A MOINS de faire la déclaration en Public (ex : public ws as worksheets) en dehors de la function et du sub)) = > A Eviter quand tu peux car:

  • cela prend de la mémoire
  • plus dur a debugger (on ne sait jamais qui a modifié la valeur a moins de passer par toutes les fonctions/sub.)
Mais des fois c'est indispensable..... Cela dépend....(désolé pour la réponse de Normand)

Définition : SUB est une routine permettant de réaliser des actions mais ne renvoi pas de valeur en retour et n'admet pas de paramètres en entrées

Function est une routine permettant des réaliser des actions avec des paramètres en entrées et qui renvoi une valeur en retours.

Exemple : pour ton cas, sans fonction, tu aurais a copier le contenu de la fonction ecrirevaleurderniereligne autant de fois (sans les declarations) que tu veux écrire dans le fichier. Et donc tu aurais des centaines de lignes dans ton code qui font la même chose... Pas super lisible.

Bonne pratique (les miennes) :

Le sub principal doit être le plus court possible afin d'être plus lisible et donc plus facile a modifier et a maintenir. D'où l'usage des fonctions. Je developpe aussi en C++ et c'est la même bonne pratique.

Avant de coder :essayes de decomposer les actions que tu veux réaliser en differents "blocs", chaque "bloc" a des entrées et des sorties. Ton programme principal doit être une suite d'appelle a ces blocs. (Ce n'est pas toujours evident, mais le temps que tu prends a ce moment t'en fera gagner 100 fois plus lors de la résolution/debug de ton programme.)

Damien

Merci de ces explications, j'espère suivre cette démarche dans mes prochaines macros, mais les mauvaises habitudes sont dures.

Encore merci Bigdams pour toute ces explications, le code et le temps passé.

Rechercher des sujets similaires à "fonction mid"