Lire une ligne entière d'un fichier excel depuis le VBA d'un autre Fichier .xls

Signaler
-
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
-
Bonjour !
J’ai un début de macro excel qui ouvre un fichier et lit des valeurs et que je veux améliorer.
Ci desssous un petit briefing :

Bonjour Fabiendag, Mpi!
J'ai pris compte de vos deux remarques et j'ai adapté la macro: Une première fonction permet d'ouvrir une boite de dialogue:
Code :
Function RechercheFichier() As String
Dim fd As FileDialog
Dim NomFichier As String

Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Filters.Add "Fichiers Excel", "*.xls"
.Title = "TITRE"
.InitialFileName = "FICHIER.xls"
End With
If fd.Show -1 Then NomFichier fd.SelectedItems(1)

RechercheFichier = NomFichier
Set fd = Nothing
End Function


Ensuite j'ouvre mon fichier:
Code :
Sub recherche()

Dim NomFichier As String

NomFichier = RechercheFichier()
If NomFichier = "" Then
MsgBox "Vous n'avez sélectionné aucun fichier"
Else
Workbooks.Open NomFichier
End If
Dim ValeurCherche As String
Dim Plage As Range
ValeurCherche = InputBox("Entrez une valeur")
If Trim(ValeurCherche) <> "" Then
With Sheets("Feuil1").Range("A:A") 'Recherche dans colonne A
Set Plage = .Find(What:=ValeurCherche, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Plage Is Nothing Then
Application.Goto Plage, True 'valeur trouvé
Else
MsgBox "Recheche nulle" 'value non trouvé
End If
End With
End If
End Sub

Je crois qu'on a peu près résolu le problème d'ouverture du fichier (même si j'envisage quelque améliorations)

Cela nous mène au 2ème point:
Dans ma feuille j'ai un nombre de ligne et de colonne fixe qui peut varier et ce qui va changer aussi c'est le nom de l'onglet (ou SHEET) sur lequel les recherches vont devoir être effectué (mais ce point n'est pas important, je changerai le nom de l'onglet à ouvrir au fur à mesure).
Ce qui m'importe c'est comment définir la ligne à balayer pour faire mon test. Je peux très bien modifier cette partie :
Code :
With Sheets("Feuil1").Range("A:A") '

Mais ce que j'envisage de faire est un peu plus complexe

le problème de l'ouverture du classeur étant résolu je souhaite :
1°) Faire une différence entre une valeur dans une cellule du 1er classeur et une autre dans une autre cellule du second classeur.Celle du 2nd classeur étant mise à jour quotidiennement, (la valeur à chercher dans le 2nd Classeur doit donc être la valeur max de la plage "row" concernée).

2°) Mettre plusieurs mise en forme conditionnelle (sur toute la ligne)lié à la valeur de cette différence.

Est ce que vous avez une idée de la procédure que je peux suivre ou me guider, j'adapterai le code avec votre aide bien sûr.

[b]
Merci de votre attention/b

15 réponses

Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Bonjour,

Préférablement une seule question par post...

Ceci dit, ce n'est pas très clair... Est-ce que tu veux avoir la valeur la plus haute de chaque ligne ou d'une seule ligne en particulier ? et si c'est le cas laquelle ou comment la trouver ?

Pour trouver la valeur la plus haute, tu pourrais soit utiliser une formule avec MAX, soit boucler la ligne et sortir la plus haute valeur dans une variable...


MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
239
Bonjour, MPi,
sans oublier l'utilisation de WorkSheetFunction.Max
Je vous laisse continuer.
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Salut ucfoutu,
C'est effectivement à ça que je pensais avec ma fonction Max...
Manque de précision de ma part...

MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Bonjour à tous!
Merçi d'avoir répondu aussi rapidement.

Afin de répondre à ceci:
Préférablement une seule question par post...
Ceci dit, ce n'est pas très clair... Est-ce que tu veux avoir la valeur la plus haute de chaque ligne ou d'une seule ligne en particulier ? et si c'est le cas laquelle ou comment la trouver ?

