XL 2016 Pb de tri et sous totaux

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Gestionnaire_rh

XLDnaute Nouveau
Bonjour tous le monde,
Je pense avoir bien avancé sur mon sujet, reste juste le tri et sous totaux qui ne fonctionne toujours pas
VB:
Sub RemplirBalanceAvecFeuilles()
    Dim wsBalanceN As Worksheet
    Dim wsBalanceN_1 As Worksheet
    Dim wsDest As Worksheet
    Dim i As Long
    Dim DernLigne As Long
    Dim feuilleNom As String
    Dim montantN As Double
    Dim montantG As Double
    Dim difference As Double
    Dim lastRow As Long
    Dim LastRowDest As Long
    Dim compteRecherche As String
    Dim cell As Range
    Dim dataIndex As Long
    Dim rowData(1 To 10) As Variant
    Dim destRow As Long
    
    Dim lastRowDict As Object
    Set lastRowDict = CreateObject("Scripting.Dictionary")
    
    ' Définir les feuilles de travail (Balance N et Balance N-1)
    Set wsBalanceN = ThisWorkbook.Sheets("Balance N")
    Set wsBalanceN_1 = ThisWorkbook.Sheets("Balance N-1")
    
    ' Trouver la dernière ligne non vide de la colonne A dans la feuille Balance N
    lastRow = wsBalanceN.Cells(wsBalanceN.Rows.Count, "A").End(xlUp).Row
    
      For i = 2 To lastRow
        ' Vérifier si la colonne K est positive ou égale à 0, puis récupérer le nom de la feuille
        If wsBalanceN.Cells(i, 11).Value >= 0 Or (wsBalanceN.Cells(i, 11).Value < 0 And UBound(Split(wsBalanceN.Cells(i, 12).Value, "/")) = 0) Then 
            feuilleNom = wsBalanceN.Cells(i, 14).Value 
        Else 
            feuilleNom = wsBalanceN.Cells(i, 15).Value 
        End If
        
        ' Définir la feuille de destination
        On Error Resume Next
        Set wsDest = ThisWorkbook.Sheets(feuilleNom)
        On Error GoTo 0
        
        ' Vérifier si la feuille de destination existe
        If wsDest Is Nothing Then
            MsgBox "La feuille " & feuilleNom & " n'existe pas.", vbCritical
            GoTo NextIteration
        End If
        
        ' Ajouter les en-têtes dans la ligne 10 si ce n'est pas déjà fait
         If wsDest.Cells(10, 1).Value <> "A10" Then
            wsDest.Cells(10, 1).Value = "A10"
            wsDest.Cells(10, 2).Value = "Account Name"
            wsDest.Cells(10, 3).Value = "Pre-adjusted"
            wsDest.Cells(10, 4).Value = "Adjustments"
            wsDest.Cells(10, 5).Value = "Adjusted Current Year"
            wsDest.Cells(10, 6).Value = "Interim"
            wsDest.Cells(10, 7).Value = "Prior Year"
            wsDest.Cells(10, 8).Value = "Variance"
            wsDest.Cells(10, 9).Value = "In %"
            wsDest.Cells(10, 10).Value = "J10"
            wsDest.Cells(10, 11).Value = "K10"
            wsDest.Cells(10, 12).Value = "Xref"
        End If
        
        ' Collecter les données pour cette ligne
        rowData(1) = wsBalanceN.Cells(i, 1).Value ' Colonne A (Numéro de compte)
        rowData(2) = wsBalanceN.Cells(i, 2).Value ' Colonne B (Valeur correspondante)
        rowData(3) = CDbl(wsBalanceN.Cells(i, 11).Value) ' Colonne K
        rowData(4) = 0 ' Colonne D vide
        rowData(5) = CDbl(rowData(3) + rowData(4)) ' Colonne E (C+D)
        rowData(6) = "" ' Colonne F vide
        rowData(10) = wsBalanceN.Cells(i, 12).Value
        ' Recherche du montant dans la Balance N-1 basé sur la colonne A (Numéro de compte)
        compteRecherche = rowData(1) ' Numéro de compte dans Balance N
        Set cell = wsBalanceN_1.Range("A2:A" & wsBalanceN_1.Cells(wsBalanceN_1.Rows.Count, "A").End(xlUp).Row).Find(compteRecherche, LookIn:=xlValues, LookAt:=xlWhole)
        
        ' Si trouvé, récupérer la valeur correspondante de la colonne K de la Balance N-1
        If Not cell Is Nothing Then
            montantG = cell.Offset(0, 10).Value ' Colonne K de Balance N-1 (colonne A + 10 = colonne K)
            rowData(7) = CDbl(montantG) ' Colonne G
        Else
            rowData(7) = "Non trouvé" ' Si non trouvé, afficher "Non trouvé"
        End If
        
        ' Calculer la différence entre E et G (H = E - G)
        montantN = rowData(5)
        rowData(8) = CDbl(rowData(5) - rowData(7))
        'rowData(8) = difference ' Colonne H
        
        ' Utiliser la fonction SI pour gérer l'erreur de division par zéro pour le taux d'erreur (Colonne I)
        If rowData(7) <> 0 Then
           rowData(9) = rowData(8) / rowData(7)
        Else
           rowData(9) = "" ' Erreur si G = 0
        End If
        
        ' Vérifier et récupérer la dernière ligne disponible de la feuille de destination
        If Not lastRowDict.exists(feuilleNom) Then
            lastRowDict.Add feuilleNom, 11 ' Si c'est la première ligne, commencer à la ligne 11
        End If
        
        ' Incrémenter la dernière ligne pour cette feuille
        DernLigne = lastRowDict(feuilleNom)
        
        ' Insérer les données collectées dans la feuille de destination
        
        'wsDest.Rows("11:250").Delete shift:=xlUp
                
        wsDest.Cells(DernLigne, 1).Value = rowData(1)
        wsDest.Cells(DernLigne, 2).Value = rowData(2)
        wsDest.Cells(DernLigne, 3).Value = CDbl(wsBalanceN.Cells(i, 11).Value)
        wsDest.Cells(DernLigne, 4).Value = 0
        wsDest.Cells(DernLigne, 5).Value = CDbl(rowData(3) + rowData(4))
        wsDest.Cells(DernLigne, 6).Value = 0
        wsDest.Cells(DernLigne, 7).Value = rowData(7)
        wsDest.Cells(DernLigne, 8) = CDbl(rowData(5) - rowData(7))
        wsDest.Cells(DernLigne, 9) = rowData(9)
        wsDest.Cells(DernLigne, 12) = rowData(10)
        
    ' Mettre à jour la dernière ligne pour cette feuille
      lastRowDict(feuilleNom) = DernLigne + 1
