Microsoft 365 activation de la dernière feuille créée selon son n° (pas sa position)

Usine à gaz

XLDnaute Barbatruc
Supporter XLD
Bonjour à toutes et à tous,

J'ai besoin de pouvoir activer la dernière feuille créée dans mon classeur
Par exemple ici j'ai créé les Feuile1 à 6

le code "Sheets(Sheets.Count).Select" fonctionne

mais active la dernière Feuille selon sa position dans le classeur
alors que c'est la dernière créé soit la Feuil6 que je souhaite activer.

Malgré mes recherches et essais, je n'ai pas trouvé comment coder.
Pourriez-vous m'aider sachant que mes feuilles sont créées depuis longtemps et donc antérieurement au code que vous m'aurez (je l'espère LOL) transmis.
Je joins un fichier test.

Avec mes remerciement,
Je vous souhaite à toutes et à tous une belle journée,
amicalement,
lionel,
 

Pièces jointes

  • derniere_Feuille.xlsm
    22.1 KB · Affichages: 10

patricktoulon

XLDnaute Barbatruc
en fait Arthour doit tester a gogo et perdre un peu le fil des choses élémentaires sur les manip d'object en vba

stapple160 tu m'a fait un peu peur quand même avec

Sheets(LastCreatedSheet.Name).Activate

parce que pour les blagues je suis pas le dernier
codage façon poupées russes
sheets(Sheets(LastCreatedSheet.Name).name).activate :p :p :p :p

bon on déconne un peu c'est le Weekend

j'a jouterais aussi en mode lecture (GET) il faudrait gérer l'absence de indice dans les customproperties

VB:
Property Get LastCreatedSheet() As Object
    Dim xsh, i&, max&, leNom$
    'parcours de tous les item "indice" de chaque feuille de calcul
    'pour déterminer le max des indices et la feuille associée
    'l'item indice est le premier (item numéro 1)

    On Error Resume Next
    For Each xsh In ThisWorkbook.Worksheets
        If xsh.CustomProperties.Item(1).Name = "indice" Then
            i = 0: i = CLng(xsh.CustomProperties.Item(1))
            If i > max Then
                max = i
                leNom = xsh.Name
            End If
        End If
    Next xsh

    If leNom <> "" Then Set LastCreatedSheet = Sheets(leNom)
End Property


Sub test2()
    If Not LastCreatedSheet Is Nothing Then
        MsgBox LastCreatedSheet.Name
    Else
        MsgBox " pas de sheets mémorise"
    End If
End Sub

bon j'avoue qu'il y aurait encore un problème si on devait ajouter plusieurs item dans les customproperties indice ne serait pas forcement le item(1) selon la façon et/ou le moment ou sont enregistrés les items

mais bon comme je vois qu'on a perdu Arthour j'y vais en douceur ;)

ps: remarquez le as object qui définit définitivement le return du get en tant qu'object
il est donc implicitement définit à nothing si indice pas trouvé
on évite ainsi une gestion d'erreur ;) avec le type retourné donc (sheets ou nothing)
 
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour @arthour973, @Roblochon, @patricktoulon, @job75, @ChTi160, @eriiiic, et au petit nouveau @Staple1600 :)

Après une bonne nuit (et une partie de la matinée) tout occupé à dormir, je tente une nouvelle méthode.

Qui ne marche pas ! (merci @patricktoulon )

Cette méthode est basée sur l'observation suivante que vous pourrez me confirmez (ou pas):
Quand une ou plusieurs feuilles sont ajoutées par quelque méthode que ce soit (création ou copie, à la mimine ou par code), la ou les feuilles semblent être ajoutées à la fin de la liste des Microsoft Excel Objects du projet VBA et cela dans l'ordre de création ou d'insertion de la ou des feuilles.

Il m'a semblé qu'il suffirait de parcourir cette liste d'objets en partant de l'élément le plus bas. Pour chaque objet, on récupèrerait le nom de l'objet, on vérifierait que le nom correspond bien à un CodeName de feuille de calcul. Si oui, on active la feuille correspondant à ce CodeName sinon on passe à l'élément suivant le liste.

Des éléments supplémentaires sont sur la feuille "ABC" du fichier joint.

