XL 2016 SOMME INDEX entre deux onglets

emeline51

XLDnaute Nouveau
Bonjour,

Je me permets de venir vers vous pour vous demander de l'aide.
Ci-joint un fichier excel pour alimenter mon problème

L'objectif est d’additionner dans l'onglet Synthèse, les valeurs des onglets compris entre les onglets aaa et zzz (pour me permettre de rajouter des onglets au fil du temps), selon les critères semaines (ligne1) et personnes (colonne a).
J'ai bien la formule pour aller chercher dans un onglet précis (cf. tableau1), mais je n'arrive pas à sommer les onglets.
Quelqu'un aurait la solution ?

Merci d'avance pour votre aide
Emeline
 

Pièces jointes

  • excel.xlsx
    14.4 KB · Affichages: 20
Solution
Bonjour,
Un essai en PJ, on commence à compter de la feuille aaa jusqu'à zzz, avec :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%, Début%, Fin%
Somme = 0
Début = 0: Fin = 1
For Each Sh In Worksheets
    If Sh.Name <> "Synthese" Then   ' On ignore la feuille Synthese
        If Sh.Name = "aaa" Then Début = 1   ' On commence à compter à partir de la feuille aaa
        A = Application.CountIf(Sheets(Sh.Name).Range("A:A"), Qui)      ' "Qui" existe t il ?
        B = Application.CountIf(Sheets(Sh.Name).Range("1:1"), Semaine)  ' "Semaine" existe t il ?
        If A > 0 And B > 0 And Début = 1 And Fin = 1 Then ' Si "Qui" et "Semaine" existent alors on somme la valeur trouvée
            Ligne =...

sylvanu

XLDnaute Barbatruc
Supporter XLD
Bonjour Emeline,
Un petit essai avec une fonction perso :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%
Somme = 0
For Each Sh In Worksheets
    If Sh.Name <> "Synthese" Then   ' On ignore la feuille Synthese
        A = Application.CountIf(Sheets(Sh.Name).Range("A:A"), Qui)      ' "Qui" existe t il ?
        B = Application.CountIf(Sheets(Sh.Name).Range("1:1"), Semaine)  ' "Semaine" existe t il ?
        If A > 0 And B > 0 Then ' Si "Qui" et "Semaine" existent alors on somme la valeur trouvée
            Ligne = Application.Match(Qui, Sheets(Sh.Name).Range("A:A"), 0)
            Colonne = Application.Match(Semaine, Sheets(Sh.Name).Range("1:1"), 0)
            Somme = Somme + Sheets(Sh.Name).Cells(Ligne, Colonne)
        End If
    End If
Next Sh
Calcule = Somme
End Function
 

Pièces jointes

  • excel (2).xlsm
    23 KB · Affichages: 11
E

Exl-Noob

Guest
Bonjour Emeline,

J'ai trouvé une solution (en fouillant un peu sur le net, rendons à César...) mais c'est pas super gracieux. En revanche c'est fonctionnel.
Cela va faire appel à une viiieeellle fonction Excel 4 qui permet d'obtenir la liste des onglets.
C'est une macro qui n'en a pas l'apparence. c'est pour cela qu'il faut enregistrer le fichier en .xlsm d'ailleurs.

Dans un premier temps il faut obtenir le nom des différents onglets.
Pour cela on va définir un nom (Formules > Définir un nom).
Je l'appelle ListeOnglet.
Code:
=REMPLACER(LIRE.CLASSEUR(1);1;TROUVE("]";LIRE.CLASSEUR(1));"")

La formule va extraire en fonction de l'ordre d'apparition de l'onglet à l'écran (numéroté de gauche à droite, de 1 à x), le nom de l'onglet.
En fait elle donne le nom du fichier + le nom de l'onglet et on va simplement supprimer le nom du fichier en cherchant le "]" de cloture.

