Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Résultat d'une sélection vers Excel

27 réponses
Avatar
Francis
Bonjour,
Je dispose actuellement d'une transaction qui me permet de faire une
sélection sur un certain nombre de critères, et dont le résultat du
filtre est contenu dans la variable nommée strfiltre. Ce filtre est
appliqué à une requête "Ma_requête" et le résultat peut soit être
affiché à l'écran, soit être imprimé sur un état.
Je voudrais aussi pouvoir transférer ce résultat vers excel, mais là
mes compétences en programmation sont largement insuffisantes. :/
Je suis donc preneur de toute aide en la matière. Merci à l'avance

Francis

--
Francis
fhgc@wanadoudou.fr
LOI DE MOSES
C'est quand on ne regarde pas que le but est marqué.

10 réponses

1 2 3
Avatar
Eric
re Bonsoir,

Je ne suis pas un spécialiste de l'automation alors ...
Essaie cette procédure sur clic d'un bouton de commande de ton
formulaire qui affiche tes données filtrées:

Private Sub Commande1_Click()
' Charger la référence Microsoft DAO Library 3.x
' Déclaration en late binding pour éviter les conflits de version
d'Excel
Dim xlApp As Object
Dim xlWbk As Object
Dim xlWks As Object
Dim Col As Integer
Dim Rs As DAO.Recordset

Set xlApp = CreateObject("Excel.Application")
Set xlWbk = xlApp.Workbooks.Add
Set xlWks = xlWbk.ActiveSheet
'Recupération du jeu d'enregistrements
Set Rs = Me.RecordsetClone
Rs.MoveFirst

'Ecriture du nom des champs sur la ligne 1 d'Excel
For Col = 0 To Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next Col
' Copie du jeu à partir de A2 dans Excel
xlWks.Cells(2, 1).CopyFromRecordset Rs
Rs.Close

'Sauvegarde du classeur
xlApp.Workbooks(1).SaveAs "c:test.xls"
xlApp.Quit

Set Rs = Nothing
Set xlWks = Nothing
Set xlWbk = Nothing
Set xlApp = Nothing
End Sub



Bonsoir Eric,
J'ai appliqué ta proposition, mais le compilateur n'accepte pas la ligne
de code:
xlApp.CurrentWorkbook.SaveAs "NomDuClasseur"
dans laquelle j'ai remplacé NomDuClasseur" par "C:Test"
Ça faisait la même chose avec Next après Rs.Movenext.
Dans les deux cas, j'ai aussi une feuille excel qui s'ouvre, mais rien
ne se passe.
Francis





--
A+
Eric
http://www.mpfa.info/
Archives : http://groups.google.fr/group/microsoft.public.fr.access?hl=fr

Avatar
Michel_D
Une fois que tu auras formalisé ton filtre multicritères cela te donnera
la condition de ta requête, ensuite :

sSql="Le_SQL_de_la_requête"
' Puis soit tu crée une requête
Set oRst=CurrentDb.CreateQueryDef("MaRequete",sSql)
' ou tu modifie une requête existante
Set oRst=CurrentDb.QueryDefs("MaRequete")
oRst.SQL=sSql
' et enfin exportation du résultat de la requête vers excel
DoCmd.TransferSpreadsheet 1,8,"MaRequete","C:ToncheminFichier.xls"



re,
Oui, c'est bien ça. Actuellement, j'ai la possibilité de visualiser ou
d'imprimer ce résultat, mais je voudrais aussi pouvoir l'exporter au
format excel pour traitements complémentaires. Je sais comment exporter
une requête dans sa forme initiale, mais pas après application d'une
sélection multicritères.
Ça ne doit pas être super compliqué, probablement, mais je ne sais pas
faire :/


Michel_D a formulé ce samedi :
re,

Si j'ai bien compris tu veux exporter le résultat d'une requête, donc ...


Bonsoir Michel,
C'est bien ça, il manquait un Next après Rs.MoveNext.
Ceci étant, ça ne marche pas quand même, et je ne pense pas que ça
réponde à ma demande.
Aurais-tu, à tout hasard, quelquechose à me proposer ?
Francis


Bonjour,

A priori il manque un Next dans le code.


Re bonsoir,