Le code principal est relativement simple:
VB:
Sub Afficher_Feuil_Plus_Recente()
Dim VBComp As VBComponents, i&, nbrItem&, nomCode$, xwsh As Worksheet

   Set VBComp = ActiveWorkbook.VBProject.VBComponents    ' initialisation de VBcomp
   nbrItem = VBComp.Count                                ' nombre total d'item
   For i = nbrItem To 1 Step -1                          ' boucle sur les items de VBComp
      If VBComp.Item(i).Type = vbext_ct_Document Then    ' si l'item est de type 'Document'
         nomCode = VBComp.Item(i).Name                   ' nom de l'item
         For Each xwsh In ThisWorkbook.Worksheets        ' boucle sur les feuilles de calcul
            If xwsh.CodeName = nomCode Then              ' si le CodeName de la feuille est le nom de l'item
               xwsh.Visible = xlSheetVisible             ' alors on rend la feuille visible
               xwsh.Select: Exit Sub                     ' et on sélectionne la feuille et on quitte
            End If
         Next xwsh
      End If
   Next i
End Sub

Le code restant est dans ThisWorkbook:
Code:
Private Sub Workbook_Open()
   ' Permet de faire référence à la bibliothèque:
   ' Microsoft Visual Basic for Applications Extensibility 5.3
   On Error Resume Next
   ThisWorkbook.VBProject.References.AddFromGuid GUID:="{0002E157-0000-0000-C000-000000000046}", Major:=5, Minor:=3
   On Error GoTo 0
End Sub
 

Pièces jointes

  • arthour973- Afficher Feuille plus récente- v2.xlsm
    20.5 KB · Affichages: 6
Dernière édition:

Usine à gaz

XLDnaute Barbatruc
Supporter XLD
Bonjour Mapomme,
"Encore une précision. Pendant que certains déconnent, moi je bosse. Jamais je ne déconne. :);):p:D (n'est ce pas)"
LOL Continues de déconner ... c'est tout bon :)

Aux premiers tests, ce nouveau code semble fonctionner "du tonnerre" (et aussi après fermeture et ré-ouverture).
Dès que j'aurai un moment, je le testerai également dans mon fichier et je reviendrai.
lionel,
 

patricktoulon

XLDnaute Barbatruc
re
je répond à mapomme

Il m'a semblé qu'il suffirait de parcourir cette liste d'objets en partant de l'élément le plus bas. Pour chaque objet, on récupèrerait le nom de l'objet, on vérifierait que le nom correspond bien à un CodeName de feuille de calcul. Si oui, on active la feuille correspondant à ce CodeName sinon on passe à l'élément suivant le liste.
et ben non
car entre deux ajout si tu supprime un/des sheets le codename est auto et donc remplace les manquants (on a testé hier)
bon il est vrai que j'ai testé sur le fichier de Arthour :p

Staple 1600
j'avoue ne pas avoir suffisamment de recul pour comprendre en quoi l'addition du tableau de bits de la conversion du nom
pourrait me donné le bon sachant qu'on le récupère déjà avec LastCreatedSheet
je vais bucher la dessus


d'autre part
je suis parti de ton premier exemple bouclant sur les sheets en lecture écriture avec max+1
Mais!!!! il n'en est nul besoins en fait il suffit de mettre le "sheets.count" dans l'item indice en écriture
je reviens donc toute a l'heure avec le code scalpé;)
 

patricktoulon

XLDnaute Barbatruc
Re @patricktoulon :)

C'est exact. C'est la grosse erreur que je n'ai pas vue mais que tout autre voit tout de suite... Sniff :confused::oops:
Ah ben je te rassure moi non plus je l'ai pas vu tout de suite ,c'est en testant l'idée de job75 avec les codename qui m'a séduit et qui m'a fait crier victoire trop vite que je m'en suit rendu compte

c'est un peu mon truc ca, décortiqué et mettre a mal une procédure en la testant dans des conditions rocambolesques
plus c'est tordu et apparemment insoluble; plus j'aime
 

patricktoulon

