Manipulation de classeur fermé

thechoux Messages postés 25 Statut Membre -  
thechoux Messages postés 25 Statut Membre -
Bonjour,

Mon problème est le suivant.

Dans un classeur se trouve un planning qui se présente de la manière suivante :

..........Janv Février Mars Avril....

Poste1..R........................P
Poste2..........P................P
Poste3....................P.......

Sachant qu'il y a environ 700 postes.

Ce que je voudrais faire, c'est qu'en ayant choisi le mois à planifier au préalable, ma macro entre dans une variable tableau (Appelons la Tab_Plan) tout les postes ayant un P dans le mois choisi. (Par exemple, si le mois choisi est Avril, ma variable tableau devrait avoir 2 lignes, Poste1 et Poste2).
Je précise que je préfèrerais que le classeur contenant le planning reste fermé.

Une fois Tab_Plan complété, je voudrais que pour chaque poste contenue dans le tableau, ma macro aille extraire les spécifications associées qui se situent dans un classeur, sachant qu'il y a un classeur par poste et que les données voulues se trouvent toutes au même endroit dans chaque classeur spécification.

Evidemment, je pense que vu le nombre de poste planifiés à chaque mois, il faudra extraire ces données sans ouvrir les classeurs spec.

Est-ce réalisable ?

Merci d'avance

