Afficher le devis en cours

Bonjour à tous,

Sur l'onglet Honda, j'ai un bouton "Afficher le devis" CB_AfficherLeDevis_Click() que j'essaye de faire fonctionner.

Le bouton à sa droite permet de sélectionner un devis. Une fois sélectionné, le N° du devis s'affiche dans la TextBoxDevisEnCours que vous voyez.

Les Devis sont dans le TableauDevis qui est dans l'onglet Devis.

J'ai essayé de faire ce code en m'inspirant de ce qui existe dans la feuille TousLesDevis et de son bouton AfficherCeDevis ( CB_AfficherDevis_Click() )

Voici ce que j'ai essayé de faire, qui évidemment bugue sur la ligne.
En fait, le problème est que je n'arrive pas à comprendre comment se font les tableaux "Array" et comment les gérer.

          r = Application.IfError(Application.Match(MonDevis, Range("TableauDevis[NoDevis]"), 0), 0)     ' la ligne du devis (enfin, c'est ce que je voulais... )
Private Sub CB_AfficherLeDevis_Click()
     '**************************
     ' ouvre le devis affiché dans la TextBoxDevisEnCours de l'onglet Honda
     '**************************
         ' // ouvre le devis sélectionné en détail dans le formulaire DetailsDuDevis
     Dim C As Range, MonDevis, r, Arr, aOut, ptr, i, MonTotal

               MonDevis = Me.TextBoxDevisEnCours    'le numero du devis

     If MonDevis = "" Then
            MonDevis = MsgBox("Aucun devis sélectionné !", vbCritical)
        Exit Sub
        Else

    With MonDevis
          r = Application.IfError(Application.Match(MonDevis, Range("TableauDevis[NoDevis]"), 0), 0)     ' la ligne du devis (enfin, c'est ce que je voulais... )
          If r = 0 Then
               MsgBox "Aucun devis sélectionné !": Exit Sub
          Else
               Arr = Range("TableauDevis").Rows(r).Value2     'contenu de la ligne de ce Devis
          End If
     End With

     Arr = Array(Range("TableauDevis").Rows(r).Value2)     'contenu de la ligne de ce Devis

     DetailsDuDevis.TextBoxNomPrenom = Arr(1, 1)       ' NomPrenom     Nom et Prénom
     DetailsDuDevis.TextBoxNoDevis = Arr(1, 3)         ' NoDevis       N° du devis
     DetailsDuDevis.TextBoxTitreDevis = Arr(1, 4)      ' TitreDevis   ' corrigé le 24/08/2025 papicx
     DetailsDuDevis.OptionButton1 = (StrComp(Arr(1, 2), "Ouvert", 1) = 0)       ' bouton "ouvert"
     DetailsDuDevis.OptionButton2 = (StrComp(Arr(1, 2), "Verrouillé", 1) = 0)   ' bouton "Verrouillé"

 '    DetailsDuDevis.TextBoxAdrCPVille = [TableauClients].Item(pos, 2) & "  " & [TableauClients].Item(pos, 3) & " " & [TableauClients].Item(pos, 4)     ' adresse,  CP, ville
 '    DetailsDuDevis.TextBoxMotoCoulImmat = [TableauClients].Item(pos, 5) & "  " & [TableauClients].Item(pos, 6) & "  " & [TableauClients].Item(pos, 7)     ' Moto, couleur, immatriculation

     r = 0
     For i = 7 To UBound(Arr, 2) Step 6      'les colonnes des ReferenceXX      ' modifié le 5 en 6 car les colonnes "designation" ont été ajoutées au TableauDevis   papicx le 22/07/2026
          r = r - (Len(Arr(1, i)) > 0)       'nombre non-vide
     Next
     ReDim aOut(1 To Application.max(1, r), 1 To 7)     'préparer une matrice la plus adaptée pour tous ces références utiles changer le 6 en 7     papicx le 20/07/2026

     For i = 7 To UBound(Arr, 2) Step 6      'boucler toutes les colonnes "Referencexx"  les colonnes "designation" ont été ajoutées au TableauDevis   papicx le 22/07/2026
          If Arr(1, i) <> "" Then            'référence connue
               ptr = ptr + 1                 'augmenter pointer
               aOut(ptr, 1) = Arr(1, i)      'reference
               aOut(ptr, 2) = Arr(1, i + 3)  ' Adap01
               aOut(ptr, 3) = Arr(1, i + 1)  ' designation
               aOut(ptr, 4) = Arr(1, i + 4)  ' Qu01
               aOut(ptr, 5) = Arr(1, i + 5)  ' Prix01
               aOut(ptr, 6) = aOut(ptr, 4) * aOut(ptr, 5)     ' calcul du total par référence (prix X quantité)
               MonTotal = MonTotal + aOut(ptr, 6)     ' total du devis
          End If
     Next
     MonTotal = Format(MonTotal, "# ##0.00 €")     ' formatage du total du devis, attention le mettre en dehors de la boucle !!!   papicx 24/08/2025   ajout du € le 28/08/2025

     With DetailsDuDevis.ListBoxDetailDuDevis
          If ptr = 0 Then
               .Clear
          Else
               .List = aOut                        ' coller matrice dans listbox
               For i = ptr + 1 To UBound(aOut)     ' n'affiche pas les lignes sans référence
                    .RemoveItem ptr
               Next
               FormaterNombreDetail          ' la liste est remplie, on formate les totaux des devis
          End If
     End With

     DetailsDuDevis.TextBoxTotal = MonTotal
     DetailsDuDevis.Show

     End If