NextIteration:
      Next i
    
' Déterminer la dernière ligne dans la colonne A avec des données
    destRow = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row

    wsDest.Sort.SortFields.Clear
    
    ' Appliquer le filtre automatique à la plage incluant l'en-tête
    'wsDest.Range("A10:L" & destRow).AutoFilter Field:=12, Criteria1:="<>", Operator:=xlFilterValues

    wsDest.Sort.SortFields.Add key:=wsDest.Range("L10:L" & destRow), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    
    ' Effectuer le tri
    With wsDest.Sort
        .SetRange wsDest.Range("A10:L" & destRow)
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

    ' Application des sous-totaux
   wsDest.Range("A10:L" & destRow).Subtotal GroupBy:=12, _
       Function:=xlSum, _
       TotalList:=Array(3, 4, 6, 7), _
       Replace:=True, _
       PageBreaks:=False
End Sub
 
ah et dans la macro "RechercherEtRécupérer"

VB:
indexValue = Application.WorksheetFunction.Index(TSParam.ListColumns(2).Range, Application.WorksheetFunction.Match(resultD, TSParam.ListColumns(4).Range, 0))
tu as bien conscience que cette instruction cherche la feuille dans la la colonne D de paramétrage pour te donner la valeur de la colonne Azerty2 (colB)
MAIS que ca te donne la première occurence..
Après réflexion, je me suis aperçu que ta remarque était effectivement pertinente. J'ai donc pris le temps de corriger le code comme suit :
VB:
indexValue = Application.WorksheetFunction.Index(wsParam.Range("H6:H156"), Application.WorksheetFunction.Match(wsBalanceN.Cells(balanceRow, 13).Value, wsParam.Range("F6:F156"), 0))
        wsBalanceN.Cells(balanceRow, 18).Value = indexValue
 