7 réponses

  1. thechoux Messages postés 25 Statut Membre 1
     
    Et bien il me semblait que ça serait plus rapide au niveau du temps d'exécution si j'utilisais une variable tableau. Et pour SQL, je débute en VBA alors SQL...il me semble que c'est un système de gestion de base de données mais mes connaissances s'arrêtent là, j'en suis navré.

    Voici le lien du classeur ou je veux concentrer mes données : https://www.cjoint.com/?0EhlUP9llXg
    Le lien du classeur ou se trouve le planning : https://www.cjoint.com/?0Ehl1VExSjK
    Le lien de l'archive avec les fichiers spec : https://www.cjoint.com/?0Ehl4nDNcXe
    1
    1. thechoux Messages postés 25 Statut Membre 1
       
      Les "P" signifie qu'une opération sur le poste est planifiée pour le mois, les "R" que les opérations planifiées sont en retard d'exécution, ils se trouvent uniquement dans la colonne Janvier.
      0
    2. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
       
      Ok, merci

      proposition certainement demain ...

      pour te donner un avant goût sur ce qui t'attends avec la manipulation des fichiers fermés...
      https://silkyroad.developpez.com/VBA/ClasseursFermes/
      0
    3. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
       
      ne pas tenir compte de ce dernier message
      0
  2. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Bonjour,

    Oui c'est faisable.
    Voyez déjà cette discussion, lisez bien également le commentaire de michel_m donné dans cette discussion.
    0
  3. thechoux Messages postés 25 Statut Membre 1
     
    D'accord, donc, si j'ai bien compris, il faudrait que le début de ma macro soit comme ça :

    Option Explicit
    
    Dim Donnees(), valeurs()
    
    Sub Import()
    Dim FeuilleAimporter As String, Classeur As String, Chemin As String, numChamp As Integer
    
    Classeur = "Préventif_CFE_Planning 2014.xlsm"
    FeuilleAimporter = "Suivi"
    Chemin = "\\frsf-sanview\profiles$\trichoux\Bureau\Dossier théo\Dossier graissage\" & Classeur
    Erase Donnees
    Erase valeurs
    ImporterLaTable FeuilleAimporter, Chemin, numChamp
    End Sub
    
    Sub ImporterLaTable(NomFeuilSource As String, strChemin As String, Colonne As Integer)
    Dim Cn As Object
    Dim rst As Object
    
    Set Cn = CreateObject("ADODB.connection")
    Set rst = CreateObject("ADODB;Recordset")
    With Cn
            .Provider = "Microsoft.Jet.OLEDB.4.0"
            .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
                & Fichier & ";Extended Properties=""Excel 12.0;HDR=YES;"""
            .Open
     End With


    Seulement, je capte rien à ces histoires de ADODB, depuis les 2 mois ou j'ai commencé à me plonger dans VBA, j'ai jamais vu ça encore. Qu'est ce que c'est ? Un protocole d'échange entre les fichiers ?

    Quand j'exécute la macro, ça me met le message d'erreur suivant : Type défini par l'utilisateur non défini
    0
    1. thechoux Messages postés 25 Statut Membre 1
       
      Si ça peut aider, voilà ce que j'ai fait jusqu'à présent :

      Sub Demander_dossier_source()

      Dim objShell As Object, objFolder As Object
      Dim Chemin As String, Fichier As String

      Set objShell = CreateObject("Shell.Application")
      Set objFolder = objShell.BrowseForFolder(&H0&, "Choisir un répertoire", &H1&)

      If objFolder Is Nothing Then
      MsgBox "Abandon opérateur", vbCritical, "Annulation"
      Else
      MsgBox (objFolder)
      End If
      End Sub
      Sub UserForm()

      Demandemois.Show
      retard = Demandemois.choix
      moisdemandé = Demandemois.verif
      MsgBox (retard & " " & moisdemandé)
      Unload Demandemois
      End Sub

      Sub Entrer_le_planning_selon_le_mois()
      Dim moisdemandé As Integer
      Dim retard As Integer
      Dim derlign As Integer
      Dim tab_planning
      Dim Chemin As String
      Dim Fichier As String

      'Mise en place de la lecture du planning sans ouvrir le fichier
      Chemin = "\\frsf-sanview\profiles$\trichoux\Bureau\Dossier théo\Dossier graissage\"
      Fichier = Dir(Chemin & "Préventif_CFE_Planning 2014*")

      'La ça marche pas
      ThisWorkbook.Names.Add "Plage", RefersTo:="='" & Chemin & "[" & Fichier & "]Suivi'!Z8:AM8"
      With Sheets("Feuil2")
      .[A1] = "=Plage"
      .[A1].Copy
      Sheets("Feuil1").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
      Sheets("Feuil1").Range("A" & Rows.Count).End(xlUp).Offset(0, 1) = Fichier
      End With
      'derlign = Range("B9").End(xlDown).Row

      End Sub

      Et voilà le code pour l'userform :



      Public Sub Validation_Click() 'Action quand clic sur "Valider le choix"

      Demandemois.Hide

      End Sub
      Public Function verif()
      If OptionButton1.Value Then
      verif = 1
      End If
      If OptionButton2.Value Then
      verif = 2
      End If
      If OptionButton3.Value Then
      verif = 3
      End If
      If OptionButton4.Value Then
      verif = 4
      End If
      If OptionButton5.Value Then
      verif = 5
      End If
      If OptionButton6.Value Then
      verif = 6
      End If
      If OptionButton7.Value Then
      verif = 7
      End If
      If OptionButton8.Value Then
      verif = 8
      End If
      If OptionButton9.Value Then
      verif = 9
      End If
      If OptionButton10.Value Then
      verif = 10
      End If
      If OptionButton11.Value Then
      verif = 11
      End If
      If OptionButton12.Value Then
      verif = 12
      End If


      End Function
      Public Function choix()
      If CheckBox1.Value = True Then
      choix = "vrai"
      Else
      choix = "faux"
      End If
      End Function


      Private Sub activer()
      'Activation du bouton si la condition est vérifiée
      If verif <> "" Then
      'colonne et ligne sont les valeurs renvoyées par les fonctions
      Validation.Enabled = True
      Validation.Caption = "Valider le choix"
      End If
      End Sub

      Private Sub OptionButton1_Click()
      activer 'Lance la procédure "activer"
      End Sub
      Private Sub OptionButton2_Click()
      activer
      End Sub
      Private Sub OptionButton3_Click()
      activer
      End Sub
      Private Sub OptionButton4_Click()
      activer
      End Sub
      Private Sub OptionButton5_Click()
      activer
      End Sub
      Private Sub OptionButton6_Click()
      activer
      End Sub
      Private Sub OptionButton7_Click()
      activer
      End Sub
      Private Sub OptionButton8_Click()
      activer
      End Sub
      Private Sub OptionButton9_Click()
      activer
      End Sub
      Private Sub OptionButton10_Click()
      activer
      End Sub
      Private Sub OptionButton11_Click()
      activer
      End Sub
      Private Sub OptionButton12_Click()
      activer
      End Sub
      0
  4. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
     
    Bonjour,

    Es tu sûr ou obligé d'avoir une variable de tableau puisqu 'il n'y en a pas besoin quand on manipule un fichier fermé ( emploi de SQL) ?

    Peut on avoir que des P ou plusieurs lettres style R, G,X....

    Le mieux serait que tu joignes ton classeur source avec une cinquantaine de postes

    pour joindre une pièce
    mettre le classeur sans données confidentielles en pièce jointe sur
    http://cjoint.com/
    puis copier l'adresse du lien et la coller dans le message de réponse

    0
    1. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
       
      Salut michel,

      Merci du relais, je n'ai pas vraiment le temps en ce moment.
      A+
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
     
    Bonjour,

    Je viens de passer pas mal de temps à essayer de comprendre ce que tu voulais faire et ma foi, je dois être borné...

    par ex:
    je voudrais que pour chaque poste contenue dans le tableau, ma macro aille extraire les spécifications associées qui se situent dans un classeur,
    Lesquelles et où ?

    pour la création de tes fiches "spec" pourquoi ne pas créer un modèle et l'appeler: cela évitera ton usine à gaz de macro et tu auras juste à donner le nom de ta fiche ?
    je suppose que les sous-dossiers "spec" correspondent à la colonne "unité" du planning: je pose la question car rien ne correspond dans ton envoi... par ex:6C ???
    A mon avis, tu as oublié dans le chemin de la fiche le nom du sous-dossier (6C, 6R)

    dans ton fichier test, je n'ai rien compris ; aucun commentaire dans tes macros: dossier source: c'est le quel ?
    Tu crées un userform, OK, mais à quoi sert la variable "verif" et pourquoi utiliser des inputbox assez "bordeliques" puisque le mois est donné par l'userform (un combobox avec le nom des mois aurait été plus simple que 12 optionbutton mais...
    Je me demande qu'est ce qu'il faut importer dans ta fiche "spec": la date, mais la quelle: celle du déclenchement de la macro ?

    si tu veux travailler avec le planning fermé il faudra ajouter une ligne sous la ligne 8 que tu pourras masquer avec le nom des mois sans accent puisqu'il faut concordance des orthographes (le mode sans accent est le bon)

    quant à tes fichiers "spec", il parait difficile de ne pas les ouvrir: il y a peut-^tre une astuce mais pas forcément évidente
    A ce propos, tu as renommé sous format XLs et MSoffice m'envoie un message à chaque demande d'ouverture...

    etc, etc...

    En général toutes tes macros sont à reprendre car "usine à gaz"

    bref, ça semble la planche à savon...

    0
  7. thechoux Messages postés 25 Statut Membre 1
     
    Désolé pour le fouilli, j'aurais du préciser :

    -Dans le classeur test, le module dont je me sert est le premier, le module programme. Le module "banque", c'est juste une banque de macro que j'ai trouvé ou déjà faite pour m'aider à faire les suivantes.

    -Dans le module programme, je n'ai pas encore lié les macros, je les créée juste par étape.

    -Les spécifications de chaque poste planifié sont à extraire des fichiers qui sont dans le dossier spec.

    -Oui effectivement les fiches spécifications sont classées par unité 6E, 6C, VF, VE, il doit y avoir une vingtaine de sous dossier dans le dossier spec.

    -Dans les fiches spec je dois extraire les données dans le tableau qui sont dans la 4 feuilles.
    -L'option verif, c'est encore autre chose ; tu dois avoir remarqué que dans le planning, dans la colonne de Janvier il y a des R. Cela signifie que les opérations pour le poste n'ont pas été réalisées à la date planifiée, et qu'elles sont donc en retard.
    L'option verif, servira à intégrer (ou non) les retards dans le tableau récapitulatif du classeur test.

    En fait mes macros du classeur test et du module programme fonctionnent. Ce que je voudrais savoir c'est si c'est possible de faire une macro qui dit par exemple :

    Si le mois est 11 alors
    On rentre dans var_tableau(1,i) tout les P de Novembre
    On rentre dans var_tableau(2,i) tout les nom_de_poste qui sont sur la même ligne que les P rentrés
    Si verif = Vrai
    On rentre à la suite de var_tableau tout les nom_de_poste qui sont en retard (R dans la colonne Janvier)

    Pour chaque fichier du dossier spec,
    Pour chaque ligne de var_tableau
    Si nom_fichier = nom_de_poste Alors
    Copie des données du nom_fichier dans test

    Voilà en gros ce que je voudrais faire

    En tout cas désolé pour le bordel, j'ai oublié de préciser qu'il y avait que le module programme du fichier test qui était vraiment utile.

    Merci pour le temps consacré.
    0
  8. thechoux Messages postés 25 Statut Membre 1
     
    Bonjour,

    Voilà j'ai réussi à bidouiller un truc qui marche, mais c'est quand même un peu long à s'exécuter, y'aurait il un moyen pour le rendre moins lourd ?

    Function ExisteFichier(fcher As String) As Boolean
    ExisteFichier = (Dir(fcher & ".xlsm") <> "")
    End Function
    
    
    Sub Générale()
    
    'Macro qui lance l'userform pour le choix du mois
    
    Demandemois.Show
    Dim fichiersource As String
    retard = Demandemois.choix 'on enregistre le choix de la prise en compte des retards
    moisdemandé = Demandemois.verif 'on enregistre le mois de plannif choisi
    fichiersource = Demandemois.dossier 'On enregistre le planning choisi
    Unload Demandemois
    
    'Macro qui extrait le planning
    
        Dim i As Integer
        Dim derlig As Long
        Dim Fichier As String
        Dim fichier1 As String
        Dim a As Integer
        Dim base As String
        Dim nom As String
        Dim ligne As Integer
        Dim colonne As Integer
        nom = ActiveWorkbook.Name
        
    
     
       
       
        fichier1 = StrReverse(fichiersource)
        a = InStr(fichier1, "\")
        Fichier = Right(fichiersource, a - 1) & ".xlsm"
        
         'Vérification existance fichier
         
       While ExisteFichier(fichiersource) = False And i < 5
            i = i + 1
            fichiersource = InputBox("Veuillez renseigner un nom de fichier valide, essai " & i & "/5", "Fichier introuvable", fichiersource)
       Wend
       
       'Ouverture du planning
        Workbooks.Open(fichiersource & ".xlsm").Activate
        Sheets("Suivi").Activate
        
        'Génération d'une variable tableau pour entrer le planning
        Dim tabplan()
        derlig = Range("B9").End(xlDown).Row 'on cherche la taille du tableau
        ReDim tablodate(derlig - 2, 14)
    
    'On entre le planning dans la variable tableau
      
      
     For ligne = 9 To derlig
           For colonne = 26 To 40
                tablodate(ligne - 8, colonne - 26) = Workbooks(Fichier).Sheets("Suivi").Cells(ligne, colonne).Value
           Next
     Next
    
    'On génère la variable tableau qui va chercher les postes plannifiés pour le mois demandé.
    
    Dim tablopostes()
    
    'On cherche maintenant la dimension du tableau
    Dim nPlanifié As Integer
    nPlanifié = 0
    For ligne = 9 To derlig
        If Cells(ligne, 2) Like "GRA*" Then 'Si l'opération plannifié concerne le graissage
            If Cells(ligne, moisdemandé + 25) Like "*P" Then
                nPlanifié = nPlanifié + 1
            End If
        End If
    Next
    
    Dim nRetard As Integer
    nRetard = 0
    
    If retard = True Then 'prise en compte des retards
        For ligne = 9 To derlig
            If Cells(ligne, 2) Like "GRA*" Then 'Si l'opération plannifié concerne le graissage
                If Cells(ligne, 26) Like "*R*" Then
                    nRetard = nRetard + 1
                End If
            End If
        Next
    End If
    
    Dim Nbligne As Integer
    Nbligne = nPlanifié + nRetard 'On a trouvé notre nombre de ligne
    ReDim tablopostes(Nbligne, 2) 'On redimentionne donc le tableau
    
    'On rempli maintenant le tableau avec les numéros de poste à prendre en compte
    Dim position_ As Long
    Dim j As Integer
    Dim Tableau() As String
    j = 0
    
    For ligne = 9 To derlig
        If Cells(ligne, 2) Like "GRA*" Then 'Si l'opération plannifié concerne le graissage
            If Cells(ligne, moisdemandé + 25) Like "*P" Then
                j = j + 1
                position_ = InStr(Cells(ligne, 4), "_") 'On cherche la position du caractere "_" dans la désignation du poste
        
                    If position_ = 0 Then
                        MsgBox ("Numéro de poste invalide à la ligne " & ligne & " merci de corriger") 'S'il n'y a pas de "_" dans la cellule alors on affiche un message d'avertissement
                        tablopostes(j, 1) = Cells(ligne, 4).Value 'On rentre quand même la valeur brute dans le tableau, sachant qu'elle risque de ne pas être prise en compte lors de la rcherche des specs
                    Else
                        tablopostes(j, 1) = Mid(Cells(ligne, 4), position_ + 1, 10) 'On rentre le numéro de poste dans le tableau
                    End If
        
                 'on va maintenant rentrer dans la deuxième colonne de tablopostes l'action à effectuer
                'découpe la chaine en fonction des espaces " "
                'le résultat de la fonction Split est stocké dans un tableau
                Tableau = Split(Cells(ligne, 2), "-")
                tablopostes(j, 2) = Tableau(1)
        
            End If
        End If
    Next
      
    
    If retard = True Then 'prise en compte des retards
        For ligne = 9 To derlig
            If Cells(ligne, 2) Like "GRA*" Then 'Si l'opération plannifié concerne le graissage
                If Cells(ligne, 26) Like "*R*" Then
                    j = j + 1
                    position_ = InStr(Cells(ligne, 4), "_") 'On cherche la position du caractere "_" dans la désignation du poste
        
                    If position_ = 0 Then
                        MsgBox ("Numéro de poste invalide à la ligne " & ligne & " merci de corriger") 'S'il n'y a pas de "_" dans la cellule alors on affiche un message d'avertissement
                        tablopostes(j, 1) = Cells(ligne, 4).Value 'On rentre quand même la valeur brute dans le tableau, sachant qu'elle risque de ne pas être prise en compte lors de la rcherche des specs
                    Else
                        tablopostes(j, 1) = Mid(Cells(ligne, 4), position_ + 1, 10) 'On rentre le numéro de poste dans le tableau
                    End If
        
                Tableau = Split(Cells(ligne, 2), "-")
                tablopostes(j, 2) = Tableau(1)
                End If
            End If
        Next
    End If
    
    'on va maintenant demander à l'utilisateur quel est le dossier ou se trouve les fichiers spec
     Dim objShell As Object, objFolder As Object
         Dim Chemin As String, Msg As String
         Dim FlagChoix As Long, NbPoint As Integer
    
         If SelType = 0 Then
              FlagChoix = &H1
              Msg = "Sélectionner un dossier :"
         Else
              FlagChoix = &H4000
              Msg = "Sélectionner un fichier :"
         End If
    
         Set objShell = CreateObject("Shell.Application")
         Set objFolder = objShell.BrowseForFolder(&H0&, Msg, FlagChoix)
        
    'Si l 'objet retourné est valide, on teste son contenu (item.title)
         'Si on a sélectionné la racine d'une partition, il se compose du nom de la partition,
         ' suivi de sa lettre et ":" entre parenthèses
         NbPoint = InStr(objFolder.Title, ":")
         If NbPoint = 0 Then
              
    'Sinon, il se compose du nom du dossier uniquement, sans le chemin précédent
              'On récupère ce chemin à l'aide des propriété et méthode ParentFolder.ParseName
              Chemin = objFolder.ParentFolder.ParseName(objFolder.Title).Path & ""
         Else
              
    
    Chemin = Mid(objFolder.Title, NbPoint - 1, 2) ' si racine on récupère la lettre du lecteur et les 2 points
    
         End If
         choixdossierfichier = Chemin
         MsgBox choixdossierfichier
        
        'On va maintenant chercher les specs en fonction des postes plannifiés
        Dim FSO As Scripting.FilesystemObject
        Dim DossierSource As Scripting.Folder
        Dim spec As Scripting.file
        Dim r As Long
        Dim derlign As Long
        Set FSO = New Scripting.FilesystemObject
        Set DossierSource = FSO.GetFolder(Chemin)
        
        r = 0
        
        For i = 1 To UBound(tablopostes, 1)
            For Each spec In DossierSource.Files
                If spec.Name Like tablopostes(i, 1) & ".xlsx" Then
                    Dim Source As ADODB.Connection
                    Dim Rst As ADODB.Recordset
                    Dim ADOCommand As ADODB.Command
                    Dim nFichier As String, Cellule As String, Feuille As String
                    Dim nLigne As Integer
                    
                    'plage de cellules à importer
                    Cellule = "A12:G30"
                    
          
                    Feuille = "Plan de maintenance$" 'n'oubliez pas d'ajouter $ au nom de la feuille.
                    
                    nFichier = choixdossierfichier & "\" & spec.Name 'Chemin complet du classeur fermé
                    
                    Set Source = New ADODB.Connection
                    With Source
                        .Provider = "Microsoft.Jet.OLEDB.4.0"
                        .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
                         & nFichier & ";Extended Properties=""Excel 12.0;HDR=YES;"""
                        .Open
                    End With
    
    
                    Set ADOCommand = New ADODB.Command
                    With ADOCommand
                        .ActiveConnection = Source
                        .CommandText = "SELECT * FROM [" & Feuille & Cellule & "]"
                    End With
                      
                    Set Rst = New ADODB.Recordset
                    Rst.Open ADOCommand, , adOpenKeyset, adLockOptimistic
                      
                    Set Rst = Source.Execute("[" & Feuille & Cellule & "]")
                    Workbooks("test.xlsm").Activate
                    derlign = Range("B1").End(xlDown).Row
                    
                    If derlign > 10000 Then
                        Range("B1").CopyFromRecordset Rst
                       
                        For nLigne = 10 To 1 Step -1
                            If Cells(nLigne, 5).Value <> tablopostes(i, 2) Then
                                Range("A" & nLigne & ":" & "H" & nLigne).Delete
                            End If
                        Next
                         Range("A1") = tablopostes(i, 1)
                    Else
                    
                        Range("B" & derlign + 1).CopyFromRecordset Rst
                        
                        
                        For nLigne = derlign + 10 To derlign + 1 Step -1
                            If Cells(nLigne, 5).Value <> tablopostes(i, 2) Then
                                Range("A" & nLigne & ":" & "H" & nLigne).Delete
                            End If
                        Next
                        Range("A" & derlign + 1) = tablopostes(i, 1)
                    End If
                
                    Rst.Close
                    Source.Close
                    Set Source = Nothing
                    Set Rst = Nothing
                    Set ADOCommand = Nothing
    
                    
                End If
            Next spec
        Next
        
        Set spec = Nothing
        Set DossierSource = Nothing
        Set FSO = Nothing
        
    End Sub
    
    0