Explication VBA : Facturation automatique
🧾 Macro : annuler_Facture
| Macro anuler facture VBA |
|---|
|
Sub annuler_Facture()
Facturation.Select
If ActiveSheet.ProtectContents = True Then
ActiveSheet.Unprotect
End If
Facturation.Range("F25:F40").Value = ""
'début vider info reglement
Facturation.Range("N17:Q20").Select
Selection.ClearContents
'fin vider info reglement
Facturation.Range("N17").Value = 1
'
'début vider info quantité produit
Range("B25:B41").Select
Selection.ClearContents
'fin vider info quantité produit
'proteger la feuille
ActiveSheet.Protect DrawingObjects:=True, Contents:=True,
Scenarios:=True
End Sub
|
✉️ Création Automatique d'une Nouvelle Facture sur Excel avec VBA
| Macro Ajouter nouvelle facture VBA |
|---|
|
Sub nouveau_Facture() 'Déverrouiller la feuille pour modification If ActiveSheet.ProtectContents = True Then ActiveSheet.Unprotect End If Range("J15:L15").FormulaR1C1 = "=TODAY()" 'Insérer la date du jour Range("J15:L15").FormulaR1C1 = "=TODAY()" 'Nettoyer les anciennes données With Facturation .Range("Q5").ClearContents .Range("O5").FormulaR1C1 = "0" .Range("A12").Value = "" .Range("N17:T23").ClearContents .Range("B25:B41").ClearContents End With ' Ajouter les formules de la facture Call formule_facture 'Cette instruction appelle une autre macro formule_facture qui insère automatiquement toutes les formules nécessaires dans la feuille. 'Générer un nouveau numéro de facture Dim annee As Integer, mois As String, ID As String, anneeFacture As String annee = Year(Date) mois = Format(Month(Date), "00") ID = Right(Facturation.Range("J16"), 3) anneeFacture = Mid(Facturation.Range("J16"), 1, 4) If Not IsNumeric(ID) Or Not IsNumeric(anneeFacture) Then ID = "0000" anneeFacture = annee End If If Int(annee) = Int(anneeFacture) Then Facturation.Range("J16") = annee & mois & Format(Int(ID) + 1, "0000") Else Facturation.Range("J16") = annee & mois & "0001" End If 'Réinitialiser les paiements With Facturation .Range("F25:G40").ClearContents .Range("N17").FormulaR1C1 = "1" End With 'Supprimer les réductions et cacher les lignes With Facturation.Range("H43:L44") .ClearContents .Borders.LineStyle = xlNone End With Facturation.Range("H45:I45").Select ActiveCell.FormulaR1C1 = "Montant Total HT :" Facturation.Range("J45:L45").Select ActiveCell.FormulaR1C1 = "=IFERROR(SUM(R[-21]C:R[-5]C[2]),"""")" Facturation.Rows("43:44").EntireRow.Hidden = True 'Message pour l'utilisateur MsgBox ("Spécifier le type de la facture Cellule : Q5") Facturation.Range("Q5").Select 'Reprotection de la feuille ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True End Sub |
Nous allons explorer une macro VBA appelée nouveau_Facture,
conçue pour préparer automatiquement une feuille Excel pour l'émission d'une
nouvelle facture. C'est une solution idéale pour les utilisateurs qui gèrent
leurs factures sur Excel et souhaitent gagner du temps tout en évitant les
erreurs manuelles.
🔒 1. Déverrouiller la feuille pour modification
If ActiveSheet.ProtectContents = True Then
ActiveSheet.Unprotect
End If
Cette partie teste si la feuille active est protégée (ProtectContents = True) et la déverrouille si besoin, pour autoriser les modifications.
🗓️ 2. Insérer la date du jour
Range("J15:L15").FormulaR1C1 = "=TODAY()"
Cette ligne insère directement la date du jour dans les cellules J15 à L15
grâce à la formule Excel =TODAY() sans avoir besoin de
sélectionner la cellule.
🤧 3. Nettoyer les anciennes données
With Facturation
.Range("Q5").ClearContents
.Range("O5").FormulaR1C1 = "0"
.Range("A12").Value = ""
.Range("N17:T23").ClearContents
.Range("B25:B41").ClearContents
End With
Ces lignes vident les cellules concernées pour préparer une nouvelle facture sans interférence des anciennes données.
➕ 4. Ajouter les formules de la facture
Call formule_facture
Cette instruction appelle une autre macro formule_facture qui
insère automatiquement toutes les formules nécessaires dans la feuille.
📅 5. Générer un nouveau numéro de facture
Dim annee As Integer, mois As String, ID As String, anneeFacture As String
annee = Year(Date)
mois = Format(Month(Date), "00")
ID = Right(Facturation.Range("J16"), 3)
anneeFacture = Mid(Facturation.Range("J16"), 1, 4)
If Not IsNumeric(ID) Or Not IsNumeric(anneeFacture) Then
ID = "0000"
anneeFacture = annee
End If
If Int(annee) = Int(anneeFacture) Then
Facturation.Range("J16") = annee & mois & Format(Int(ID) + 1, "0000")
Else
Facturation.Range("J16") = annee & mois & "0001"
End If
Cette section génère automatiquement un nouveau numéro de facture selon l'année et le mois courant. Elle vérifie que le contenu de la cellule J16 est bien un nombre, pour éviter des erreurs en cas de cellule vide.
💳 6. Réinitialiser les paiements
With Facturation
.Range("F25:G40").ClearContents
.Range("N17").FormulaR1C1 = "1"
End With
On vide les anciennes informations de paiement (quantité, mode, échéance, etc.) et on initialise le nombre de paiements à 1.
❌ 7. Supprimer les réductions et cacher les lignes
With Facturation.Range("H43:L44")
.ClearContents
.Borders.LineStyle = xlNone
End With
Facturation.Range("H45:I45").FormulaR1C1 = "Montant Total HT :"
Facturation.Range("J45:L45").Formula2R1C1 = "=IFERROR(SUM(R[-21]C:R[-5]C[2]),\"\")"
Facturation.Rows("43:44").EntireRow.Hidden = True
Cette section vide les réductions, enlève les bordures, cache les lignes
correspondantes et met à jour le total HT de la facture avec une formule
adaptée au format moderne (Formula2R1C1).
🚨 8. Message pour l'utilisateur
MsgBox ("Spécifier le type de la facture Cellule : Q5")
Facturation.Range("Q5").Select
Une alerte s'affiche pour rappeler à l'utilisateur de préciser le type de facture, puis la cellule Q5 est sélectionnée.
🔐 9. Reprotection de la feuille
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
Enfin, la feuille est de nouveau protégée pour éviter des modifications accidentelles.
✅ Notions VBA Clés Utilisées
| Code VBA | Description |
|---|---|
.Select |
Sélectionne une cellule ou plage de cellules |
.Value |
Modifie le contenu d'une cellule |
.FormulaR1C1 |
Insère une formule au format R1C1 |
.Formula2R1C1 |
Version moderne pour formules complexes |
.ClearContents |
Vide une cellule |
.Protect/.Unprotect |
(Dé)protège une feuille Excel |
Call |
Appelle une autre macro |
MsgBox |
Affiche un message à l'utilisateur |
If...Then...End If |
Structure conditionnelle |
IsNumeric |
Vérifie si une donnée est un nombre |
💡 Astuce : toujours tester si une cellule contient un nombre avant de l'utiliser pour générer un identifiant ou une opération mathématique. Cela permet d'éviter les erreurs d'exécution !
Tu peux adapter cette macro à ta propre feuille Excel en changeant les références de cellules et les noms de feuilles selon tes besoins. C’est un excellent exemple de comment automatiser une tâche répétitive avec VBA
✉️ Enregistrement Automatique d'une Facture sur Excel avec VBA
| Macro enregistrer facture VBA |
|---|
|
Sub facture_enregistrer() If ActiveSheet Is Facturation Then Facturation.Select If Factures_Liste.Range("E10").Value <> Facturation.Range("J16").Value Then Factures_Liste.Range("E10").EntireRow.Insert Factures_Liste.Range("E10").Value = Facturation.Range("J16").Value Factures_Liste.Range("F10").Value = Facturation.Range("J15").Value Factures_Liste.Range("G10").Value = Facturation.Range("E19").Value & "_" & Facturation.Range("E20").Value Factures_Liste.Range("H10").Value = Facturation.Range("J47").Value Factures_Liste.Range("I10").Value = "Impayée" Factures_Liste.Range("L10").Formula2R1C1 = "=YEAR([@Date])" Factures_Liste.Range("M10").Formula2R1C1 = "=MONTH([@Date])"
Dim nomDocument As String, dossierAdresse As String dossierAdresse = Parameters.Range("K12").Value & "\" ''''''''''''''Bonus : vérifier que le dossier existe avant d'enregistrer '''***''''Tu peux ajouter un petit contrôle pour créer le dossier s’il n’existe pas : If Dir(dossierAdresse, vbDirectory) = "" Then MkDir dossierAdresse End If ''''''''''''''Bonus : vérifier que le dossier existe avant d'enregistrer '''***''''Tu peux ajouter un petit contrôle pour créer le dossier s’il n’existe pas : ' Crée le nom du document (sécurisé) enlèves les slash et.. nomDocument = NettoyerNomFichier(Facturation.Range("J16").Value & "_" & Facturation.Range("E19").Value) Factures_Liste.Range("Q10").Value = dossierAdresse & nomDocument & ".pdf" With Factures_Liste.Hyperlinks.Add(Factures_Liste.Range("K10"), Address:=dossierAdresse & nomDocument & ".pdf", TextToDisplay:="Consulter") .Range.Font.Name = "Montserrat" .Range.Font.Color = RGB(60, 65, 205) .Range.Font.Size = 11 End With Dim wb As Workbook, feuille As Worksheet Dim plage As String Dim iVis As XlSheetVisibility Set wb = ThisWorkbook Set feuille = Facturation 'Set feuille = wb.Sheets("Facture") devient--->>>Set feuille = Facturation sans wb quand j'utilise le code de la feuille aulieu de son nom 'Macro utiliser le nom de feuille visible devient Macro utiliser son code feuille VBA 'Sheets("Réglement") devient Factures_Suivie_Règlement 'Sheets("Réglement").Select devient Factures_Suivie_Règlement.Select 'ActiveWorkbook.Worksheets("Réglement")devient Factures_Suivie_Règlement 'If ActiveSheet.Name = "Facture" Then devien If ActiveSheet Is Facturation Then 'Set feuille = wb.Sheets("Facture")devient Set feuille = Facturation sans wb 'rempire les envlope Envlope_Adresse.Range("A2").EntireRow.Insert Envlope_Adresse.Range("A2").Value = Facturation.Range("E19").Value Envlope_Adresse.Range("B2").Value = Facturation.Range("E20").Value Envlope_Adresse.Range("C2").Value = Facturation.Range("A20").Value 'Fin rempire les envlope 'rempire les envlope 'remplire feille reglement Réglement ''''''enlever la protection 'If Factures_Suivie_Règlement.Unprotect = False Then 'ActiveSheet.Unprotect 'End If If Factures_Suivie_Règlement.ProtectContents = True Then Factures_Suivie_Règlement.Unprotect End If Set cell = Factures_Suivie_Règlement.Range("B10:B10") Set tblf = Factures_Suivie_Règlement.ListObjects("T_Suivie_Reglement") ICE = Mid(Facturation.Range("E21"), 5, 20) With Factures_Suivie_Règlement ' liste facture If Facturation.Range("N17").Value <> "" Then 'facture Factures_Suivie_Règlement.Range("E10").EntireRow.Insert Set cell = Factures_Suivie_Règlement.Range("B10:B10") With cell .Offset(0, tblf.ListColumns("ID INTERNE").Index - 1).Value = Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("N°facture").Index - 1).Value = "N°: " & Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("Date Facture").Index - 1).Value = Facturation.Range("J15").Value 'date facture .Offset(0, tblf.ListColumns("Nom du Client").Index - 1).Value = Facturation.Range("E19").Value 'nom du client .Offset(0, tblf.ListColumns("Ville").Index - 1).Value = Facturation.Range("E20").Value 'Ville du client
.Offset(0, tblf.ListColumns("ICE").Index - 1).Value = ICE ' ICE 'Taux Réduction S31 'Montant Réduction Q31 'TOTAL NET H.T. Q32 'TVA Q33 .Offset(0, tblf.ListColumns("Montant TTC").Index - 1).Value = Facturation.Range("Q34").Value ' prix .Offset(0, tblf.ListColumns("Taux Réduction").Index - 1).Value = Facturation.Range("S31").Value 'Taux Réduction .Offset(0, tblf.ListColumns("Montant Réduction").Index - 1).Value = Facturation.Range("Q31").Value 'Montant Réduction .Offset(0, tblf.ListColumns("TOTAL NET H.T.").Index - 1).Value = Facturation.Range("Q32").Value ' TOTAL NET H.T .Offset(0, tblf.ListColumns("Montant TVA").Index - 1).Value = Facturation.Range("Q33").Value ' TVA .Offset(0, tblf.ListColumns("Montant HT").Index - 1).Value = Facturation.Range("Q30").Value ' prix .Offset(0, tblf.ListColumns("TAUX TVA").Index - 1).Value = "20%" 'Désignation des biens et services .Offset(0, tblf.ListColumns("Désignation des biens et services").Index - 1).Value = Facturation.Range("E25").Value ' Désignation
'Nombre de réglement*************************** .Offset(0, tblf.ListColumns("N°REG").Index - 1).Value = Facturation.Range("N17").Value 'NBR paiement .Offset(0, tblf.ListColumns("Mode de paiement").Index - 1).Value = Facturation.Range("O17").Value 'MODE DE REGLEMENT .Offset(0, tblf.ListColumns("N° Chq").Index - 1).Value = Facturation.Range("P17").Value 'N° Cheque .Offset(0, tblf.ListColumns("Montant chaque traite").Index - 1).Value = Facturation.Range("R17").Value 'MONTANT CHAQUE TRAITE End With End If End With 'fin With Factures_Suivie_Règlement ' liste facture With Factures_Suivie_Règlement ' liste facture If Facturation.Range("N18").Value <> "" Then Factures_Suivie_Règlement.Range("E10").EntireRow.Insert Set cell = Factures_Suivie_Règlement.Range("B10:B10") With cell .Offset(0, tblf.ListColumns("ID INTERNE").Index - 1).Value = Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("N°facture").Index - 1).Value = "N°: " & Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("Date Facture").Index - 1).Value = Facturation.Range("J15").Value 'date facture .Offset(0, tblf.ListColumns("Nom du Client").Index - 1).Value = Facturation.Range("E19").Value 'nom du client .Offset(0, tblf.ListColumns("Ville").Index - 1).Value = Facturation.Range("E20").Value 'Ville du client .Offset(0, tblf.ListColumns("ICE").Index - 1).Value = ICE ' ICE 'Taux Réduction S31 'Montant Réduction Q31 'TOTAL NET H.T. Q32 'TVA Q33 .Offset(0, tblf.ListColumns("Montant TTC").Index - 1).Value = Facturation.Range("Q34").Value ' prix .Offset(0, tblf.ListColumns("Taux Réduction").Index - 1).Value = Facturation.Range("S31").Value 'Taux Réduction .Offset(0, tblf.ListColumns("Montant Réduction").Index - 1).Value = Facturation.Range("Q31").Value 'Montant Réduction .Offset(0, tblf.ListColumns("TOTAL NET H.T.").Index - 1).Value = Facturation.Range("Q32").Value ' TOTAL NET H.T .Offset(0, tblf.ListColumns("Montant TVA").Index - 1).Value = Facturation.Range("Q33").Value ' TVA .Offset(0, tblf.ListColumns("Montant HT").Index - 1).Value = Facturation.Range("Q30").Value ' prix .Offset(0, tblf.ListColumns("TAUX TVA").Index - 1).Value = "20%" 'Désignation des biens et services .Offset(0, tblf.ListColumns("Désignation des biens et services").Index - 1).Value = Facturation.Range("E25").Value ' Désignation 'Nombre de réglement*************************** .Offset(0, tblf.ListColumns("N°REG").Index - 1).Value = Facturation.Range("N18").Value 'NBR paiement .Offset(0, tblf.ListColumns("Mode de paiement").Index - 1).Value = Facturation.Range("O18").Value 'MODE DE REGLEMENT .Offset(0, tblf.ListColumns("N° Chq").Index - 1).Value = Facturation.Range("P18").Value 'N° Cheque .Offset(0, tblf.ListColumns("Montant chaque traite").Index - 1).Value = Facturation.Range("R18").Value 'MONTANT CHAQUE TRAITE End With End If End With 'fin With Factures_Suivie_Règlement ' liste facture With Factures_Suivie_Règlement ' liste facture If Facturation.Range("N19").Value <> "" Then Factures_Suivie_Règlement.Range("B10").EntireRow.Insert Set cell = Factures_Suivie_Règlement.Range("B10:B10") With cell .Offset(0, tblf.ListColumns("ID INTERNE").Index - 1).Value = Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("N°facture").Index - 1).Value = "N°: " & Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("Date Facture").Index - 1).Value = Facturation.Range("J15").Value 'date facture .Offset(0, tblf.ListColumns("Nom du Client").Index - 1).Value = Facturation.Range("E19").Value 'nom du client .Offset(0, tblf.ListColumns("Ville").Index - 1).Value = Facturation.Range("E20").Value 'Ville du client .Offset(0, tblf.ListColumns("ICE").Index - 1).Value = ICE ' ICE 'Taux Réduction S31 'Montant Réduction Q31 'TOTAL NET H.T. Q32 'TVA Q33 .Offset(0, tblf.ListColumns("Montant TTC").Index - 1).Value = Facturation.Range("Q34").Value ' prix .Offset(0, tblf.ListColumns("Taux Réduction").Index - 1).Value = Facturation.Range("S31").Value 'Taux Réduction .Offset(0, tblf.ListColumns("Montant Réduction").Index - 1).Value = Facturation.Range("Q31").Value 'Montant Réduction .Offset(0, tblf.ListColumns("TOTAL NET H.T.").Index - 1).Value = Facturation.Range("Q32").Value ' TOTAL NET H.T .Offset(0, tblf.ListColumns("Montant TVA").Index - 1).Value = Facturation.Range("Q33").Value ' TVA .Offset(0, tblf.ListColumns("Montant HT").Index - 1).Value = Facturation.Range("Q30").Value ' prix .Offset(0, tblf.ListColumns("TAUX TVA").Index - 1).Value = "20%" 'Désignation des biens et services .Offset(0, tblf.ListColumns("Désignation des biens et services").Index - 1).Value = Facturation.Range("E25").Value ' Désignation
'Nombre de réglement*************************** .Offset(0, tblf.ListColumns("N°REG").Index - 1).Value = Facturation.Range("N19").Value 'NBR paiement .Offset(0, tblf.ListColumns("Mode de paiement").Index - 1).Value = Facturation.Range("O19").Value 'MODE DE REGLEMENT .Offset(0, tblf.ListColumns("N° Chq").Index - 1).Value = Facturation.Range("P19").Value 'N° Cheque .Offset(0, tblf.ListColumns("Montant chaque traite").Index - 1).Value = Facturation.Range("R19").Value 'MONTANT CHAQUE TRAITE End With End If End With 'fin With Factures_Suivie_Règlement ' liste facture With Factures_Suivie_Règlement ' liste facture If Facturation.Range("N20").Value <> "" Then Factures_Suivie_Règlement.Range("B10").EntireRow.Insert Set cell = Factures_Suivie_Règlement.Range("B10:B10") With cell .Offset(0, tblf.ListColumns("ID INTERNE").Index - 1).Value = Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("N°facture").Index - 1).Value = "N°: " & Facturation.Range("J16").Value .Offset(0, tblf.ListColumns("Date Facture").Index - 1).Value = Facturation.Range("J15").Value 'date facture .Offset(0, tblf.ListColumns("Nom du Client").Index - 1).Value = Facturation.Range("E19").Value 'nom du client .Offset(0, tblf.ListColumns("Ville").Index - 1).Value = Facturation.Range("E20").Value 'Ville du client .Offset(0, tblf.ListColumns("ICE").Index - 1).Value = ICE ' ICE 'Taux Réduction S31 'Montant Réduction Q31 'TOTAL NET H.T. Q32 'TVA Q33 .Offset(0, tblf.ListColumns("Montant TTC").Index - 1).Value = Facturation.Range("Q34").Value ' prix .Offset(0, tblf.ListColumns("Taux Réduction").Index - 1).Value = Facturation.Range("S31").Value 'Taux Réduction .Offset(0, tblf.ListColumns("Montant Réduction").Index - 1).Value = Facturation.Range("Q31").Value 'Montant Réduction .Offset(0, tblf.ListColumns("TOTAL NET H.T.").Index - 1).Value = Facturation.Range("Q32").Value ' TOTAL NET H.T .Offset(0, tblf.ListColumns("Montant TVA").Index - 1).Value = Facturation.Range("Q33").Value ' TVA .Offset(0, tblf.ListColumns("Montant HT").Index - 1).Value = Facturation.Range("Q30").Value ' prix .Offset(0, tblf.ListColumns("TAUX TVA").Index - 1).Value = "20%" 'Désignation des biens et services .Offset(0, tblf.ListColumns("Désignation des biens et services").Index - 1).Value = Facturation.Range("E25").Value ' Désignation 'Nombre de réglement*************************** .Offset(0, tblf.ListColumns("N°REG").Index - 1).Value = Facturation.Range("N20").Value 'NBR paiement .Offset(0, tblf.ListColumns("Mode de paiement").Index - 1).Value = Facturation.Range("O20").Value 'MODE DE REGLEMENT .Offset(0, tblf.ListColumns("N° Chq").Index - 1).Value = Facturation.Range("P20").Value 'N° Cheque .Offset(0, tblf.ListColumns("Montant chaque traite").Index - 1).Value = Facturation.Range("R20").Value 'MONTANT CHAQUE TRAITE
End With End If End With 'fin With Factures_Suivie_Règlement ' liste facture 'fin remplire feille reglement Réglement 'fin remplire feille reglement Réglement
''''''proteger la feuille réglement Factures_Suivie_Règlement.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True 'Mettre à plage l adresse de la plage à imprimer plage = "$C$8:$M$64" Application.ScreenUpdating = False With feuille.PageSetup '**************'**************il faut que le nom d'école ne comporte pas les slashe verifier le nom'**************'************** .PrintArea = plage .FitToPagesTall = 1 .FitToPagesWide = 1 .LeftMargin = Application.InchesToPoints(0) .RightMargin = Application.InchesToPoints(0) .TopMargin = Application.InchesToPoints(0) .BottomMargin = Application.InchesToPoints(0) End With With feuille '**************'**************il faut que le nom d'école ne comporte pas les slashe verifier le nom'**************'************** With feuille '**************'**************il faut que le nom d'école ne comporte pas les slashe verifier le nom'**************'************** iVis = .Visible .Visible = xlSheetVisible .Activate .ExportAsFixedFormat Type:=xlTypePDF, _ Filename:=dossierAdresse & nomDocument & ".pdf", _ Quality:=xlQualityStandard, IncludeDocProperties:=True, _ IgnorePrintAreas:=False, OpenAfterPublish:=True .Visible = iVis End With Application.ScreenUpdating = True End With Application.ScreenUpdating = True Else MsgBox " Même num facture" End If Else MsgBox "il faut être dans la feille facture" End If End Sub |
Voici une explication claire, étape par étape, des bases VBA utilisées dans
ta macro facture_enregistrer.
On va décortiquer les principales structures et syntaxes utilisées dans ce
code afin de comprendre, même pour les débutent.
🔧 1. Déclaration de la procédure
Cette ligne déclare une macro nommée
facture_enregistrer. Le mot-clé
Sub signifie "Subroutine", soit
une
procédure qui ne retourne pas de valeur. Elle peut être lancée manuellement ou appelée par un autre code.
🧾 2. Vérifier que la feuille active est bien la feuille de facturation
Ici, ActiveSheet représente la
feuille actuellement affichée.
Facturation est le
nom de code VBA de la
feuille (et non son nom visible par l’utilisateur).
Is est utilisé pour
comparer deux objets (ici,
deux feuilles Excel).
📥 3. Vérification si la facture est déjà enregistrée
On vérifie ici si la valeur dans la cellule
E10 de la feuille
Factures_Liste est
différente de celle dans
J16 de la feuille
Facturation. Cela permet
d’éviter d’enregistrer deux fois la même facture.
🧩 4. Insertion d'une ligne et remplissage de données
Cette ligne insère une nouvelle ligne vide avant la ligne 10, pour ajouter une nouvelle facture.
Les lignes suivantes remplissent ensuite plusieurs cellules avec les valeurs
de la feuille Facturation :
👉 Formula2R1C1 est une
syntaxe de formule compatible avec les
Tableaux Excel (ListObjects). Elle permet d’utiliser des formules dynamiques avec les noms de colonnes.
📁 5. Création du dossier si besoin
-
Dir(...)vérifie si un dossier existe. -
MkDircrée le dossier si nécessaire.
🔗 6. Création d’un lien hypertexte
Cela insère un lien dans la cellule
K10 qui pointe vers le
fichier PDF de la facture, avec une mise en forme personnalisée.
✉️ 7. Ajout des coordonnées dans une feuille "Enveloppe"
Même principe que précédemment : on ajoute une ligne vide en haut puis on y insère le nom, la ville et l'adresse du client.
🛡️ 8. Déprotéger la feuille si besoin
Cette partie vérifie si la feuille est protégée (verrouillée), et la déverrouille temporairement pour pouvoir y écrire.
📊 9. Enregistrement des paiements (jusqu’à 4 échéances)
Les blocs
If Facturation.Range("N17").Value <> "" Then
à N20 sont très similaires.
Pour chaque échéance de paiement, le code :
-
Insère une nouvelle ligne
-
Remplit les informations de la facture
-
Ajoute les détails du règlement (mode de paiement, n° chèque, montant, etc.)
🔁 Récapitulatif des techniques VBA utilisées
| Élément | Explication |
|---|---|
Sub ... End Sub
|
Crée une macro |
If ... Then ... End If
|
Condition |
.Insert
|
Insère une ligne ou colonne |
.Value,
.Formula2R1C1
|
Écrit des valeurs ou des formules |
With ... End With
|
Simplifie l’écriture répétitive |
Dir,
MkDir
|
Gère les dossiers |
.Hyperlinks.Add
|
Ajoute un lien |
ListObjects,
.ListColumns
|
Utilise les tableaux Excel |
.Offset(row, col)
|
Accède à une cellule relative |
Unprotect
|
Déverrouille une feuille protégée |
✉️ Ajout des formules à la facture automatiquement sur Excel avec VBA
| VBA formule_facture |
|---|
|
Sub formule_facture() ' formule_facture Macro INFO ' ' Facturation.Range("A5").Select ActiveCell.Formula2R1C1 = "='Liste Factures'!R[5]C[4]"
Facturation.Range("A6").Select ActiveCell.Formula2R1C1 = "=MAX('Liste Factures'!R[4]C[4]:R[98189]C[4])"
Facturation.Range("A4").Select ActiveCell.Formula2R1C1 = "Num Derniere Facture"
Facturation.Range("B5").Select ActiveCell.Formula2R1C1 = _ "=IF(RC[-1]=R[11]C[8],""num dernier facture"",IF(R[11]C[8]=RC[-1]+1,""OK dernier num +1""))"
Facturation.Range("B6").Select ActiveCell.Formula2R1C1 = "Max num"
Facturation.Range("A11").Select ActiveCell.Formula2R1C1 = "Recherche"
Facturation.Range("A13").Select ActiveCell.Formula2R1C1 = "ID SMS"
Facturation.Range("A14").Select ActiveCell.Formula2R1C1 = "Non ecole SMS"
Facturation.Range("B13").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(IF(R[-8]C[15]=""Facture SMS"",LEFT(R[-1]C[-1],FIND("" "",R[-1]C[-1])-1),""""),"""")"
Facturation.Range("B14").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(IF(R[-9]C[15]<>""Facture SMS"",R12C1,MID(R12C1,SEARCH("" "",R12C1)+1,100)),"""")"
Facturation.Range("A17").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(IF(R[-12]C17=""Facture SMS"","" Nom Client SMS"","" Nom Ecole""),"""")"
Facturation.Range("A18").Select ActiveCell.Formula2R1C1 = _ "=IF(R[-13]C[16]<>""Facture SMS"",IFERROR(INDEX(Clients[Nom Facture],MATCH(UPPER(SUBSTITUTE(R12C1,"" "","""")),UPPER(SUBSTITUTE(Clients[Nom Facture],"" "","""")),0)),""""),IFERROR(INDEX(Clients[Nom Facture],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Clients[ID SMS],"" "",""""),0)),INDEX(clientsms[Nom ecole Facture],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(cli" & _ "entsms[ID],"" "",""""),0))))" & _ ""
Facturation.Range("A19").Select ActiveCell.Formula2R1C1 = "Adresse"
Facturation.Range("A20").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(INDEX(Clients[Adresse],MATCH(SUBSTITUTE(R19C5,"" "",""""),SUBSTITUTE(Clients[Nom Facture],"" "",""""),0)),"""")"
Facturation.Range("A24").Formula2R1C1 = "Date fin OLD CM : " Facturation.Range("A25").Formula2R1C1 = "quantité produit 1" Facturation.Range("A26").Formula2R1C1 = "quantité produit 2" Facturation.Range("A27").Formula2R1C1 = "quantité produit 3" Facturation.Range("A28").Formula2R1C1 = "quantité produit 4" Facturation.Range("A29").Formula2R1C1 = "quantité produit 5" Facturation.Range("A30").Formula2R1C1 = "quantité produit 6" Facturation.Range("A31").Formula2R1C1 = "quantité produit 7" Facturation.Range("A32").Formula2R1C1 = "quantité produit 8" Facturation.Range("A33").Formula2R1C1 = "quantité produit 9" Facturation.Range("A34").Formula2R1C1 = "quantité produit 10" Facturation.Range("A35").Formula2R1C1 = "quantité produit 11" Facturation.Range("A36").Formula2R1C1 = "quantité produit 12" Facturation.Range("A37").Formula2R1C1 = "quantité produit 13" Facturation.Range("A38").Formula2R1C1 = "quantité produit 14" Facturation.Range("A39").Formula2R1C1 = "quantité produit 15" Facturation.Range("A40").Formula2R1C1 = "quantité produit 16" Facturation.Range("A41").Formula2R1C1 = "quantité produit 17"
'pour les cellule fusioner voudrai mieu utiliser .select
Facturation.Range("E19").Select ActiveCell.Formula2R1C1 = _ "=IF(R[-14]C[12]<>""Facture SMS"",IFERROR(INDEX(Clients[Nom Facture],MATCH(UPPER(SUBSTITUTE(R12C1,"" "","""")),UPPER(SUBSTITUTE(Clients[Nom Facture],"" "","""")),0)),""""),IFERROR(INDEX(Clients[Nom Facture],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Clients[ID SMS],"" "",""""),0)),INDEX(clientsms[Nom ecole Facture],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(cli" & _ "entsms[ID],"" "",""""),0))))" & _ "" Facturation.Range("E20").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(INDEX(Clients[Ville],MATCH(UPPER(SUBSTITUTE(R19C5,"" "","""")),UPPER(SUBSTITUTE(Clients[Nom Facture],"" "","""")),0)),"""")" Facturation.Range("E21").Select ActiveCell.Formula2R1C1 = _ "=IFERROR(IFERROR(""ICE ""& INDEX(Clients[ICE],MATCH(UPPER(SUBSTITUTE(R19C5,"" "","""")),UPPER(SUBSTITUTE(Clients[Nom Facture],"" "","""")),0)),""""),"""")" ' FIN formule_facture Macro INFO 'formule_facture_CALCUL Macro ' 'on utillise with et end with pour etendre la formule à toute la plage que j'ai mis dans with With Facturation.Range("E25:E41") .Formula2R1C1 = _ "=IFERROR(IF(VLOOKUP(RC[1],Produits,2,FALSE)<>"""",VLOOKUP(RC[1],Produits,2,FALSE),IF(VLOOKUP(RC[1],Produits,2,FALSE)="""","""")),"""")" End With
With Facturation.Range("H25:H41") .Formula2R1C1 = _ "=IFERROR(IF(RC[-2]="""","""",IF(AND(R5C17=""Facture SMS"",RC[-2]=""Abonnement mensuel"")," & Chr(10) & "INDEX(Consom_SMS_par_mois!C[-2],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Consom_SMS_par_mois!C[-6],"" "",""""),0))," & Chr(10) & "IF(AND(R5C17=""Facture SMS"",RC[-2]<>""Abonnement mensuel""),""""," & Chr(10) & "IF(AND(R5C17<>""Facture SMS"",RC[-2]<>"""",RC[-6]>0),RC[-6],"""")))),"""")" End With With Facturation.Range("I25:I41") .Formula2R1C1 = _ "=IFERROR(" & Chr(10) & " IF(AND(R5C17=""Facture SMS"",RC[-3]=""Abonnement mensuel"")," & Chr(10) & " INDEX(Consom_SMS_par_mois!C[-2],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Consom_SMS_par_mois!C[-7],"" "",""""),0))," & Chr(10) & " IF(AND(R5C17=""Facture SMS"",RC[-3]=""Frais d'abonnement et service SMS."")," & Chr(10) & " INDEX(Consom_SMS_par_mois!C,MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Consom_SMS_pa" & _ "r_mois!C[-7],"" "",""""),0))," & Chr(10) & " IF(AND(R5C17=""Facture SMS"",RC[-3]<>""Abonnement mensuel"",RC[-3]<>""Frais d'abonnement et service SMS."")," & Chr(10) & " """"," & Chr(10) & " IF(AND(R5C17<>""Facture SMS"",RC[-3]=""Pack SMS Forfaitaire"")," & Chr(10) & " INDEX(Tab_SMS_Forfait_Prix_unite,MATCH(1,(RC[-1]>=Tab_SMS_Forfait_Palier_Min)*(RC[-1]<Tab_SMS_Forfait_Palier_Max),0))," & Chr(10) & " IF(AND(R5C17<>""Facture SM" & _ "S"",RC[-3]<>""Pack SMS Forfaitaire"")," & Chr(10) & " VLOOKUP(RC[-3],Produits,3,FALSE)" & Chr(10) & " )))))," & Chr(10) & """"")" & _ "" End With With Facturation.Range("J25:L41") .Formula2R1C1 = _ "=IFERROR(" & Chr(10) & "IF(AND(R5C17=""Facture SMS"",RC[-4]=""Abonnement mensuel"")," & Chr(10) & "INDEX(Consom_SMS_par_mois!C[-2],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Consom_SMS_par_mois!C[-8],"" "",""""),0))," & Chr(10) & "IF(AND(R5C17=""Facture SMS"",RC[-4]=""Frais d'abonnement et service SMS."")," & Chr(10) & "INDEX(Consom_SMS_par_mois!C[-1],MATCH(SUBSTITUTE(R13C2,"" "",""""),SUBSTITUTE(Consom_SMS_par_mois!C" & _ "[-8],"" "",""""),0))," & Chr(10) & "IF(AND(R5C17=""Facture SMS"",RC[-4]<>""Abonnement mensuel"",RC[-4]<>""Frais d'abonnement et service SMS."")," & Chr(10) & """""," & Chr(10) & "IF(AND(R5C17<>""Facture SMS"",RC[-1]="""")," & Chr(10) & """""," & Chr(10) & "IF(AND(R5C17<>""Facture SMS"",RC[-2]<>"""")," & Chr(10) & "RC[-2]*RC[-1]," & Chr(10) & "IF(AND(R5C17<>""Facture SMS"",RC[-2]="""")," & Chr(10) & "RC[-1]))))))," & Chr(10) & """"")" & _ "" End With 'les élément coté droit en dehors de la feuille imprimer de la facture pour rendre les élement mentant total tva ...cnum c'est à dire numéro With Facturation .Range("Q30").Formula2R1C1 = "=IF(AND(R27C16<>"""",R[13]C[-7]>0),VALUE(R[13]C[-7]),VALUE(R[15]C[-7]))" .Range("Q32").Formula2R1C1 = "=IF(R27C16<>"""",IF(R[13]C[-7]>0,VALUE(R[13]C[-7]),""""),"""")" .Range("Q33").Formula2R1C1 = "=IF(R27C16<>"""",IF(R[13]C[-7]>0,VALUE(R[13]C[-7]),""""),IF(R[13]C[-7]>0,VALUE(R[13]C[-7]),""""))" .Range("Q34").Formula2R1C1 = "=IF(R27C16<>"""",IF(R[13]C[-7]>0,VALUE(R[13]C[-7]),""""),IF(R[13]C[-7]>0,VALUE(R[13]C[-7]),""""))"
.Range("S31").Formula2R1C1 = "=IF(R27C16<>"""",VALUE(R5C15),"""")" .Range("O31").Formula2R1C1 = "Remise :"
.Range("O30").Formula2R1C1 = "Montant Total HT :" .Range("O32").Formula2R1C1 = "TOTAL NET H.T." .Range("O33").Formula2R1C1 = "TVA 20% :" .Range("O34").Formula2R1C1 = "Montant Total TTC :"
.Range("O27").Formula2R1C1 = "remise" .Range("P27").Formula2R1C1 = "=IF(ISNUMBER(SEARCH(""remise"",R[17]C[-8],1)),""Oui"","""")"
End With 'fin 'les élément coté droit en dehors de la feuille imprimer de la facture pour rendre les élement mentant total tva ...cnum c'est à dire numéro 'montant en lettre Facturation.Range("E50").Formula2R1C1 = _ "=""Arrêter la présente facture à la somme de : ""&@chiffrelettre(R[-3]C[5])&"" toutes taxes comprises."""
'montant en lettre 'fin 'formule_facture_CALCUL Macro 'mise en forme trai de fin Range("J25:L25").Select Selection.AutoFill Destination:=Range("J25:L41"), Type:=xlFillDefault Range("J25:L41").Select Range("E41").Select ActiveWindow.SmallScroll Down:=4 Range("E41:L41").Select Selection.Borders(xlDiagonalDown).LineStyle = xlNone Selection.Borders(xlDiagonalUp).LineStyle = xlNone Selection.Borders(xlEdgeLeft).LineStyle = xlNone Selection.Borders(xlEdgeTop).LineStyle = xlNone With Selection.Borders(xlEdgeBottom) .LineStyle = xlContinuous .ThemeColor = 5 .TintAndShade = 0 .Weight = xlMedium End With Selection.Borders(xlEdgeRight).LineStyle = xlNone Selection.Borders(xlInsideVertical).LineStyle = xlNone Selection.Borders(xlInsideHorizontal).LineStyle = xlNone 'mise en forme trai de fin Application.Calculation = xlCalculationAutomatic Application.Calculate '.Formula2R1C1 est indispensable dans certains cas récents ' .FormulaR1C1 : ancienne méthode, fonctionne avec la majorité des formules simples. ' .Formula2R1C1 : méthode plus récente qui gère mieux : ' les cellules fusionnées, ' les formules dynamiques (comme FILTER, SORT, LET, LAMBDA, etc.), ' les plages nommées structurées (comme Clients[Nom Facture]), ' les tableaux Excel (ListObjects). End Sub |
🔍
Structure générale de la macro
formule_facture
-
Insertion de formules d’en-tête (cellules A4 à B6)
Ces lignes récupèrent et comparent le dernier numéro de facture à celui en cours pour vérifier la continuité. -
Bloc de saisie client et info SMS (cellules A11 à A21)
Formules conditionnelles pour afficher les informations du client ou de l'école selon le type de facture ("Facture SMS" ou non). -
Bloc quantités de produits (cellules A24 à A41)
Tu ajoutes ici des étiquettes de lignes de produits (quantité produit 1, 2, ...). -
Bloc E25 à L41 : Calculs dynamiques
Tu utilises des formulesIF,VLOOKUP,INDEX,MATCHpour calculer :-
Nom du produit
-
Quantité selon la consommation ou la saisie
-
Prix unitaire selon type de facture
-
Montants totaux (colonne J à L)
-
-
Bloc montant total (Q30 à Q34)
Tu calcules les montants HT, TVA, TTC, etc. -
Montant en lettres (E50)
Formule utilisant une fonction personnalisée@chiffrelettre. -
Mise en forme (bordures)
Tu ajoutes une ligne de fin avec une bordure épaisse pour clôturer le tableau.
🧩 Les ListObjects dans
Excel VBA : des tableaux intelligents pour des formules plus robustes
Quand on travaille avec des macros VBA ou même des formules dans Excel, on peut utiliser deux types de plages de données :
-
des plages classiques (comme
A2:A100) -
ou des ListObjects, qu’on appelle aussi tableaux Excel structurés (comme
Clients[Nom Facture])
🎯 C’est quoi un ListObject ?
C’est un tableau nommé, structuré et intelligent dans Excel.
Par exemple, si tu as une liste de clients comme celle-ci :
| Nom Facture | Ecole | Nom Client | Ville |
|---|---|---|---|
| SMS001 | ABC | Mr X | Rabat |
| SMS002 | DEF | Mme Y | Casa |
… et que tu la convertis en tableau avec Ctrl + T (ou via l’onglet "Insertion > Tableau"), alors elle devient un ListObject.
Tu peux ensuite lui donner un nom dans l’onglet
Création de tableau (par
exemple Clients), et chacune
des colonnes aura un nom structuré, comme :
-
Clients[Nom Facture] -
Clients[Nom Client] -
Clients[Ecole]
✅ Pourquoi utiliser les ListObjects dans VBA et les formules ?
1. C’est plus lisible :
Au lieu d’écrire
=VLOOKUP(A1, A2:D100, 2, FALSE)
Tu peux écrire :
=VLOOKUP(A1, Clients, 2, FALSE)
2. C’est plus dynamique :
Si tu ajoutes une nouvelle ligne, le tableau se met à jour
automatiquement.
Pas besoin de modifier la plage de recherche dans ta macro ou formule.
3. C’est plus robuste :
-
Tu évites les erreurs liées aux lignes manquantes
-
Tu peux structurer tes recherches par nom de colonne (avec
INDEX/MATCH)
🔁 Exemple dans ta macro
Dans la ligne suivante de la macro :
je fais une
recherche directe dans le tableau
Clients, en prenant la colonne
Nom Facture comme critère et
Ecole comme valeur de retour.
Cela remplace une formule complexe du type :
Mais ici, même si la base
Clients s’agrandit,
ta formule reste valide et automatique
💡
🛠️ Comment créer un tableau structuré dans Excel ?
-
Sélectionne tes données (entête comprise)
-
Clique sur Insertion > Tableau
-
Coche "Mon tableau comporte des en-têtes"
-
Donne-lui un nom via l’onglet "Création de tableau" (par exemple :
Clients)
📄 Remplissage automatique de la désignation d'une facture de maintenance
📌 À quoi sert cette macro ?
La macro Maintenance() remplie automatiquement des
lignes de désignation pour une facture de maintenance, en
s’appuyant sur un tableau structuré dans la feuille
Param CL & PRIX.
📁 Où modifier les informations de maintenance ?
Les désignations sont stockées dans le tableau structuré nommé
Tabl_maintenance1 dans la feuille
Param CL & PRIX.
- La 2e colonne contient les désignations.
-
Les 3 premières lignes remplissent automatiquement
F25,F26,F27de la facture.
⚙️ Ce que fait la macro
- Vérifie que la feuille active est bien Facturation.
- Déverrouille la feuille si elle est protégée.
- Efface les anciennes données : désignations, quantités, règlement.
-
Met à jour certaines cellules :
Q5= "Autre Facture",N17= 1. - Remplit les désignations depuis le tableau structuré.
- Reprotège la feuille à la fin.
🔧 Code de la macro
Sub Maintenance()
If ActiveSheet Is Facturation Then
If ActiveSheet.ProtectContents = True Then
ActiveSheet.Unprotect
End If
' Vider les anciennes données
Facturation.Range("F25:F40").Value = ""
Facturation.Range("N17:Q20").ClearContents
Facturation.Range("B25:B41").ClearContents
Facturation.Range("N17").Value = 1
' Mise à jour de la facture
Facturation.Range("Q5").Value = "Autre Facture"
Facturation.Range("F25").Value = Param_CL_et_PRIX.ListObjects("Tabl_maintenance1").DataBodyRange.Cells(1, 2).Value
Facturation.Range("F26").Value = Param_CL_et_PRIX.ListObjects("Tabl_maintenance1").DataBodyRange.Cells(2, 2).Value
Facturation.Range("F27").Value = Param_CL_et_PRIX.ListObjects("Tabl_maintenance1").DataBodyRange.Cells(3, 2).Value
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
Else
MsgBox "Il faut être dans la feuille facture"
End If
End Sub🧩 Décomposition de la ligne de code
Facturation.Range("F25").Value = Param_CL_et_PRIX.ListObjects("Tabl_maintenance1").DataBodyRange.Cells(1, 2).Value
📌 Détail :
-
Facturation.Range("F25").Value
-
Facturation : fait référence à la feuille de calcul nommée "Facturation".
-
Range("F25") : désigne la cellule F25 sur cette feuille.
-
.Value : représente la valeur contenue dans cette cellule.
👉 Cette partie du code indique que nous allons affecter une valeur à la cellule F25 de la feuille "Facturation".
-
Param_CL_et_PRIX.ListObjects("Tabl_maintenance1")
-
Param_CL_et_PRIX : fait référence à la feuille de calcul nommée "Param CL & PRIX".
-
ListObjects("Tabl_maintenance1") : accède au tableau structuré nommé "Tabl_maintenance1" sur cette feuille.
NB : Tabl_maintenance1 doit être une chaîne de caractères (entre guillemets), car c’est le nom du tableau structuré (ListObject)
Tabl_maintenance1 doit être une chaîne de caractères (entre guillemets), car c’est le nom du tableau structuré (ListObject)
👉 Cette partie du code permet d'accéder au tableau structuré spécifique contenant les données de maintenance.
-
.DataBodyRange.Cells(1, 2).Value
-
.DataBodyRange : représente la plage de données du tableau, excluant les en-têtes.
-
.Cells(1, 2) : sélectionne la cellule située à la première ligne et deuxième colonne de la plage de données.
-
.Value : extrait la valeur contenue dans cette cellule.Microsoft Learn
👉 Cette partie du code récupère la valeur de la première ligne, deuxième colonne du tableau "Tabl_maintenance1".
📝 Résumé
Cette ligne de code copie la valeur de la première ligne, deuxième colonne du tableau "Tabl_maintenance1" situé sur la feuille "Param CL & PRIX", et la colle dans la cellule F25 de la feuille "Facturation".
🔄 Exemple visuel
Supposons que le tableau "Tabl_maintenance1" ressemble à ceci :
Code Désignation M001 Entretien mensuel M002 Révision annuelle M003 Intervention rapide
La ligne de code ci-dessus prendra la valeur "Entretien mensuel" (première ligne, deuxième colonne) et la placera dans la cellule F25 de la feuille "Facturation".
📌 Points importants
-
Les noms de feuilles et de tableaux doivent correspondre exactement à ceux utilisés dans votre classeur Excel.
-
Si le tableau "Tabl_maintenance1" est vide, la propriété .DataBodyRange renverra une erreur. Il est donc conseillé de vérifier que le tableau contient des données avant d'accéder à ses cellules.
Commentaires
Enregistrer un commentaire