End Sub

Merci de votre aide bienveillante.

Bonjour le fil,

papicx, il y a combien de temps que vous êtes sur ce ficher ?

Franchement vous cherchez le bâton pour vous faire battre.

Question avez-vous accès à l'application Access, si OUI basculez dessus vous irez beaucoup plus vite pour finaliser votre projet et si vous gérez bien vos tables sans pratiquement pas de code.

Bon ceci dit :
Pour arriver au résultat voulu vous devez quand même faire des modifications assez importantes :

  • Le formulaire "DetailsDuDevis" ne doit avoir qu'une seule fonction afficher les détails de ce devis. exit donc le bouton changer de devis.
  • Vous ne devez pas pouvoir le modifier si celui-ci est verrouillé.
  • Votre liste de devis tableau "TableauDevis" ne dois pas comporter les lignes pour les pièces c'est trop limitatif. Préférez travailler avec deux tableaux qui seront en relation avec un index de ligne (comme dans Access)
  • image

Sinon j'ai remarqué que certains contrôle n'avaient pas de colonne équivalente dans la table devis mais dans la table contact (ex:TextBoxAdrCPVille) tout cela va compliquer la maintenance du code.

Bon votre bouton "Afficher ce devis" sur la feuille "Devis" doit faire quelques tests :

  • Vérifier que le tableau contient des lignes.
  • Vérifier que la cellule active est bien dans le tableau
  • Vérifier que la colonne "NoDevis" contient bien des données
  • Si OUI récupérer cette ligne
  • La transmettre au formulaire DetailsDuDevis"
  • Remplir le formulaire avec les données de la ligne