Donc quelque part dans ton fichier il faut faire apparaître la liste des onglets. Pour cela je copie en I4 le chiffre 1 (qui correspond à Synthèse), et je recopie vers le bas les valeurs suivantes.
Dans la colonne J j'insère la formule suivante :
Code:
INDEX(ListeOnglet;I3)
Je lui demande de lister le nom de l'onglet correspondant au chiffre indiqué en I3.
Mais tout cela ne va pas se mettre à jour automagiquement quand on va ajouter un onglet. Je vais donc lui demander de recalculer la formule à chaque modification. Pour cela je lui demande de m'ajouter l'heure MAINTENANT() qui s'affiche en chiffre, mais de le retourner au format texte avec la formule T(). Du coup rien ne va s'afficher, mais dès qu'on va modifier une cellule (simplement taper "entrée" dans une cellule vide), l'onglet va apparaître.
Code:
INDEX(ListeOnglet;I3)&T(MAINTENANT())
Ensuite on fait un peu de nettoyage pour supprimer les balises #REF!.
Code:
SIERREUR(INDEX(ListeOnglet;I3)&T(MAINTENANT());"")

Ensuite, je modifie légèrement tes formules dans le tableau pour faire référence au nom de chaque onglet qu'on vient de lister.
Ainsi :
Code:
INDEX(Feuil1!$B$2:$E$5;EQUIV($B3;Feuil1!$A$2:$A$5;0);EQUIV(C$2;Feuil1!$B$1:$E$1;0))
Devient :
Code:
INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0))

Il faut ensuite faire la somme des différents onglets, et c'est là que c'est moins gracieux. Je n'ai pas trouvé comment faire du récursif facilement, alors la bonne vieille méthode "à la main" fera l'affaire.
On fait donc un simple somme ;
Code:
INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0))+INDEX(INDIRECT(J9&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J9&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J9&"!$B$1:$E$1");0))+etc.

Cela va causer des erreurs, car tu vas avoir des onglets qui vont retourner la valeur #N/A.
Donc on va supprimer ces erreurs avec le code SI.NON.DISP(), ce qui donne la formule suivante, pour faire la somme de 4 onglets (à ajuster au nombre d'onglets que tu souhaites calculer au final :
Code:
SI.NON.DISP(INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J9&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J9&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J9&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J10&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J10&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J10&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J11&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J11&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J11&"!$B$1:$E$1");0));)

Formule en C15 à répéter/adapter dans les autres colonnes du tableau.

A noter qu'on ne peut pas faire
Code:
SI.NON.DISP(Valeur;"")
Car cela va retourner du texte en cas d'erreur, et on ne peut ajouter du texte dans une formule sans déclencher une erreur. Je suis donc obligé d'ignorer le dernier argument, ce qui va retourner des 0 là où tu affichais auparavant des "-".

Bref, voilà pour toutes ces raisons pourquoi c'est fonctionnel, mais pas super gracieux je trouve. Pour l'élégance, quelqu'un va sans doute t'apporter une réponse plus appropriée ;)

Bonne journée,
 

Pièces jointes

  • excel.xlsm
    26.3 KB · Affichages: 3

emeline51

XLDnaute Nouveau
Bonjour Emeline,
Un petit essai avec une fonction perso :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%
Somme = 0
For Each Sh In Worksheets
    If Sh.Name <> "Synthese" Then   ' On ignore la feuille Synthese
        A = Application.CountIf(Sheets(Sh.Name).Range("A:A"), Qui)      ' "Qui" existe t il ?
        B = Application.CountIf(Sheets(Sh.Name).Range("1:1"), Semaine)  ' "Semaine" existe t il ?
        If A > 0 And B > 0 Then ' Si "Qui" et "Semaine" existent alors on somme la valeur trouvée
            Ligne = Application.Match(Qui, Sheets(Sh.Name).Range("A:A"), 0)
            Colonne = Application.Match(Semaine, Sheets(Sh.Name).Range("1:1"), 0)
            Somme = Somme + Sheets(Sh.Name).Cells(Ligne, Colonne)
        End If
    End If
Next Sh
Calcule = Somme
End Function


Bonjour,

Merci de ton retour,
C'est pas tout à fait ça car si je rajoute des infos dans les onglets avant les onglets "aaa", cela vient se cumuler aussi.
Merci en tout cas
 

emeline51

XLDnaute Nouveau
Bonjour Emeline,

J'ai trouvé une solution (en fouillant un peu sur le net, rendons à César...) mais c'est pas super gracieux. En revanche c'est fonctionnel.
Cela va faire appel à une viiieeellle fonction Excel 4 qui permet d'obtenir la liste des onglets.
C'est une macro qui n'en a pas l'apparence. c'est pour cela qu'il faut enregistrer le fichier en .xlsm d'ailleurs.