Je ne sais pas où ça cloche, mais je reçois systématiquement le
message d'erreur de compilation: "Wend sans While", alors que le
While figure bien dans ton code.
Alors, où est la faille ???
J'espère que pour toi ça sera limpide,
@+
Francis


Gloops a émis l'idée suivante :
[Transfert des résultats d'une requête vers Excel]

Bonjour,

Attention au mot transaction, ça désigne quelque chose de très
précis pour un programmeur Access :)

Ensuite, il serait bien d'exprimer de manière pratique ce qu'il y
a à faire. J'ai l'impression qu'il y a plusieurs façons de s'y
prendre, et que le choix dépend grandement de l'énoncé du problème.

Je suppose déjà que la requête est définie sur la base de données
où on va taper le code, pour appeler des tables de la même base de
données, et qu'on veut envoyer le résultat vers un nouveau fichier
Excel.

J'ai eu quelque chose de très proche à faire hier, j'ai parcouru
deux boucles, l'une décrivant les colonnes sur une ligne, inscrite
dans une autre qui décrit les différentes lignes.

ça ressemble à ça, que je tape au fil du clavier sur une machine
où il n'y a pas Excel ni Access :

Commencer par ouvrir, depuis un module, la boîte Outils /
Références, et y cocher Microsoft Excel.

Public Sub Transfert()
Dim xlApp As New Excel.Application
Dim xlWks as Excel.Worksheet
Dim Lig As Integer, Col As Integer
Dim Rs As Recordset

xlApp.Visible = True
xlApp.Workbooks.Add
xlApp.CurrentWorkbook.SaveAs "NomDuClasseur"
Set xlWks = xlApp.Workbooks("NomDuClasseur").Worksheets(1)
Set Rs = CurrentDb().QueryDefs("MaRequête").OpenRecordset()
While Not Rs.EOF
Lig = 1
For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(Lig, Col + 1) = Rs.Fields(Col)
Rs.MoveNext
Wend
Rs.Close
Set Rs = Nothing

'Après il reste à fermer les objets xlApp et xlWks,
'une fois qu'on n'en a plus besoin :

xlApp.Workbooks("NomDuClasseur").Close
xlApp.Quit
Set xlApp = Nothing
Set xlWks = Nothing

End Sub














Avatar
Gloops
Francis a écrit, le 19/04/2008 21:21 :
Bonsoir Michel,
C'est bien ça, il manquait un Next après Rs.MoveNext.


Objection votre honneur.

Si on veut que le code ait une petite chance de fonctionner, c'est AVANT
le Rs.MoveNext qu'il faut placer le Next, que j'ai effectivement oublié .

Les deux structures de code en jeu sont :

Boucle :

For N = 1 to Max
'traitement sur boucle
Next


Traitement sur jeu d'enregistrements :

Set Rs = DB.OpenRecordset(...)
While Not Rs.EOF 'tant qu'il reste des données à traiter
'traitement d'un enregistrement

Rs.MoveNext 'passage à l'enregistrement suivant
Wend 'fermeture de la boucle
Rs.Close 'fermeture du jeu d'enregistrements
Set Rs = Nothing 'libération de la variable

En réimbriquant les deux
(le traitement d'un enregistrement est constitué d'une incrémentation de
Lig suivie d'une boucle sur les champs) :

Lig = 1
Set Rs = CurrentDb().QueryDefs("MaRequête").OpenRecordset()
While Not Rs.EOF
'===== Début de traitement de l'enregistrement
Lig = Lig + 1
For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(Lig, Col + 1) = Rs.Fields(Col)
Next
'===== Fin de traitement de l'enregistrement
Rs.MoveNext 'passage à l'enregistrement suivant
Wend
Rs.Close
Set Rs = Nothing

L'indentation a bien pour but d'aider à se rendre compte qu'il manque
quelque chose (un Wend après un While, un Next après un For, un Rs.Cl ose
après un OpenRecordset ou un Rs.MoveNext dans une boucle entre les deux
...). Mais cette semaine il y a eu quelques soirées un peu longues :)

Pas que pour moi apparemment : personne n'a relevé que j'ai tout écri t
sur la première ligne du fichier cible
(Lig = 1 au lieu de Lig = Lig + 1). Je dis ceci pour faire l'économ ie du
prochain message : "ça y est ça ne plante plus mais je n'ai qu'une li gne
d'écrite dans le fichier".