XLDnaute Barbatruc
re
donc avec l'idée de Staple160
  1. dans des propriété get/let
  2. recherche de l'item "indice" dans les customproperties 'new!!! (c'est pas forcé que ça soit le premier item )
  3. abolition de gestion d'erreur (c'est pas ma faute j'aime pas!!) ;)

VB:
Option Explicit
Property Let LastCreatedSheet(Sh)
    Dim xsh, i&, max&, DerCodeName, X& 'Variables
    For Each xsh In ThisWorkbook.Worksheets    'boucle sur sheets
        If LCase(xsh.Name) <> xsh.Name Then    'test name ???????????????????
            If xsh.CustomProperties.Count > 0 Then    'si il y a des customproperties
                For X = 1 To xsh.CustomProperties.Count    'boucle sur les custompropertie
                    If xsh.CustomProperties.Item(X).Name = "indice" Then
                        i = 0: i = CLng(xsh.CustomProperties.Item(X))    'récupération de la valeur de indice
                        If i > max Then max = i    ' max devient l'index de boucle sur sheets
                        Exit For    'et on s'arrete(sortie de boucle) a "indice"
                    End If
                Next
            End If
        End If
    Next xsh
    'et enfin on ajoute  l'item indice dans les customproperties et sa valeur qui est max+1
    Sh.CustomProperties.Add "indice", max + 1
End Property

Property Get LastCreatedSheet() As Object
    Dim xsh, i&, max&, leNom$, X& 'Variable
    For Each xsh In ThisWorkbook.Worksheets    'boucle sur sheets
        If xsh.CustomProperties.Count > 0 Then    'si il y a des customproperties
            For X = 1 To xsh.CustomProperties.Count    'boucle sur les custompropertie
                If xsh.CustomProperties.Item(X).Name = "indice" Then Exit For    'et on s’arrête(sortie de boucle) a "indice"
            Next
            If X > 0 Then    'si X > 0
                i = 0: i = CLng(xsh.CustomProperties.Item(X))
                If i > max Then max = i:  leNom = xsh.Name
              End If
        End If
    Next xsh
    If leNom <> "" Then Set LastCreatedSheet = Sheets(leNom)
End Property

sub de test
Code:
Sub test2()
    If Not LastCreatedSheet Is Nothing Then
        MsgBox LastCreatedSheet.Name
    Else
        MsgBox " pas de sheets mémorisé"
    End If
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
oui j'ai saisi le trait d'humour après un petit moment de panique (voila qu'il sort un tableau de bits)
donc pour rendre a cesar ce qui est a cesar
oui je me suis trompé c'est mapomme qui a fait cette proposition au départ

Arthour a part le sheet_new tout est dans un standard
 

Valtrase

XLDnaute Occasionnel
Salut le fil
Une autre approche utilisant un code de ce bon et talentueux Hervé Inisan qui était au départ conçu pour Access et que j'ai modifié pour l'adapter à Excel.
A quoi ça sert ? tout simplement à enregistrer toute sorte d'informations sur une feuille "Paramètres" je m'en sers souvent pour enregistrer les paramètres de mon application. Bien sur c'est long mais à l'utilisation ça rends d'énormes services.
Donc dans un module tu colles les deux fonctions Get et SetParam
VB:
' Procedure : SetParam
' Date      : 14/12/2016
' Révision  : 08/09/2019
' Auteur    : JeanPaul
' Objectif  : Enregistrer un paramètre dans une feuille de paramètres
' Entrée    :
' Sortie    :
' Note      : Si la feuille paramètres n'existe pas elle est créée si le paramètre n'existe pas il sera créé,
'             La plage nommée est étendue à chaque entrée. Si AttriRangeName est sur True la plage Value sera nommée
' Exemple   : SetParam("Formats.Hide.Ribbon", True, "Cache ou affiche le ruban.",True  Retour : pas de retour
Public Function SetParam(Key As String, _
                         Value As Variant, _
                         Optional RemReq As String = "", _
                         Optional AttribRangeName As Boolean = False)

    Dim lRow As Integer, Sh As Sheets, c As Range

    'Si pas de feuille paramètres on l'a crée
    If Not (SheetExist(shParam)) Then
        With ThisWorkbook
            .Sheets.Add After:=Sheets(Sheets.Count)
            With ActiveSheet
                .Name = shParam
                With .Range("A1:C1")
                    .Interior.Color = vbYellow
                    .HorizontalAlignment = xlCenter
                    .VerticalAlignment = xlCenter
                    .WrapText = False
                    .Orientation = 0
                    .AddIndent = False
                    .IndentLevel = 0
                    .ShrinkToFit = False
                    .ReadingOrder = xlContext
                    .MergeCells = False
                End With
                .Range("A1:C1").Value = Array(rngParamKeyName, rngParamValueName, rngParamRemReqName)
                '.visible = xlSheetVeryHidden
                .Columns("A:C").AutoFit
            End With
            .Names.Add Name:=rngParamKeyName, RefersTo:="='Paramètres'!$A$1"
        End With
    End If
    'On ne rafraichi pas la feuille
    Application.ScreenUpdating = False

    'On recherche la clé
    With Worksheets(shParam).Range(rngParamKeyName)
        Set c = .Find(UCase(Key), Lookin:=xlValues)
    'Si elle existe on met à jour
        If Not c Is Nothing Then
            c.Offset(0, 1).Value = Value
            If RemReq <> "" Then
                c.Offset(0, 2).Value = RemReq
            End If
    'Sinon on crée une Clé
        Else
            lRow = .Rows.Count
            Set c = .Range("A" & (lRow + 1))
            c.Value = Format(Key, ">")
            c.Offset(0, 1).Value = Value
            c.Offset(0, 2).Value = RemReq
        End If

    'On crée la plage nommée de la valeur
        If AttribRangeName = True Then
            Dim e As Name, Exist As Boolean
            Exist = False
            For Each e In ThisWorkbook.Names
                If UCase(e.Name) = UCase(c.Value) Then Exist = True
            Next

            Select Case Exist
                Case False
                    ThisWorkbook.Names.Add Name:=FormatParamKeyText(c.Value, vbProperCase), RefersTo:="='" & shParam & "'!" & c.Offset(0, 1).Address
                Case True
                    ThisWorkbook.Names(c.Value).RefersTo = "='" & shParam & "'!" & c.Offset(0, 1).Address
            End Select

        End If

    'On redimensionne la plage nommée Param_Key
        Dim Tableau() As String
        With ThisWorkbook.Names(rngParamKeyName)
            Tableau = Split(.RefersTo, "!")
            ThisWorkbook.Names.Add _
                    Name:=.Name, _
                    RefersTo:=Tableau(0) & "!" & _
                              Range(Tableau(1)).Resize(Range(Tableau(1)).Rows.Count + 1).Address

        End With

    End With

    Worksheets(shParam).Columns("A:C").AutoFit


    If Not c Is Nothing Then Set c = Nothing
    'Worksheets(shParam).Protect Contents:=True, Password:=sPassWord, UserInterfaceOnly:=True

    Application.ScreenUpdating = True

End Function

' Procedure : GetParam
' Date      : 14/12/2016
' Auteur    : JeanPaul
' Objectif  : Lire un paramètre
' Entrée    :
' Sortie    :
' Note      :
' Exemple   : GetParam("Formats.Hide.Ribbon", True  Retour : Pas de retour
Public Function GetParam(Key As String, Optional DefaultValue As Variant = "") As Variant
    Dim c      As Range

    If SheetExist(shParam) = False Then GetParam = "": Exit Function

    'On recherche la clé
    With Worksheets(shParam).Range(rngParamKeyName)
        Set c = .Find(UCase(Key), Lookin:=xlValues, lookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext)
    'Si elle existe on charge sa valeur
        If Not c Is Nothing Then
            GetParam = c.Offset(0, 1).Value
    'Sinon on charge la valeur par défaut
        Else

            GetParam = DefaultValue
        End If

    End With
End Function

Et ensuite dans ThisWorkBook tu colles juste
Code:
Private Sub Workbook_NewSheet(ByVal Sh As Object)
SetParam "LastSheetCreated", Sh.Name
End Sub

Après tu peux accéder de n'importe où à tes informations enregistrées dans ta feuille soit en faisant un :
Code:
strTemp= GetParam("LastSheetCreated")

Soit en l'appelant avec la méthode Range si tu as spécifié AttribRangeName à True
Code:
strTemp= Range("LastSheetCreated").Value
 

Discussions similaires

Membres actuellement en ligne

Statistiques des forums

Discussions
312 023
Messages
2 084 715
Membres
102 637
dernier inscrit
TOTO33000