Dernière version ici
reste 2 points à éclaircir/confirmer

1) ce que je t'ai indiqué dans le post 14
2) macro RemplirBalanceAvecFeuilles: remplissage du rowsource(10)
ne serait ce pas exactement la meme chose que le test que tu fais juste un peu avant pour avoir "feuilleNom" ??
Les en-têtes de colonnes correspondent aux conditions des sous-totaux. Si k >= 0, la colonne P est copiée vers la colonne L des feuilles de destination. Sinon, la colonne Q est copiée vers la colonne L des feuilles de destination. C'est pour cette raison que j'ai repris la même logique, car il est nécessaire de renseigner la colonne L des feuilles de destination, qui sera utilisée pour les sous-totaux après chaque changement de ce qu'elle contient.
 
La dernière version, avec les résultats souhaités, présente un seul problème : remplacer ceci
VB:
.ShowTotals = True
par cela
Code:
.Subtotal GroupBy:=12, Function:=xlSum, TotalList:=Array(3, 5, 7), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
 

Pièces jointes

Dernière édition:
Hello

il y a encore des soucis sur l'index..
je crois qu'il y a mélange dans les numéros de colonnes..

VB:
'on cherche ResultD dans la colonne 4 (=D = Lead Auto Débit) de param, et on récupère la valeur de la colonne 8 (=H = Sous-Totaux)
            'indexValue = Application.WorksheetFunction.Index(TSParam.ListColumns(8).Range, Application.WorksheetFunction.Match(resultD, TSParam.ListColumns(4).Range, 0))
            'on peut remplacer les numéros de colonne (8 et 4) par leur nom d'entete==> permet de s'affranchir de la place de la colonne ==> elle peut etre déplacée sans impact sur le code
            indexValue = Application.WorksheetFunction.Index(TSParam.ListColumns("Sous-Totaux").Range, Application.WorksheetFunction.Match(resultD, TSParam.ListColumns("Lead Audit Crédit").Range, 0))
            .DataBodyRange(i, 18).Value = indexValue 'on met l'index dans la colonne 18 (=R) de la table Balance
            
            'on ne cherche pas ResultF ??, si oui, on le mettrait ou?


bon après.. je vois pas à quoi ce sert cette colonne R.. dans ton fichier, tu n'en fais rien.. peut etre dans des macros que tu n'as pas fournies?


pour les sous-totaux.. je ne comprend pas ce que tu souhaites obtenir comme résultat..
Dans la feuille Modèle, j'ai réaffiché la ligne "Totaux"==> tu peux donc choisir sur quelles colonnes tu veux calculer un total, et tu choisis somme, nb, max.....
comme la feuille modèle est utilisée pour recrééer les feuilles, les totaux seront reproduits..
 

Pièces jointes

Je souhaite avoir des sous-totaux des colonnes 3,5, et 7 selon les valeurs présentes dans la colonne 12 (L), sans passer par onglet données --> Plan --> sous-total. Et pour la fonction index et la colonne 8, je souhaite l'avoir autant qu'identifiant du sous-total. (exemple en image feuille SS).
Nouveau Image bitmap (2).jpeg
 
ok compris
je viens de voir que les sous-totaux ne sont pas disponibles avec les Tables structurées.. il faut les retransformer en Plages normales

mais je pense que pour garder les tables structurées, on peut tricher en inserant des lignes "Sous-total manuel" pour les avoir..

