Tableaux dans vba

akni

XLDnaute Nouveau
Bonjour,
J'ai un tableau des quantités vendues par articles, clients et mois, je veux faire une récap par client sans passer par TCD quand j'utilise la méthode FOR NEXT elle tarde un peu, je crois qu'avec les tableaux Ubound et Lbound le résultat sera rapide.
ci joint mon fichier avec la macro FOR NEXT.


Merci beaucoup pour toute aide.
 

Pièces jointes

  • test Tableau 2.xlsm
    1.8 MB · Affichages: 116

Dranreb

XLDnaute Barbatruc
Ça dépend de ce qu'on veut obtenir.
Ce n'est pas une macro, c'est une méthode.
Dim TExtrac()
SIT.Extraire TExtrac, nC_Bud
mettrait dans TExtrac les valeurs de la colonne nC_Bud de toutes les lignes détail attachées indirectement au SsGr SIT courant.
 

Dranreb

XLDnaute Barbatruc
Déclaré: TCond(), TBud(), N As Long
VB:
'            TRés(L, 6) = Eqp.NbSi(nc_ETAT, "En cours")                    ' Code OK, mais qu'on
'            TRés(L, 7) = Eqp.SommeSi(nc_ETAT, "En cours", nC_BUD)         ' tente de remplacer.
            Eqp.Extraire TCond, nc_ETAT
            Eqp.Extraire TBud, nC_BUD
'            TRés(L, 6) = WorksheetFunction.CountIf(TCond, "En Cours")     ' MAUVAISE SURPRISE:
'            TRés(L, 7) = WorksheetFunction.SumIf(TCond, "En Cours", TBud) ' Tableaux hélas non acceptés.
            For N = 1 To UBound(TBud)
               If TCond(N) = "En cours" Then TRés(L, 6) = TRés(L, 6) + 1: TRés(L, 7) = TRés(L, 7) + TBud(N)
               Next N                             ' mais la méthode Extraire donne les tableaux attendus.
            Next Eqp, Site, Serv, Dpt
 

KIM

XLDnaute Accro
Bonsoir Dranreb et le forum,
Aujourd'hui j'ai eu à traiter un nouveau type de tableaux. Je dois récupérer pour chaque SsGr : DPT/SERV
et par titres de la col PHASE : Set DicTit = GigIdx.DicInvent(LOt, "PHASE", nC_PHASE)
les 3 col BUD, ENG et FAC mais en lignes voir fichier ci-joint avec résultat souhaité.

Je l'ai déjà fait par colonnes en demultipliant les titres pour chaque col traitée BUD, ENG et FAC. Par contre je n'ai pas réussi à faire un seul tableau avec ces 3 col en lignes.
Ensuite par SsGr DPT/SERV je dois rajouter les 2 lignes de formules :
Reste à engagé (BUD-ENG) et %(ENG/BUD)
Merci de votre aide.
KIM
 

Pièces jointes

  • GigogneKIM(AvecLO)_v3.xlsm
    24.2 KB · Affichages: 20

Dranreb

XLDnaute Barbatruc
Ben c'est à peu près ça :
VB:
Option Explicit
Sub RecapParPhase_v2()
Dim DicTit As Dictionary, CMax As Long, L As Long, C As Long, TRés(1 To 500, 1 To 12), _
   Dpt As SsGr, Serv As SsGr, Détail

'Recherche les entetes des colonnes pour identifier le numero de la colonne.
Dim nC_PHASE&, nC_LibEQP&, nc_ETAT&, nC_BUD&, nC_ENG&, nC_FAC&
Dim LOt As ListObject
Set LOt = FDonn.ListObjects(1)
nC_PHASE = NColTab(LOt, "PHASE")
nC_LibEQP = NColTab(LOt, "Lib EQP")
nc_ETAT = NColTab(LOt, "ETAT")
nC_BUD = NColTab(LOt, "BUD")
nC_ENG = NColTab(LOt, "ENG")
nC_FAC = NColTab(LOt, "FAC")
Set DicTit = GigIdx.DicInvent(LOt, "PHASE", 4): CMax = 3 + DicTit.Count
L = 1
For C = 1 To 3: TRés(L, C) = Choose(C, "DPT", "SERV", "BILAN"): Next C
VerserTitres TRés, DicTit
For Each Dpt In GigIdx.Gigogne(Null, "DPT", "SERV")
   For Each Serv In Dpt.Co
            L = L + 1
            TRés(L, 1) = Dpt.ID
            TRés(L, 2) = Serv.ID
            TRés(L, 3) = "BUD"
            TRés(L + 1, 3) = "ENG"
            TRés(L + 2, 3) = "FAC"
            For Each Détail In Serv.Co
               C = DicTit(Détail(nC_PHASE))
               TRés(L, C) = TRés(L, C) + Détail(nC_BUD)
               TRés(L + 1, C) = TRés(L + 1, C) + Détail(nC_ENG)
               TRés(L + 2, C) = TRés(L + 2, C) + Détail(nC_FAC)
               Next Détail
            L = L + 3
            TRés(L, 1) = "Reste à engager (DUB-ENG)"
            For C = 4 To CMax: TRés(L, C) = TRés(L - 3, C) - TRés(L - 2, C)
               Next C
            L = L + 1
            TRés(L, 1) = "%(ENG/BUD)"
            For C = 4 To CMax: If TRés(L - 4, C) <> 0 Then TRés(L, C) = TRés(L - 3, C) / TRés(L - 4, C)
               Next C
            L = L + 1
            Next Serv, Dpt