Dans un premier temps il faut obtenir le nom des différents onglets.
Pour cela on va définir un nom (Formules > Définir un nom).
Je l'appelle ListeOnglet.
Code:
=REMPLACER(LIRE.CLASSEUR(1);1;TROUVE("]";LIRE.CLASSEUR(1));"")

La formule va extraire en fonction de l'ordre d'apparition de l'onglet à l'écran (numéroté de gauche à droite, de 1 à x), le nom de l'onglet.
En fait elle donne le nom du fichier + le nom de l'onglet et on va simplement supprimer le nom du fichier en cherchant le "]" de cloture.

Donc quelque part dans ton fichier il faut faire apparaître la liste des onglets. Pour cela je copie en I4 le chiffre 1 (qui correspond à Synthèse), et je recopie vers le bas les valeurs suivantes.
Dans la colonne J j'insère la formule suivante :
Code:
INDEX(ListeOnglet;I3)
Je lui demande de lister le nom de l'onglet correspondant au chiffre indiqué en I3.
Mais tout cela ne va pas se mettre à jour automagiquement quand on va ajouter un onglet. Je vais donc lui demander de recalculer la formule à chaque modification. Pour cela je lui demande de m'ajouter l'heure MAINTENANT() qui s'affiche en chiffre, mais de le retourner au format texte avec la formule T(). Du coup rien ne va s'afficher, mais dès qu'on va modifier une cellule (simplement taper "entrée" dans une cellule vide), l'onglet va apparaître.
Code:
INDEX(ListeOnglet;I3)&T(MAINTENANT())
Ensuite on fait un peu de nettoyage pour supprimer les balises #REF!.
Code:
SIERREUR(INDEX(ListeOnglet;I3)&T(MAINTENANT());"")

Ensuite, je modifie légèrement tes formules dans le tableau pour faire référence au nom de chaque onglet qu'on vient de lister.
Ainsi :
Code:
INDEX(Feuil1!$B$2:$E$5;EQUIV($B3;Feuil1!$A$2:$A$5;0);EQUIV(C$2;Feuil1!$B$1:$E$1;0))
Devient :
Code:
INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0))

Il faut ensuite faire la somme des différents onglets, et c'est là que c'est moins gracieux. Je n'ai pas trouvé comment faire du récursif facilement, alors la bonne vieille méthode "à la main" fera l'affaire.
On fait donc un simple somme ;
Code:
INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0))+INDEX(INDIRECT(J9&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J9&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J9&"!$B$1:$E$1");0))+etc.

Cela va causer des erreurs, car tu vas avoir des onglets qui vont retourner la valeur #N/A.
Donc on va supprimer ces erreurs avec le code SI.NON.DISP(), ce qui donne la formule suivante, pour faire la somme de 4 onglets (à ajuster au nombre d'onglets que tu souhaites calculer au final :
Code:
SI.NON.DISP(INDEX(INDIRECT(J8&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J8&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J8&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J9&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J9&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J9&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J10&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J10&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J10&"!$B$1:$E$1");0));)+SI.NON.DISP(INDEX(INDIRECT(J11&"!$B$2:$E$5");EQUIV($B3;INDIRECT(J11&"!$A$2:$A$5");0);EQUIV(C$2;INDIRECT(J11&"!$B$1:$E$1");0));)

Formule en C15 à répéter/adapter dans les autres colonnes du tableau.

A noter qu'on ne peut pas faire
Code:
SI.NON.DISP(Valeur;"")
Car cela va retourner du texte en cas d'erreur, et on ne peut ajouter du texte dans une formule sans déclencher une erreur. Je suis donc obligé d'ignorer le dernier argument, ce qui va retourner des 0 là où tu affichais auparavant des "-".

Bref, voilà pour toutes ces raisons pourquoi c'est fonctionnel, mais pas super gracieux je trouve. Pour l'élégance, quelqu'un va sans doute t'apporter une réponse plus appropriée ;)

Bonne journée,


Bonjour,
Merci à toi aussi pour ton retour, bien que je ne suis pas certaine d'avoir tout compris :D
Le problème, c'est que ce n'est pas moi qui vais alimenter le fichier, et je ne peux pas me permettre d'aller modifier la formule a chaque fois que quelqu'un aujoutera un onglet et des informations :/
 

sylvanu