Je vous propose ceci:
Comme ce qui se conçoit clairement s'énonce clairement (ou vice versa..), est ce que je vous fais un TOPO de ce que j'envisage de faire? vous pouvez ainsi me dire que je fais fausse route ou me dire vaut mieux passer par ce chemin çi( quitte par la suite à ce que je développe tout seul)?

Merçi
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Plus les problèmes sont expliqués clairement, plus rapide est la réponse...

Je dirais qu'une fois la valeur recherchée (.Find), tu connais donc la ligne s'il n'y a qu'une seule valeur à trouver: Plage.Row

Tu pourrais déterminer le nombre de colonnes de cette ligne
nbColonnes = Cells(Plage.Row, Columns.Count).End(xlToLeft).Column

Tu peux alors utiliser la fonction MAX dont ucfoutu t'a parlé.

MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Je vous fais le T0PO : j’ai deux classeurs Classeur1 et Classeur2.

Dans le Classeur1 j’ai plusieurs onglets (dont deux qui m’intéresse).
Dans chacun des 2 onglets (du Classeur1), Il y a des cellules sur plusieurs lignes et colonnes dans lesquelles je fais des différences de valeurs.
Par exemple CELL11(Classeur1)=Valeur_Cell_Issue_du_Classeur2 -CELL9(Classeur1). Et sur cette différence je fais une MFC.

NB : Les cellules du classeur1 dans les quelles se trouvent les valeurs et le résultat, sont toutes sur une même colonne (ce sont les lignes qui varient)

Les données dans le Classeur2 i.e. (Valeur_Cell_Issue_du_Classeur2) sont actualisées chaque jour et évoluent colonne par colonne.
J’aurais pu créer un Onglet supplémentaires dans classeur1 avec les valeurs du Classeur2 qui interviennent dans le calcul, et actualiser le Classeur1 tous les jours.

Je souhaite que lors de l’ouverture de Classeur2 (pour actualisation des données) que le classeur1 soit ouvert aussi et que la valeur intervenant dans le calcul à savoir (Valeur_Cell_Issue_du_Classeur2) soit mise à jour et que le résultat de la différence tienne compte de la MFC.


Pour l’instant c’est l’inverse que je fais j'ouvre le Classeur2 lors de l’ouverture du Classeur1.

La suite vous la connaissez surtout le point concernant la valeur à récupérer dans le Classeur2.En effet dans le classeur2 si je prends la Cell(F12),le lendemain lors de la mise à jour ce sera la CELL(G12)qui renseignée. Et mon calcul devra tenir compte de cette nouvelle valeur G12 (qui peut être supérieure ou égale à celle de la veille)

C’est un peu tiré par les cheveux mais si vous pensez qu'il y a une meilleure façons de faire avant d'attaquer la macro ci-dessus, je suis preneur.
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Et maintenant, où est-ce que tu coinces ?

l'ouverture d'un fichier B peut être faite à l'ouverture d'un fichier A dans l'événement Workbooks_Open

Il faut tout de même vérifier s'il est déjà ouvert en balayant toutes les applications déjà ouvertes
Dim Fenetre As Window
For Each Fenetre in Windows
  If Fenetre.Caption = "NomDuFichieràOuvrir" then
    Trouvé = True ' et on ne cherche pas à l'ouvrir une 2e fois
......


tu pourrais mettre ce genre de code dans une Function qui te retourne un Boolean


MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Merçi à tous!

Je vais opter pour que lors de l'ouverture du fichier B que le A s'ouvre et que la mise à jour soit faite comme spécifié plus haut.

Et maintenant, où est-ce que tu coinces ?
==> Ou peut on trouver des cours sur VBA excel qui permettent de bien faire distingo entre module, module de classe, function ainsi que leur portée. Pour l'instant je n'en ai pas une idée très précise. Je me débrouille;

Merçi!!
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Un bon manuel a toujours sa place...


MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Salut Mpi merci pour tes conseils (ainsi qu'a toi UCFOUTU)
J'ai adapté la macro du fichier B pour ouvrir un fichier . Cf le code ci dessous:
Function RechercheFichier() As String

   Function RechercheFichier() As String

    Dim Fenetre As Window
    For Each Fenetre In Windows
        If Fenetre.Caption = " FICHIER.xls" Then
            Trouvé = True ' et on ne cherche pas à l'ouvrir une 2e fois
             MsgBox " FICIER.XLS OUVERT CHECK MFC"
             Exit For
          End If
          
            Dim fd As FileDialog
            Dim NomFichier As String
            Set fd = Application.FileDialog(msoFileDialogFilePicker)
            With fd
            .Filters.Add "Fichiers Excel", "*.xls"
            .Title = "TITRE"
            .InitialFileName = "FICHIER.xls"
            End With
    If fd.Show -1 Then NomFichier fd.SelectedItems(1)
 
    RechercheFichier = NomFichier
    Set fd = Nothing
    Next Fenetre
    End Function
    


Maintenant je dois gérer la lecture des valeurs du fichier B en question et leur mise en jour dans le Fichier A (dans les cellules correspondantes) pour faire le calcul. Je dois réadapter la MACRO du début
Sub recherche() notamment la partie inputbox vu que je ne cherche pas une valeur spécifique mais je balaie une plage pour trouver une valeur max

Je dois marquer ce post résolu avant qu'on attaque la partie compliquée??
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
En fait, je modifierais un peu ta procédure et oui, il serait préférable d'ouvrir un autre post avec un titre adéquat au problème.

De la façon dont tu procède, tu vérifies la présence du fichier à savoir s'il est ouvert, mais tu passes tout de même dans l'ouverture de ta boîte de dialogue...

En passant, quand tu mets du code, utilise la 3e icones à droite pour formater ton code. Sélectionne ton code et choisi VB dans la liste.

Function RechercheFichier() As String

    Dim Fenetre As Window
    Dim fd As FileDialog
    Dim NomFichier As String

    For Each Fenetre In Windows
        If Fenetre.Caption = "FICHIER.xls" Then
            Trouvé = True ' et on ne cherche pas à l'ouvrir une 2e fois
            MsgBox " FICIER.XLS OUVERT CHECK MFC"
            NomFichier = Fenetre .Caption
            Exit For
        End If
    Next Fenetre

    If Not Trouvé then     'Faire la suite si le fichier n'a pas été trouvé
        Set fd = Application.FileDialog(msoFileDialogFilePicker)
        
        With fd
            .Filters.Add "Fichiers Excel", "*.xls"
            .Title = "TITRE"
            .InitialFileName = "FICHIER.xls"
        End With

        If fd.Show -1 Then NomFichier fd.SelectedItems(1)
    End If

    RechercheFichier = NomFichier

    Set fd = Nothing
    'Next Fenetre
End Function




MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Bonjour Mpi,
Effectivement, je l'avais remarque au dernier moment mais je n'ai pas pu corriger le post. Merçi de me l'avoir signalé.
J'ai fais quelques modifications:
j'ai rajouté dans le thiswoorkbook ceci pour que la macro s'exécute automatiquement lors de l'ouverture du classeur excel:
Private Sub Workbook_Open()

Call RechercheFichier
   
End Sub

Si j'ai bien compris la macro parcourt juste les différents fichiers excel qui sont ouvert et propose d'ouvrir celui qui m'intéresse.
Cependant je veux que le "bon" fichier soit ouvert lors de l'exécution de la fonction.
Function RechercheFichier() As String

    Dim Fenetre As Window
    Dim fd As FileDialog
    Dim NomFichier As String

    For Each Fenetre In Windows
        If Fenetre.Caption = "FICHIER.xls" Then
            Trouvé = True ' et on ne cherche pas à l'ouvrir une 2e fois
            MsgBox " FICIER.XLS OUVERT CHECK MFC"
            NomFichier = Fenetre .Caption
            Exit For
        End If
    Next Fenetre

    If Not Trouvé then     'Faire la suite si le fichier n'a pas été trouvé
        Set fd = Application.FileDialog(msoFileDialogFilePicker)
        
        With fd
            .Filters.Add "Fichiers Excel", "*.xls"
            .Title = "TITRE"
            .InitialFileName = "C:\Documents and Settings\..."
        End With

        If fd.Show -1 Then NomFichier fd.SelectedItems(1)
    End If

    RechercheFichier = NomFichier
If NomFichier <> "FICHIER.xls" Then
        MsgBox " MAUVAUIS FICHIER REESSAYEZ"
        ElseIf NomFichier = "FICHIER.xls" Then
        Workbooks.Open NomFichier
    End If
    Set fd = Nothing
    'Next Fenetre

End Function


Mais même quand je chois le "bon fichier" çà ne renvoie rien. Est ce qu'il faut utiliser la fonction Item()?

merci!
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
239
Je ne comprends pas vos démarches, car trop risquées.
La présence d''une fenêtre avec le caption "FICHIER.xls" ne veut pas dire avec certitude qu'il s'agit du bon classeur. Un autre, de ce même nom, pourrait exister dans un autre répertoire et être choisi pour traitement. Or, ce choix serait ignoré si une fenêtre déjà ouverte avait par malheur déjà ce nom !
La fonction GetObject met à l'abri de tels aléas. Si le classeur (celui choisi, quel que soit son nom, dans un répertoire) est déjà ouvert : n'en ouvrira pas un nouveau. Si au contraire non encore ouvert === >> l'ouvrira

Exemple : (ici, bien sur, remplacer toto par le résultat du choix fait par Application.FileDialog )
Dim toto As Object
  Set toto  = GetObject("d:\Classeur1.xlsm")
  toto.Windows(1).Visible =  True
  toto.Activate

Je passerais donc systématiquement par Filedialog, personnellement.
Au besoin (si vraiment nécessaire), je mettrais les chemins complets dans une collection ce que j'ouvre (juste pour le confort de l'utilisateur, que je ne forcerais pas à choisir à nouveau un fichier déjà ouvert)
Je ne faisais que passer.
Continuez.

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
19
Il y a effectivement risque de se mélanger avec 2 fichiers ayant le même nom...
Par contre, si on l'ouvre une deuxième fois dans une autre instance d'Excel, il sera en lecture seule, si je ne me trompe ... (?)