mais avant. quelques questions:
dans ton fichier original.. combien de lignes peut il y avoir dans les balances? une vingtaine comme dans l'exemple, ou plutot quelques centaines?
dans ce cas..je présume que le code actuel est un peu "lent" à s'executer.. il faudrait sans doute revoir le code pour travailler avec des tableaux vba..
l'idée serait de
1) mettre les balances N et N-1 dans deux tablos vba
2) et peut etre qu'au lieu de parcourir les lignes une par une, on ferait plutot une boucle pour traiter feuille par feuille, et on colle le résultat final directement dans la feuille
 
Bizarrement, cela ne fonctionne pas maintenant. J'ai ajouté mes données sur les feuilles "Balance N", "Balance N-1" et "Paramétrage des leads", mais les nouvelles feuilles ne respectent pas la condition de la colonne K, ceci dit que la feuille générer est vide et le message d'erreur 438 sur la ligne
VB:
XRef = .DataBodyRange(.ListRows.Count, 12)
 
Hello

pour l'erreur, je pense qu'elle arrive lorsqu'il n'y a pas de ligne dans le tableau.. donc pas de Sous-Totaux

remplace la macro "SousTotal" par ce code

VB:
Public Sub SousTotal(clé As String)
    Dim LigSousTotal(1 To 12) As Variant
    Dim NewLig As Boolean

    With Sheets(clé).ListObjects(1)
        If .ListRows.Count > 0 Then
            XRef = .DataBodyRange(.ListRows.Count, 12)
            LigInsert = .ListRows.Count
            For i = .ListRows.Count To 0 Step -1
                If XRef <> .DataBodyRange(i, 12) Then
                    NewLig = True
                End If
                If NewLig Then
                    ind = .ListRows.Add(LigInsert + 1).Index
                    .DataBodyRange(ind, 1).Resize(, 12) = LigSousTotal
                    .DataBodyRange(ind, 12) = "Sous-Total " & XRef
                    .ListRows(ind).Range.Font.Bold = True
                    NewLig = False
                    LigInsert = i
                    XRef = .DataBodyRange(i, 12)
                  
                    LigSousTotal(3) = .DataBodyRange(i, 3)
                    LigSousTotal(5) = .DataBodyRange(i, 5)
                    LigSousTotal(7) = .DataBodyRange(i, 7)
    '                For j = 3 To 11 'on ne remplit pas les deux premières colonnes qui contiennent du texte
    '                    LigSousTotal(j) = .DataBodyRange(i, j) 'on met la dernière ligne en sous total
    '                Next j
                Else
                    LigSousTotal(3) = .DataBodyRange(i, 3) + LigSousTotal(3)
                    LigSousTotal(5) = .DataBodyRange(i, 5) + LigSousTotal(5)
                    LigSousTotal(7) = .DataBodyRange(i, 7) + LigSousTotal(7)
    '                For j = 3 To 11 'on ne remplit pas les deux premières colonnes qui contiennent du texte
    '                    LigSousTotal(j) = LigSousTotal(j) + .DataBodyRange(i, j) 'on met la dernière ligne en sous total
    '                Next j
                End If
            Next i
        End If
    End With
End Sub
 
Hello
pour l'erreur corrigée, c'est donc OK
mais pour le reste??
tu disais que les feuilles ne respectaient pas la condition colonne K ==> c'est à dire??

et tu n'as pas répondu aux questions que je te posais:
est ce que ton "vrai" fichier contient 20 lignes, ou plutot plusieurs centaines?? (LA question sous-jacente étant: est ce que l'execution n'est pas trop lente?)

est ce que Balance N et N-1 ont le MEME nombre de lignes, et les MEMES comptes dans le MEME ordre?
 
Bonjour,

Pour l'erreur, c'est bon, et concernant les feuilles générées, j'ai constaté que la condition n'est pas respectée car elles sont générées même lorsque K < 0. Normalement, le code devrait générer soit la colonne N, soit la colonne O. De plus, le nombre de lignes sur les feuilles "balance N" et "balance N-1" ne dépasse pas 250 lignes.
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
2
Affichages
66
  • Question Question
Microsoft 365 worksheet_change
Réponses
29
Affichages
280
  • Question Question
Microsoft 365 Export données
Réponses
4
Affichages
515
Retour