XLDnaute Barbatruc
Supporter XLD
Bonjour,
Un essai en PJ, on commence à compter de la feuille aaa jusqu'à zzz, avec :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%, Début%, Fin%
Somme = 0
Début = 0: Fin = 1
For Each Sh In Worksheets
    If Sh.Name <> "Synthese" Then   ' On ignore la feuille Synthese
        If Sh.Name = "aaa" Then Début = 1   ' On commence à compter à partir de la feuille aaa
        A = Application.CountIf(Sheets(Sh.Name).Range("A:A"), Qui)      ' "Qui" existe t il ?
        B = Application.CountIf(Sheets(Sh.Name).Range("1:1"), Semaine)  ' "Semaine" existe t il ?
        If A > 0 And B > 0 And Début = 1 And Fin = 1 Then ' Si "Qui" et "Semaine" existent alors on somme la valeur trouvée
            Ligne = Application.Match(Qui, Sheets(Sh.Name).Range("A:A"), 0)
            Colonne = Application.Match(Semaine, Sheets(Sh.Name).Range("1:1"), 0)
            Somme = Somme + Sheets(Sh.Name).Cells(Ligne, Colonne)
        End If
        If Sh.Name = "zzz" Then Fin = 0     ' On finit de compter quand la feuille zzz est passée
    End If
Next Sh
Calcule = Somme
End Function
Si le nom des feuilles aaa et zzz changent il faut reprendre la macro sur ces deux noms.
(NB: Cela repose sur le fait que le VBA analyse les feuilles non pas par leur nom ou leur indice, mais par ordre de rangement. il suffit alors de ne rien faire avant aaa et après zzz )
 

Pièces jointes

  • excel (3).xlsm
    23.7 KB · Affichages: 8
Dernière édition:

emeline51

XLDnaute Nouveau
Bonjour,
Un essai en PJ, on commence à compter de la feuille aaa jusqu'à zzz, avec :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%, Début%, Fin%
Somme = 0
Début = 0: Fin = 1
For Each Sh In Worksheets
    If Sh.Name <> "Synthese" Then   ' On ignore la feuille Synthese
        If Sh.Name = "aaa" Then Début = 1   ' On commence à compter à partir de la feuille aaa
        A = Application.CountIf(Sheets(Sh.Name).Range("A:A"), Qui)      ' "Qui" existe t il ?
        B = Application.CountIf(Sheets(Sh.Name).Range("1:1"), Semaine)  ' "Semaine" existe t il ?
        If A > 0 And B > 0 And Début = 1 And Fin = 1 Then ' Si "Qui" et "Semaine" existent alors on somme la valeur trouvée
            Ligne = Application.Match(Qui, Sheets(Sh.Name).Range("A:A"), 0)
            Colonne = Application.Match(Semaine, Sheets(Sh.Name).Range("1:1"), 0)
            Somme = Somme + Sheets(Sh.Name).Cells(Ligne, Colonne)
        End If
        If Sh.Name = "zzz" Then Fin = 0     ' On finit de compter quand la feuille zzz est passée
    End If
Next Sh
Calcule = Somme
End Function
Si le nom des feuilles aaa et zzz changent il faut reprendre la macro sur ces deux noms.
(NB: Cela repose sur le fait que le VBA analyse les feuilles non pas par leur nom ou leur indice, mais par ordre de rangement. il suffit alors de ne rien faire avant aaa et après zzz )


Ca m'a l'air bien comme ça ! Merci.
Il faut que j'arrive à l'appliquer dans mon fichier maintenant ;)
 

sylvanu

XLDnaute Barbatruc
Supporter XLD
1.jpg

Le plus simple. Vous ouvrez votre fichier et le mien.
Vous cliquez et restez appuyer sur mon module et vous le tirez dans votre fichier, le module sera dupliqué. Comme cela :

20201204_150920.gif
 

sylvanu

XLDnaute Barbatruc
Supporter XLD
Rajoutez Application.Volatile :
VB:
Function Calcule(Qui, Semaine)
Dim Somme, Sh, A%, B%, Ligne%, Colonne%, Début%, Fin%
Application.Volatile
Somme = 0
Début = 0: Fin = 1
La fonction sera réactulaisée à chaque nouveau recalcul de la feuille.
( mais comme peut être lourd suivant les fonctions, par défaut je ne le mets pas de base.)
 

Statistiques des forums

Discussions
312 115
Messages
2 085 451
Membres
102 889
dernier inscrit
monsef JABBOUR