Dans Excel, Cells a pour premier argument le numéro de ligne, pour
deuxième argument le numéro de colonne (en tout cas pour la syntaxe a vec
deux arguments numériques).

On notera les différences de notation entre la source et la cible : les
champs d'un jeu d'enregistrements sont numérotés à partir de zéro , alors
que les colonnes d'une feuille Excel sont numérotées à partir de 1, d'où
Col + 1 en deuxième argument de Cells. Par ailleurs on fournit la ligne
en premier argument de Cells, mais en source pour s'adresser à la bonne
ligne on sélectionne l'enregistrement correspondant, c'est l'instructio n
Rs.MoveNext qui joue ce rôle.

Si on oublie Rs.MoveNext on ne reprend pas la main sans interruption
brutale du programme, puisqu'on n'arrive jamais à Rs.EOF (fin du jeu
d'enregistrements). Si Access veut bien rendre la main avec les touches
Ctrl Pause c'est tant mieux, sinon c'est fin d'Access avec le
gestionnaire des tâches de Windows (un progrès par rapport à l'ép oque
DOS où on redémarrait la machine).


Dans le code ci-dessus j'ai pris soin de libérer la première ligne du
fichier Excel (Lig = 1 plutôt que 0 avant la boucle, incrémentation
avant d'exploiter les données), on peut donc y mettre les noms des
champs en attendant d'y mettre des intitulés plus explicites.

Entre le Wend et le Rs.Close :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next

J'ai mis le nom du champ pour simplifier, mais
Rs.Fields(Col).Properties("Description") devrait donner quelque chose de
plus parlant si on a pris soin de renseigner la propriété corresponda nte
dans la description de la table. Attention, si ce n'est pas le cas,
cette syntaxe retourne une erreur.

Il faut donc l'inclure dans une fonction :

Function DescriptionChamp(Fd As Field) As String
On Error Goto ErrDescriptionChamp
DescriptionChamp = Fd.Properties("Description")
Exit Function
ErrDescriptionChamp:
DescriptionChamp = ""
End Function

Ceci permettra de transférer les descriptions existantes comme ceci :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = DescriptionChamp(Rs.Fields(Col))
Next

En espérant que cette fois je n'ai pas oublié une instruction décis ive.
Sinon je finirai bien par démarrer la machine avec les applications.

Avatar
Gloops
Michel_D a écrit, le 19/04/2008 23:31 :
DoCmd.TransferSpreadsheet 1,8,"MaRequete","C:ToncheminFichier.xls"



Effectivement j'ai loupé des instructions plus simples.
Eric en a donné un autre exemple.

Avatar
Gloops
Eric a écrit, le 19/04/2008 23:29 :
xlWks.Cells(2, 1).CopyFromRecordset Rs



Ben moi je dis un truc : on n'a jamais fini d'apprendre.
Et j'ai bien fait de passer un peu de temps dans le newsgroup, car une
fois que mon code fonctionnait, je ne voyais guère de raison de cherche r
autre chose dans l'aide (à chaque nouvelle version d'Excel).

Avatar
Francis
Bonjour Michel, Eric et Gloops,
et merci beaucoup pour vos propositions "nocturnes".
Avec ça, j'ai de quoi m'occuper pour une bonne partie de la journée.
Je vous tiendrai au courant de ma réussite ou de mes problèmes.
Bon dimanche,
Francis

Gloops a émis l'idée suivante :
Francis a écrit, le 19/04/2008 21:21 :
Bonsoir Michel,
C'est bien ça, il manquait un Next après Rs.MoveNext.


Objection votre honneur.

Si on veut que le code ait une petite chance de fonctionner, c'est AVANT le
Rs.MoveNext qu'il faut placer le Next, que j'ai effectivement oublié.

Les deux structures de code en jeu sont :

Boucle :

For N = 1 to Max
'traitement sur boucle
Next


Traitement sur jeu d'enregistrements :

Set Rs = DB.OpenRecordset(...)
While Not Rs.EOF 'tant qu'il reste des données à traiter
'traitement d'un enregistrement

Rs.MoveNext 'passage à l'enregistrement suivant
Wend 'fermeture de la boucle
Rs.Close 'fermeture du jeu d'enregistrements
Set Rs = Nothing 'libération de la variable

En réimbriquant les deux
(le traitement d'un enregistrement est constitué d'une incrémentation de Lig
suivie d'une boucle sur les champs) :

Lig = 1
Set Rs = CurrentDb().QueryDefs("MaRequête").OpenRecordset()
While Not Rs.EOF
'===== Début de traitement de l'enregistrement
Lig = Lig + 1
For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(Lig, Col + 1) = Rs.Fields(Col)
Next
'===== Fin de traitement de l'enregistrement
Rs.MoveNext 'passage à l'enregistrement suivant
Wend
Rs.Close
Set Rs = Nothing

L'indentation a bien pour but d'aider à se rendre compte qu'il manque quelque
chose (un Wend après un While, un Next après un For, un Rs.Close après un
OpenRecordset ou un Rs.MoveNext dans une boucle entre les deux ...). Mais
cette semaine il y a eu quelques soirées un peu longues :)

Pas que pour moi apparemment : personne n'a relevé que j'ai tout écrit sur la
première ligne du fichier cible
(Lig = 1 au lieu de Lig = Lig + 1). Je dis ceci pour faire l'économie du
prochain message : "ça y est ça ne plante plus mais je n'ai qu'une ligne
d'écrite dans le fichier".

Dans Excel, Cells a pour premier argument le numéro de ligne, pour deuxième
argument le numéro de colonne (en tout cas pour la syntaxe avec deux
arguments numériques).

On notera les différences de notation entre la source et la cible : les
champs d'un jeu d'enregistrements sont numérotés à partir de zéro, alors que
les colonnes d'une feuille Excel sont numérotées à partir de 1, d'où Col + 1
en deuxième argument de Cells. Par ailleurs on fournit la ligne en premier
argument de Cells, mais en source pour s'adresser à la bonne ligne on
sélectionne l'enregistrement correspondant, c'est l'instruction Rs.MoveNext
qui joue ce rôle.

Si on oublie Rs.MoveNext on ne reprend pas la main sans interruption brutale
du programme, puisqu'on n'arrive jamais à Rs.EOF (fin du jeu
d'enregistrements). Si Access veut bien rendre la main avec les touches Ctrl
Pause c'est tant mieux, sinon c'est fin d'Access avec le gestionnaire des
tâches de Windows (un progrès par rapport à l'époque DOS où on redémarrait la
machine).


Dans le code ci-dessus j'ai pris soin de libérer la première ligne du fichier
Excel (Lig = 1 plutôt que 0 avant la boucle, incrémentation avant d'exploiter
les données), on peut donc y mettre les noms des champs en attendant d'y
mettre des intitulés plus explicites.

Entre le Wend et le Rs.Close :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next

J'ai mis le nom du champ pour simplifier, mais
Rs.Fields(Col).Properties("Description") devrait donner quelque chose de plus
parlant si on a pris soin de renseigner la propriété correspondante dans la
description de la table. Attention, si ce n'est pas le cas, cette syntaxe
retourne une erreur.

Il faut donc l'inclure dans une fonction :

Function DescriptionChamp(Fd As Field) As String
On Error Goto ErrDescriptionChamp
DescriptionChamp = Fd.Properties("Description")
Exit Function
ErrDescriptionChamp:
DescriptionChamp = ""
End Function

Ceci permettra de transférer les descriptions existantes comme ceci :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = DescriptionChamp(Rs.Fields(Col))
Next

En espérant que cette fois je n'ai pas oublié une instruction décisive.
Sinon je finirai bien par démarrer la machine avec les applications.


--
Francis

CINQUIÈME LOI DE YOUNG
Se tromper est humain, mais pour vraiment mettre le bordel, il faut y
ajouter un ordinateur.


Avatar
Francis
Bonjour Michel,
Désolé, j'ai un problème avec ton code car le fichier excel obtenu
n'est pas filtré du tout.
Voici comment je l'ai transposé dans mon appli:

Dim oRst As DAO.QueryDef 'Est-ce le bon type de Def???
Dim sSql As String
sSql = strfiltre
' Puis soit tu crées une requête
'Set oRst = CurrentDb.CreateQueryDef("MaRequete", sSql)
' ou tu modifies une requête existante
Set oRst = CurrentDb.QueryDefs("rqt journal des opérations")
oRst.SQL = sSql
' et enfin exportation du résultat de la requête vers excel
DoCmd.TransferSpreadsheet 1, 8, "rqt journal des opérations",
"C:Documents and settingsFrancisMes DocumentsAncreFichier.xls"

strfiltre est une variable qui évolue au fil des critères de sélection
et qui, à un certain moment, ressemble à ceci:
strfiltre = strfiltre & "(abs([solde])>=" & Me!MontantMini & ")" &
"and" & "(abs([solde])<=" & Me!MontantMaxi & ")" '& " or " &
"(-[solde]>=" & Me!MontantMini & ")" & "and" & "(-[solde]<=" &
Me!MontantMaxi & ")"
Cette variable marche au poil pour l'affichage et l'impression (c'est
Roger qui en a écrit le code).
Le problème vient que si je mets "rqt journal des opérations", j'ai
toujours la totalité de la base, quelle que soit la valeur de
strfiltre.
J'ai aussi tenté le coup en prenant l'option où je crée une requête
"MaRequete", et là je n'obtiens plus rien du tout (aucun fichier excel)
Qu'est que j'ai mal fait ou que dois-je faire en plus, stp ?
@+
Francis



Michel_D a formulé la demande :
Une fois que tu auras formalisé ton filtre multicritères cela te donnera
la condition de ta requête, ensuite :

sSql="Le_SQL_de_la_requête"
' Puis soit tu crée une requête
Set oRst=CurrentDb.CreateQueryDef("MaRequete",sSql)
' ou tu modifie une requête existante
Set oRst=CurrentDb.QueryDefs("MaRequete")
oRst.SQL=sSql
' et enfin exportation du résultat de la requête vers excel
DoCmd.TransferSpreadsheet 1,8,"MaRequete","C:ToncheminFichier.xls"



re,
Oui, c'est bien ça. Actuellement, j'ai la possibilité de visualiser ou
d'imprimer ce résultat, mais je voudrais aussi pouvoir l'exporter au format
excel pour traitements complémentaires. Je sais comment exporter une
requête dans sa forme initiale, mais pas après application d'une sélection
multicritères.
Ça ne doit pas être super compliqué, probablement, mais je ne sais pas
faire :/






--
Francis

RÈGLE DE FLUGG
Plus est urgent le motif pour lequel tu es dans la file d'attente,
plus sera lent l'employé du guichet.


Avatar
Francis
Bonjour Eric,

Merci beaucoup pour ton code: réussite 100% du premier coup.
Pour quelqu'un qui n'est pas "un spécialiste de l'Automation", on peut
difficilement imaginer ce qui aurait été mieux si tu l'avais été. :')
Merci encore, et bon dimanche,

Francis

Eric a présenté l'énoncé suivant :
re Bonsoir,

Je ne suis pas un spécialiste de l'automation alors ...
Essaie cette procédure sur clic d'un bouton de commande de ton formulaire qui
affiche tes données filtrées:

Private Sub Commande1_Click()
' Charger la référence Microsoft DAO Library 3.x
' Déclaration en late binding pour éviter les conflits de version
d'Excel
Dim xlApp As Object
Dim xlWbk As Object
Dim xlWks As Object
Dim Col As Integer
Dim Rs As DAO.Recordset

Set xlApp = CreateObject("Excel.Application")
Set xlWbk = xlApp.Workbooks.Add
Set xlWks = xlWbk.ActiveSheet
'Recupération du jeu d'enregistrements
Set Rs = Me.RecordsetClone
Rs.MoveFirst

'Ecriture du nom des champs sur la ligne 1 d'Excel
For Col = 0 To Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next Col
' Copie du jeu à partir de A2 dans Excel
xlWks.Cells(2, 1).CopyFromRecordset Rs
Rs.Close

'Sauvegarde du classeur
xlApp.Workbooks(1).SaveAs "c:test.xls"
xlApp.Quit

Set Rs = Nothing
Set xlWks = Nothing
Set xlWbk = Nothing
Set xlApp = Nothing
End Sub



Bonsoir Eric,
J'ai appliqué ta proposition, mais le compilateur n'accepte pas la ligne de
code:
xlApp.CurrentWorkbook.SaveAs "NomDuClasseur"
dans laquelle j'ai remplacé NomDuClasseur" par "C:Test"
Ça faisait la même chose avec Next après Rs.Movenext.
Dans les deux cas, j'ai aussi une feuille excel qui s'ouvre, mais rien ne
se passe.
Francis





--
Francis

PRINCIPE DE RUBY
La probabilité de rencontrer une personne de ta connaissance augmente
quand tu es avec quelqu'un avec qui tu ne veux pas être vu.


Avatar
Francis
Bonjour "Gloops",

Un grand merci pour ta réponse super didactique.
Je l'ai mise en application, mais ça bloque car le debugger me dit
qu'il y a un pb avec la ligne de code suivante:
xlApp.CurrentWorkbook.SaveAs "C:Documents and settingsFrancisMes
documentsAncre"
Si, après Ancre, je mets un nom de fichier.xls, ça fait pareil.
J'ai une feuille excel qui s'ouvre, mais rien ne se passe, et dans
Access j'ai un message: "erreur d'exécution '438'": propriété ou
méthode non gérée par cet objet".
Un avis sur ce que je dois faire en plus? Une référence à activer???
Bon dimanche et @+
Francis

Gloops avait prétendu :
Francis a écrit, le 19/04/2008 21:21 :
Bonsoir Michel,
C'est bien ça, il manquait un Next après Rs.MoveNext.


Objection votre honneur.

Si on veut que le code ait une petite chance de fonctionner, c'est AVANT le
Rs.MoveNext qu'il faut placer le Next, que j'ai effectivement oublié.

Les deux structures de code en jeu sont :

Boucle :

For N = 1 to Max
'traitement sur boucle
Next


Traitement sur jeu d'enregistrements :

Set Rs = DB.OpenRecordset(...)
While Not Rs.EOF 'tant qu'il reste des données à traiter
'traitement d'un enregistrement

Rs.MoveNext 'passage à l'enregistrement suivant
Wend 'fermeture de la boucle
Rs.Close 'fermeture du jeu d'enregistrements
Set Rs = Nothing 'libération de la variable

En réimbriquant les deux
(le traitement d'un enregistrement est constitué d'une incrémentation de Lig
suivie d'une boucle sur les champs) :

Lig = 1
Set Rs = CurrentDb().QueryDefs("MaRequête").OpenRecordset()
While Not Rs.EOF
'===== Début de traitement de l'enregistrement
Lig = Lig + 1
For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(Lig, Col + 1) = Rs.Fields(Col)
Next
'===== Fin de traitement de l'enregistrement
Rs.MoveNext 'passage à l'enregistrement suivant
Wend
Rs.Close
Set Rs = Nothing

L'indentation a bien pour but d'aider à se rendre compte qu'il manque quelque
chose (un Wend après un While, un Next après un For, un Rs.Close après un
OpenRecordset ou un Rs.MoveNext dans une boucle entre les deux ...). Mais
cette semaine il y a eu quelques soirées un peu longues :)

Pas que pour moi apparemment : personne n'a relevé que j'ai tout écrit sur la
première ligne du fichier cible
(Lig = 1 au lieu de Lig = Lig + 1). Je dis ceci pour faire l'économie du
prochain message : "ça y est ça ne plante plus mais je n'ai qu'une ligne
d'écrite dans le fichier".

Dans Excel, Cells a pour premier argument le numéro de ligne, pour deuxième
argument le numéro de colonne (en tout cas pour la syntaxe avec deux
arguments numériques).

On notera les différences de notation entre la source et la cible : les
champs d'un jeu d'enregistrements sont numérotés à partir de zéro, alors que
les colonnes d'une feuille Excel sont numérotées à partir de 1, d'où Col + 1
en deuxième argument de Cells. Par ailleurs on fournit la ligne en premier
argument de Cells, mais en source pour s'adresser à la bonne ligne on
sélectionne l'enregistrement correspondant, c'est l'instruction Rs.MoveNext
qui joue ce rôle.

Si on oublie Rs.MoveNext on ne reprend pas la main sans interruption brutale
du programme, puisqu'on n'arrive jamais à Rs.EOF (fin du jeu
d'enregistrements). Si Access veut bien rendre la main avec les touches Ctrl
Pause c'est tant mieux, sinon c'est fin d'Access avec le gestionnaire des
tâches de Windows (un progrès par rapport à l'époque DOS où on redémarrait la
machine).


Dans le code ci-dessus j'ai pris soin de libérer la première ligne du fichier
Excel (Lig = 1 plutôt que 0 avant la boucle, incrémentation avant d'exploiter
les données), on peut donc y mettre les noms des champs en attendant d'y
mettre des intitulés plus explicites.

Entre le Wend et le Rs.Close :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next

J'ai mis le nom du champ pour simplifier, mais
Rs.Fields(Col).Properties("Description") devrait donner quelque chose de plus
parlant si on a pris soin de renseigner la propriété correspondante dans la
description de la table. Attention, si ce n'est pas le cas, cette syntaxe
retourne une erreur.

Il faut donc l'inclure dans une fonction :

Function DescriptionChamp(Fd As Field) As String
On Error Goto ErrDescriptionChamp
DescriptionChamp = Fd.Properties("Description")
Exit Function
ErrDescriptionChamp:
DescriptionChamp = ""
End Function

Ceci permettra de transférer les descriptions existantes comme ceci :

For Col = 0 to Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = DescriptionChamp(Rs.Fields(Col))
Next

En espérant que cette fois je n'ai pas oublié une instruction décisive.
Sinon je finirai bien par démarrer la machine avec les applications.


--
Francis

LOI DE LA GRAVITE SÉLECTIVE
En tout point de la surface du globe, toute biscotte tombera côté
beurre.


Avatar
Eric
Bonjour Francis,

Merci pour le retour et bonne continuation.

Bonjour Eric,

Merci beaucoup pour ton code: réussite 100% du premier coup.
Pour quelqu'un qui n'est pas "un spécialiste de l'Automation", on peut
difficilement imaginer ce qui aurait été mieux si tu l'avais été. :')
Merci encore, et bon dimanche,

Francis

Eric a présenté l'énoncé suivant :
re Bonsoir,

Je ne suis pas un spécialiste de l'automation alors ...
Essaie cette procédure sur clic d'un bouton de commande de ton
formulaire qui affiche tes données filtrées:

Private Sub Commande1_Click()
' Charger la référence Microsoft DAO Library 3.x
' Déclaration en late binding pour éviter les conflits de version
d'Excel
Dim xlApp As Object
Dim xlWbk As Object
Dim xlWks As Object
Dim Col As Integer
Dim Rs As DAO.Recordset

Set xlApp = CreateObject("Excel.Application")
Set xlWbk = xlApp.Workbooks.Add
Set xlWks = xlWbk.ActiveSheet
'Recupération du jeu d'enregistrements
Set Rs = Me.RecordsetClone
Rs.MoveFirst

'Ecriture du nom des champs sur la ligne 1 d'Excel
For Col = 0 To Rs.Fields.Count - 1
xlWks.Cells(1, Col + 1) = Rs.Fields(Col).Name
Next Col
' Copie du jeu à partir de A2 dans Excel
xlWks.Cells(2, 1).CopyFromRecordset Rs
Rs.Close

'Sauvegarde du classeur
xlApp.Workbooks(1).SaveAs "c:test.xls"
xlApp.Quit

Set Rs = Nothing
Set xlWks = Nothing
Set xlWbk = Nothing
Set xlApp = Nothing
End Sub



Bonsoir Eric,
J'ai appliqué ta proposition, mais le compilateur n'accepte pas la
ligne de code:
xlApp.CurrentWorkbook.SaveAs "NomDuClasseur"
dans laquelle j'ai remplacé NomDuClasseur" par "C:Test"
Ça faisait la même chose avec Next après Rs.Movenext.
Dans les deux cas, j'ai aussi une feuille excel qui s'ouvre, mais
rien ne se passe.
Francis







--
A+
Eric
http://www.mpfa.info/
Archives : http://groups.google.fr/group/microsoft.public.fr.access?hl=fr



1 2 3