Quoiqu'il en soit, pour le code suggéré ici, la Function devrait retourner une string avec le nom du fichier, sinon une string vide si annulé et c'est avec ce retour que tu dois utiliser Workbooks.Open ou laisser tomber.

Private Sub Workbook_Open()
   Dim NomFichier as String

   NomFichier = RechercheFichier()
   
   If NomFichier = "" Then Exit Sub  'a été annulé

   If NomFichier <> "OK" then  's'il n'est pas déjà ouvert
      Workbooks.Open NomFichier   
   End If

   '... et le reste du code

End Sub

Function RechercheFichier() As String
    Dim Fenetre As Window
    Dim fd As FileDialog
    Dim NomFichier As String

    For Each Fenetre In Windows
        If Fenetre.Caption = "FICHIER.xls" Then
            Trouvé = True ' et on ne cherche pas à l'ouvrir une 2e fois
            MsgBox " FICHIER.XLS OUVERT CHECK MFC"
            Windows("FICHIER.xls").Activate ' le fichier est activé et on sort
            RechercheFichier="OK"
            Exit Function   
        End If
    Next Fenetre

    If Not Trouvé then     'Faire la suite si le fichier n'a pas été trouvé
        Set fd = Application.FileDialog(msoFileDialogFilePicker)
        
        With fd
            .Filters.Add "Fichiers Excel", "*.xls"
            .Title = "TITRE"
            .InitialFileName = "C:\Documents and Settings\..."
        End With

        If fd.Show = -1 Then 
           NomFichier = fd.SelectedItems(1)
           RechercheFichier = NomFichier
        End If  
    End If

End Function


Je n'ai pas testé, mais ça devrait fonctionner.
Perso, j'utilise GetOpenFilename plutôt que FileDialog(msoFileDialogFilePicker)

MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
239
Par contre, si on l'ouvre une deuxième fois dans une autre instance d'Excel, il sera en lecture seule, si je ne me trompe ... (

réponse :
La fonction GetObject met à l'abri de tels aléas. Si le classeur (celui choisi, quel que soit son nom, dans un répertoire) est déjà ouvert : n'en ouvrira pas un nouveau. Si au contraire non encore ouvert ===>> l'ouvrira

Essaye.
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.