Voici la procédure qui va faire cela :
Public Sub AfficherDevis(ByVal celluleActuelle As Range)
    '// Teste la présence de la feuille. Pas obligatoire si la procédure est lancée depuis la feuille elle-même
    Dim itemSheet As Worksheet
    Set itemSheet = xlTools.GetSheetByCodeName(GlobalConsts.SHEET_DEVIS_NAME)
    If itemSheet Is Nothing Then
        MsgBox "Impossible d'initialiser la feuille ""Devis""" & vbCrLf _
             & "Vous l'avez peut-être supprimée ou renommée !" & vbCrLf _
             & "" & vbCrLf _
             & "L'action va être annulée.", vbOKOnly Or vbInformation, "Gestion des feuilles"
        Exit Sub
    End If

    '// Teste si le tableau est présent sur la feuille
    Dim lstO  As ListObject
    Set lstO = xlTools.GetListObject(GlobalConsts.TAB_DEVIS_NAME)
    If lstO Is Nothing Then
        MsgBox "Impossible de trouver le tableau " & GlobalConsts.TAB_DEVIS_NAME & "." & vbCrLf _
             & "Vous l'avez peut-être supprimé ou renommé." & vbCrLf _
             & "" & vbCrLf _
             & "L'action va être annulée !", vbOKOnly Or vbInformation, "Gestion des tableaux"
        Exit Sub
    End If

    '// teste si la colonne "No Devis" est bien présente
    Dim IndexColumn As Long
    On Error Resume Next
    IndexColumn = lstO.ListColumns(GlobalConsts.TAB_DEVIS_NUMERO_NAME).Index
    On Error GoTo 0

    If IndexColumn = 0 Then
        MsgBox "Impossible de trouver la colonne " & GlobalConsts.TAB_DEVIS_NUMERO_NAME & "." & vbCrLf _
             & "Vous l'avez peut-être supprimée ou renommée." & vbCrLf _
             & "" & vbCrLf _
             & "L'action va être annulée !", vbOKOnly Or vbInformation, "Gestion des tableaux."
        Exit Sub
    End If

    '// Teste si la table contient des lignes
    If lstO.ListRows.Count = 0 Then
        MsgBox "Le tableau de devis ne contient aucune lignes." & vbCrLf _
             & "" & vbCrLf _
             & "L'action va être annulée", vbOKOnly Or vbInformation, "Gestion des tableaux."
        Exit Sub
    End If

    '// teste si la cellule active est dans une des lignes du tableau
    With lstO
        If Not Intersect(lstO.DataBodyRange, celluleActuelle) Is Nothing Then
            '// Calcul de l'index de ligne dans le tableau
            Dim rowIndex As Long
            rowIndex = celluleActuelle.Row - lstO.DataBodyRange.Row + 1

            Dim itemRow As ListRow
            Set itemRow = lstO.ListRows(rowIndex)
            If Not itemRow Is Nothing Then
                '// On affiche le formulaire en lui passant la ligne en référence
                With DetailsDuDevisForm
                    Set .LigneDevis = itemRow
                    .Show
                End With
                Unload DetailsDuDevisForm
            Else
                MsgBox "Oupss nous avons rencontré un problème au chargement du devis " & GlobalConsts.TAB_DEVIS_NUMERO_NAME & ".", vbOKOnly Or vbExclamation, "Gestion des tableaux."
            End If
        Else
            MsgBox "Vous devez sélectionner une ligne dans le tableau [" & lstO.Name & "], avant de pouvoir afficher le devis.", vbOKOnly Or vbInformation, "Gestion des devis."
            Exit Sub
        End If
    End With
End Sub

Cette procédure appelle deux fonctions "GetSheetByCodeName()" et "GetListObject()" elles se trouve dans le module "XlTools". La première sert à récupérer une feuille par son CodeName si trouvé elle renvoie l'objet Feuille sinon elle renvoie Nothing. La seconde fait pareil pour un objet ListObject.

J'ai aussi ajouter des constantes dans le module "GlobalConsts" pour éviter de retaper le nom des colonnes etc.

J'ai ajouter une propriété au formulaire pour lui faire passer la ligne qui doit être éditée
Vous remarquerez que je ne fais pas un Unload sur le bouton "Fermer" du formulaire, si vous regardez bien le code :

 '...
'...
             If Not itemRow Is Nothing Then
                '// On affiche le formulaire en lui passant la ligne en référence
                With DetailsDuDevisForm
                    Set .LigneDevis = itemRow
                    .Show
                End With
                Unload DetailsDuDevisForm
            Else
                MsgBox "Oupss nous avons rencontré un problème au chargement du devis " & GlobalConsts.TAB_DEVIS_NUMERO_NAME & ".", vbOKOnly Or vbExclamation, "Gestion des tableaux."
            End If
'...
'...

On affiche le formulaire, si depuis celui-ci on le cache "Me.Hide" alors la main est redonnée au code appelant et c'est lui qui le supprime de la mémoire.

Je n'ai pas traité le remplissage de la zone de liste comme déjà dit je trouve que cette façon de faire est trop limitée (Vous devriez travailler avec deux tableaux)

Pour conclure c'est une version minimaliste. Il y aurait beaucoup de choses à changer dans ce classeur à commencer par toutes ces variables publiques qui à mon sens ne peuvent que poser des problèmes.

hello,

je plussoie ce que dit Jean-Paul

papicx, il y a combien de temps que vous êtes sur ce ficher ?

Franchement vous cherchez le bâton pour vous faire battre.

Question avez-vous accès à l'application Access, si OUI basculez dessus vous irez beaucoup plus vite pour finaliser votre projet et si vous gérez bien vos tables sans pratiquement pas de code.

Excel c'est un tableur, lui faire prendre le role de gestionnaire de base de données c'est se compliquer la vie.