FDonn.[A15].Resize(500, 12).Value = TRés
End Sub

Function NColTab(ByVal LOt As ListObject, ByVal Titre As String) As Long
On Error Resume Next
NColTab = LOt.ListColumns(Titre).Index
If Err Then MsgBox "Le tableau " & LOt.Name & " ne contient pas de colonne """ _
   & Titre & """.", vbCritical: End
End Function
Où était la difficulté ?
 
Dernière édition:

KIM

XLDnaute Accro
Bonjour Dranreb et le forum,
Merci pour les nouveautés de ces derniers jours.
Jusqu'à maintenant j'utilise seulement une seule colonne à traiter dans Détail. Traiter 3 col en même temps m'a perturbé. Je vais commencer à modifier mes vingtaines de tableaux de synthèse pour intégrer ces nouveautés. Je te tiens au courant.
Merci encore et bonne journée.
KIM
 

KIM

XLDnaute Accro
Bonjour Dranreb et le forum,
Je teste les nouveautés dans mes tableaux.
1/ Je fais appel à toi car depuis hier je n'arrive pas à trouver la cause de l'erreur. J'ai besoin de l'oeil du spécialiste. Merci d'avance.
TS(L, 12) = TS(L, 12) + SIT.Somme(nC_BUD) me donne la bonne somme pour tous les DT par OP.
En sélectionnat une col pour les titres nC_RT = NColTab(LOt, "BT.RT")
la ligne de code ci-dessous
TS(L, DicTit(Détail(nC_RT))) = TS(L, DicTit(Détail(nC_RT))) + Détail(nC_BUD)
me donne des sommes correctes pour chaque titre sauf pour la DT07 (cellule correspondante pour "Avec P P" est vide.. La somme par titre de toutes les autres DT sont correctes (au mois une cinquantaine).
Je n'ai pas réussi à trouver pourquoi la cellule est vide!
2/ Après avoir calculé la somme BUD par titre dans nC_RT, comment calculer la somme de tous les titres d'une m^me ligne ( par DT) dans la col "BUD Total" qui suit le dernier titre de la col nC_RT ?
3/ Avant de passer à l'OP suivant, je fais la somme de chaque colonne à partir de la col 4
For C = 4 To CFin: TS(L, C) = TotOP(C): Next C
Je ne trouve pas les sommes correctes pour les colonnes des titres de la nC_RT.
Pourquoi?
Merci de ton aide
KIM
 

Pièces jointes

  • T_R2018_TE.xlsm
    82.6 KB · Affichages: 29

Dranreb

XLDnaute Barbatruc
Bonjour.
C'est semble-t-il le texte vide en O18 qui pose problème en interprétant le "+" comme opérateur de concaténation vu qu'il n'y a aucun nombre dans l'histoire jusqu'à ce moment là, qui met donc un texte vide dans TS(L, DicTit(Détail(nC_RT))), sur lequel on ne peut ensuite plus rien ajouter de numérique.
Une cellule remplie d'un texte vide n'est pas une cellule vide.

Pas bien, ça, de mettre un On Error Resume Next au début et ne jamais faire de Err.Clear ni If Err Then…
 
Dernière édition:

KIM

XLDnaute Accro
Merci, pb réglé, Je n'y ai pas pensé car les sommes globales étaient correctes. C'est donc au niveau de Détail qu'il ne faut pas avoir des cellules vides. Y-a-t-il d'autres prérequis?
As-tu une fonction qu'on lui donne le numéro de la colonne et remplce tous les vides par "0" par exemple?

Pour la Question 2,
2/ Après avoir calculé la somme BUD par titre dans nC_RT, avec
TS(L, DicTit(Détail(nC_RT))) = TS(L, DicTit(Détail(nC_RT))) + Détail(nC_BUD)
comment calculer la somme de tous les titres d'une m^me ligne ( par DT) dans la col "BUD Total" qui suit le dernier titre de la col nC_RT ?

Merci pour l'aide et les conseils.
KIM
 

Dranreb

XLDnaute Barbatruc
Une cellule vide ne pose pas de problème: c'est assimilé à 0. C'est une cellule contenant un texte vide qui en pose un.
Faire un boucle For C = ColDép To ColMax: TS(L, CMax + 1) = TS(L, CMax + 1) + TS(L, C)
Ou alors profiter du Cumul dans le bon Dictit pour cumuler aussi dans la colonne en question.
Évite de rechercher plusieurs fois DicTit(Détail(nC_RT)), affecte ça une fois à C.
 

KIM

XLDnaute Accro
Je viens de finaliser quelques tableaux de synthèses.
J'ai utilisé le code suivant
CMax = ColDep + DicTit.Count
ensuite
For C = ColDep To CMax - 2: TS(L, CMax - 1) = TS(L, CMax - 1) + TS(L, C): Next C
Est-ce normal que DicTit.Count = 3 pour 2 titres?

Dans ton dernier message tu disais :
"Ou alors profiter du Cumul dans le bon Dictit pour cumuler aussi dans la colonne en question."
Comment ?
Merci
KIM
 

Dranreb

XLDnaute Barbatruc
Non, mais si CMax = ColDep + 2, ColDep à CMax couvre 3 colonnes. Avec CMax = ColDep - 1 + 2, ColDep à CMax en couvre 2: ColDep et ColDep + 1
On a déjà dû le faire des quantités de fois
C = DicTit(Détail(nC_RT)): TS(L, C) = TS(L, C) + Détail(nC_BUD) : TS(L, CTot) = TS(L, CTot) + Détail(nC_BUD)
 

KIM

XLDnaute Accro
Bonsoir Dranreb et le forum,
Quelques questions pour améliorer le code. Merci d'avance pour tes conseils.
1/ VerserTitres TS, DicTit: C = ColDep + DicTit.Count: TS(1, C) = "Bud Total"
Dans TS il ya les titres saisies en dur dans le code,
DicTit me donne les titres de colonnes à partir d'une colonne ColTitre
Je rajoute une col du titre "BudTotal".
Après cette colonne je rajoute les mêmes titres de DicTit pour les mêmes titres de colonnes mais pour un calcul de nombre de Références. Pour cela j'utilise le code suivant :
For Each Détail In DicTit.Keys: C = C + 1: TS(1, C) = Détail: Next Détail
C = C + 1: TS(1, C) = "Nombre total de Réf"
CFin = ColDep + DicTit.Count + DicTit.Count + 2
FTS023.[A4].Resize(1, CFin).Value = TS
Q1 : Est-il possible de créer cette ligne de titres (TS + 2 fois DicTit avec des col entre les DicTit) par une seule ligne de commande de VerserTitres ?

2/ Set LOt = FBase.ListObjects(1)
Dans LOt, je définis le tableau des données de FBase. Je mets à jour FBase avec plus ou moins de lignes ou de col.
Q2 : Est-ce que le tableau géré par ListObjects(1) est mis à jour automatiquement ?
Si Non, Comment faire pour éviter de le faire manuellement à chaque fois?

3/ NColTab
Avec NColTab je récupère le num de col d'un titre donné. Dans mon tableau de synthese je recherche 13 titres de col. par ex : nC_OP = NColTab(LOt, "Bud.OP") etc.
Pour chaque col recherchée et selon l'ordre souhaité je les copie dans une nouvelle feuil BaseTavec :
Sheets("FBase").Cells(7, nC_OP).Resize(derLgn).Copy Destination:=Sheets("BaseT").Cells(10, ColCible)
Q3 : As-tu une fonction qui recopie ces col à partir de leurs numéros trouvés par NColTab dans un autre onglet, à partir d'une ligne donnée et selon un ordre souhaité ? Sinon comment mieux faire ?

J'utilise régulièrement les 3 cas ci-dessous. Merci d'avance de ton aide
Bonne soirée
KIM
 

Dranreb

XLDnaute Barbatruc
Bonsoir.
Par un seul appel à VerserTitres non, mais cette procédure admet un 3ième paramètre, ColDép, optionnel permettant d'en spécifier un différent de celui spécifié à DicInvent.
Correctement manipulé, un tableau Excel est mis à jour automatiquement, C'est la propriété DataBodyRange du ListObject qui le représente.
Les élément de sa collection ListColumns peuvent être désigné par leurs numéros d'ordre, et leurs Name sont les titres des colonnes. Possible aussi de récupérer sa .HeaderRow.Range.Value dans un tableau VBA 2 dimension mais d'une seule ligne.
 

Discussions similaires

Réponses
1
Affichages
322

Statistiques des forums

Discussions
311 725
Messages
2 081 944
Membres
101 849
dernier inscrit
florentMIG