Certes Access va demander un temps d'adaptation, mais pas forcément autant que ce que vous passer à bidouiller le VBA.

Bon courage

Bonjour le fil,

Je suis impressionné par la démarche entreprise...

Je demandais juste un petit bout de code pour ce bouton, puisque le numéro de devis provient déjà d'une sélection. Nul besoin d'aller y rechercher à nouveau les infos y affairant.

Au cas où il serait saisi à la main directement dans la TextBox une comparaison avec la colonne du TableauDevis ferait qu'il est trouvé ou pas.

Si j'ai repris la désignation des pièces dans le TableauDevis, c'est justement parce que j'ai des références qui vont à différentes affectations. Ainsi, plus de souci de cohérence dans mon devis. Simple, efficace.
C'est la raison pour laquelle les premiers devis n'ont plus de désignation de pièces.

Le bouton "changer de devis" est destiné à retourner à la fonction de sélection du devis, rien de plus. C'est pour palier une erreur de choix.
Le choix du devis ne se faisant que par le formulaire TousLesDevis par présélection du Nom+prénom puis dans le DetailDuDevis on à la moto qui correspond au devis. C'est tout simple et suffisant.

Ce que je demandais, c'est le genre de code comme ça :
Bon, après le Else, c'est là que j'ai besoin de vous.

Private Sub CB_AfficherLeDevis_Click()

    Dim s, numero As String
        numero = Me.TextBoxDevisEnCours

    If Me.TextBoxDevisEnCours = "" Then
        MsgBox "Aucun devis sélectionné !" & vbCrLf _
        & "" & vbCrLf _
        & "Veuillez sélectionner un devis.", vbCritical
        Exit Sub

    Else
    '// recherche de la cohérence entre le numéro de la TextBox et la cellule dans le TableauDevis

     '       s = Application.IfError(Application.Match(numero, Range("TableauDevis[NoDevis]"), 0), 0) 'quel listrow
     '   If s = 0 Then
      '          DetailDuDevisForm , (Application.Match(numero, Range("TableauDevis[NoDevis]"), 0)), 0
         '   MsgBox "Problème : le N° de devis est inconnu.": Exit Sub
    '    Else
                ' // MsgBox "le numéro de devis ok"

     '   DetailDuDevisForm
        '    Arr = Range("TableauDevis").Rows(r).Value2     '// contenu de la ligne de ce Devis
    '    End If

          TousLesDevisForm.CB_AfficherDevis [NoDevis].Show
      End If

End Sub

Pour l'heure, la version qu'à posté Jean-Paul crée qq problèmes de fonctionnement. Désolé, pour cela, mais il faut le dire.

Un message d'erreur se produit à chaque sélection de devis et la listBox s'allonge au point de ne plus voir les boutons.

2026 07 28 145108

autrement, il y a bien toutes les infos affairant au devis, pour ceux qui sont postérieur à la modification "désignation" dans le TableauDevis, cf la capture ci-dessous.

2026 07 28 145444

edit 15h23

Par contre, j'ai vu que les boutons de l'onglet Devis fonctionnent.
Le souci rencontré est que le bouton "afficher le devis" déclenche bien l'ouverture du formulaire, mais la clef CAM ( = Client-Adresse-Moto) ne doit pas être détectée car ce ne sont pas les bonnes infos qui s'affichent pour l'adresse et la moto.

Merci de votre indulgence et de votre bienveillance pour un papi de 67 ans.

RE

Voilà le fichier avec les cellules désignation des devis remplis à la main.
J'ai supprimé des devis "tests" pour éclaircir le tableau.
Je n'ai pas réussi à trouver le couac qui fait que la première référence d'un devis se met en deuxième position, jamais à la première.
Dans les premiers devis, celles qui le sont ont été mises à la main directement dans le tableau, pour voir si elles apparaissaient dans le listbox. => oui.

Bonjour le fil,

papicx, Quand vous dites :

Un message d'erreur se produit à chaque sélection de devis et la listBox s'allonge au point de ne plus voir les boutons.

Je suis un peu étonné car comme dis dans mon précédent post je ne gère pas la zone de liste. Donc je ne vois pas comment elle pourrait s'allonger.

Vous avez sûrement fait un mix de plusieurs fichiers...

Rechercher des sujets similaires à "afficher devis cours"