Aller au contenu

Lire et écrire des feuilles Excel


(gile)

Messages recommandés

Salut,

 

 

Un petit cadeau de fin d'année pour les LISPeurs.

 

Il s'agit de deux fonctions LISP définies en .NET.

 

Elles sont un peu basiques mais devraient permettre de lire ou d'écrire une feuille Excel assez facilement.

 

 

(gc-XlRead filename [sheet])

 

Lit une feuille Excel et retourne les données sous forme d'une liste de sous-listes dont les éléments sont de chaînes.

 

Arguments

 

filename : le nom complet du fichier (chemin compris)

 

sheet : [optionnel] le nom de la feuille (lit la feuille active si sheet est omis, retourne nil si sheet n'existe pas)

 

 

(gc-XlWrite filename sheet datas)

 

Inscrit des données dans un fichier Excel, retourne T ou nil

 

Arguments

 

filename : le nom complet du fichier.

 

sheet : le nom de la feuille ("" ou nil pour la première feuille) si la feuille n'existe pas elle est créée

 

datas : liste de sous listes de chaînes et/ou de nombres.

 

 

NOTA: Si le fichier existe déjà et que la feuille spécifiée contient des données elles seront écrasées. C'est au code LISP de le contrôler. Par contre, on peut écrire dans un fichier existant en spécifiant soit une feuille vide soit une feuille qui n'existe pas et sera automatiquement créée.

 

 

Exemple :

 

(gc-XlWrite "F:\\XlTest.xls" "boo" '(("ceci" "est" "un" "test") (1 2 3 4))) retourne T

 

(gc-XlRead "F:\\XlTest.xls" "boo") retourne (("ceci" "est" "un" "test") ("1" "2" "3" "4"))

 

 

Télécharger ExcelLISP.zip

 

Le code source ici

 

Les liens ci-dessus sont rompus, gc-XlRead et gc-XlWrite font parti (avec d'autres fonctions LISP définies en .NET) de LispExtension sur cette page.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile,

 

Si j'ai bien compris tes deux fonctions, on peut lire et écrire des feuilles dans un fichier Excel et tes deux fonctions peuvent être appelés dans un lisp pur par exemple comme les fonctions write-line ou read-line à part que l'on peut paramétrer plus d'options avec tes deux fonctions.

 

J'aimerais essayé la fonction gc-XlRead pour insérer des blocs dont les coordonnées sont dans un tableau Excel, doit-on spécifier le nom des colonnes et des lignes à prendre en compte pour arrêter le traitement ou non et le classeur Excel peut il être ouvert ou non ?

 

Si tu aurais un petit exemple d'application en lisp, ca serait idéal bien sur si tu as 2 min, sinon c'est pas grave.

Merci encore de ton aide.

John.

 

[Edité le 30/12/2009 par chris_mtp]

Lien vers le commentaire
Partager sur d’autres sites

Les fonction LISP gc-XlRead et gc-XlWrite sont assez sommaires.

 

gc-XlRead lit toute la plage utilisée depuis la cellule A1 et retourne la plage sous forme de liste dont chaque élément est une liste contenant les valeurs des cellules d'une rangée, les valeurs sont de type chaîne.

Les arguments sont :

- le chemin complet du Fichier,

- optionnellement le nom de la feuille (si ce dernier est omis, c'est la première feuille qui est lue).

 

gc-XlWrite écrit dans une feuille Excel à partir de la cellule A1 et retourne T si l'opération s'est bien passée, nil sinon.

Les arguments sont :

- le chemin complet du Fichier,

- le nom de la feuille dans le fichier, si l'argument est "" ou nil gc-xlWrite écrit dans la première feuille, si le nom de la feuille n'existe pas, elle est créee, si la feuille contient des données, elle sont écrasées

- une liste de sous-liste où chaque sous liste contient les données à écrire dans une rangée (les données peuvent être de type chaîne ou nombre.

 

Après avoir chargé la DLL dans AutoCAD avec NETLOAD, on peut utiliser ces 2 nouvelles fonctions LISP dans toute la session courante.

 

Ensuite tu peux faire ;

(if (setq filename (getfiled "Choisir un fichier Excel" "" "xls;xlsx" 0))
  (setq lst (gc-XlRead filename))
)

 

Et tu verras bien le format de ce que retourne gc-XlRead.

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Salut gile sa a l'air d'etre une bonne idée mais a paremetn la pieces jointes n'existe plus sur acadlabs

DAO: AutoCAD(2D & 3D), Covadis

CAO: 3D's MAX, Rhinoceros 3D, REVIT

GeoModeliSation: AutoCAD MEP, RhinoTerrain

Rendu: Vray for Rhino, Keyshot, Lumion

Programmation: Grasshopper, Dynamo, VisualStudio

 

C.V.

Profil LinkedIn

Book

Site web

 

http://nsa37.casimages.com/img/2016/09/26/160926023334168603.jpg

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Tu peux télécharger le fichier ZIP directement depuis le lien du premier message ou depuis AcadLabs.

 

Il contient un fichier ExcelLISP.dll qui, lorsqu'il est chargé dans une session AutoCAD (avec la commande NETLOAD ou automatiquement) ajoute deux nouvelles fonctions LISP utilisables dans tes routines LISP.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 6 mois après...

Bonjour Gile,

 

Je suis en train d'utiliser les deux fonctions de ExcelLisp mais j'ai un gros problème avec le choix de la feuille à sélectionner dans un classeur Excel.

J'ai un fichier Excel avec plusieurs feuilles qui contiennent elle-même plusieurs points.

J'aimerais en indiquant le chemin de mon fichier excel par getfiled avoir la liste de toutes les feuilles présentes dans ce fichier excel et ensuite lancer la lecture de la feuille sélectionné avec gc-XlRead mais il me manque des connaissances en Vlisp pour obtenir cette liste.

Je ne pense qu'en pur AutoLisp cela soit possible.

Je fais un traitement sur l'insertion de blocs depuis Excel vers Autocad avec des attributs un peu particuliers, d'où ma demande sur une fonction si possible.

 

Merci par avance de ton aide.

John

 

[Edité le 1/8/2010 par chris_mtp]

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je l'ai déjà dit et je le répète, à mon avis, l'utilisation de fichiers CSV plutôt que de fichiers XLS(X) permet un gestion par programmation LISP (ou autre) :

- beaucoup plus facile : lecture/écriture dans un fichier ascii avec les fonctions AutoLISP read-line et write-line

- beaucoup plus rapide : l'ouverture d'un fichier ascii avec la fonction open est quasi instantanée tandis que l'ouverture d'un fichier xls(x) nécessite l'ouverture d'un processus Excel (démarrage de l'application)

- plus sûre : fermer le fichier ouvert avec close est facile à gérer tant en fonctionnement normal que dans la gestion des erreurs, fermer un fichier xls et terminer le processus Excel pour libérer les ressources l'est beaucoup moins (difficile d'être certain de terminer le bon processus si plusieurs sont ouverts).

 

Ceci dit,concernant ta demande,c'est, à mon avis, une fausse bonne idée que d'ouvrir un fichier Excel avec Visual LISP pour récupérer la liste des feuilles de ce fichier, de fermer ce fichier (et de terminer le processus), puis de le rouvrir avec gc-XlRead (ou gc-XlWrite) pour le lire (ou le modifier), étant donné que ce sont l'ouverture et la fermeture d'Excel qui sont les plus dispendieuses en temps.

 

Le plus cohérent serait donc de tout écrire dans le même langage pour pouvoir ne démarrer qu'un processus Excel dans lequel il serait possible choisir la feuille et de la lire.

 

Pour lire écrire dans une feuille Excel tu peux t'inspirer des routines de GetExcel sur cette page (réponse 7). Tu verras comment on démarre le processus (GetExcel et OpenExcel) et comment on le termine (GetExcel et CloseExcel).

 

 

;; On démarre un processus avec la fonction vlax-create-object (ou vlax-get-or-create-object) 
(setq ExcelApp (vlax-create-object "Excel.Application"))

;; On ouvre le fichier
(vlax-invoke-method
 (vlax-get-property ExcelApp 'WorkBooks)
 'Open
 NomduFichier
)

;; On récupère la liste des feuilles
(vlax-for sheet	(vlax-get-property ExcelApp 'Sheets)
 (setq sheetList (cons (vlax-get-property Worksheet 'Name) sheetList))
)

 

Une fois le nom de la feuille à traiter récupérée (dans la variable sheetName par exemple), on active cette feuille :

;; On récupère la feuille
(setq workSheet (vlax-get-property sheetCol 'Item sheetName ))

;; On active la feuille
(vlax-invoke-method workSheet 'Activate)

 

Tu peux ensuite t'inspirer de GetExcel pour récupérer les données de cette feuille.

 

Dans tous les cas, que le processus ait abouti ou qu'une erreur l'ait interrompu (Echap est considéré comme une erreur) il faut absolument fermer le fichier, terminer le processus Excel, et libérer les ressources.

;; Fermer le fichier
(vlax-invoke-method
 (vlax-get-property ExcelApp 'ActiveWorkbook)
 'Close
 :vlax-False
)

;; Quitter l'application
(vlax-invoke-method ExcelApp 'Quit)

;; Terminer le processus
(vlax-release-object ExcelApp)

;; Libérer les ressources
(gc)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Bonjour Gile,

 

J'ai un problème pour récupérer la liste des feuilles d'un fichier Excel.

Je récupère le nom du Fichier à traiter avec

 

 (setq fni (getfiled "Sélectionner le fichier Excel"  ""  "xls;xlsx;*" 0))

 

Ensuite, je fais les deux premières commandes comme décrit

 

 ;; On démarre un processus avec la fonction vlax-create-object (ou vlax-get-or-create-object) 

(setq ExcelApp (vlax-create-object "Excel.Application"))



;; On ouvre le fichier
(setq filo
(vlax-invoke-method

 (vlax-get-property ExcelApp 'WorkBooks)

 'Open

fni

)
)

 

Et ensuite je lance

 

 ;; On récupère la liste des feuilles

(vlax-for sheet	(vlax-get-property ExcelApp 'Sheets)

 (setq sheetList (cons (vlax-get-property filo 'Name) sheetList))

)

 

Mais il me retourne une liste avec que le nom du fichier d'origine et pas le nom des feuilles de ce même fichier.

Il ne me manque plus que çà. J'ai tout trouvé pour lire et écrire dans Excel. Pour sortir des informations d'Excel et ensuite les traiter dans Autocad mais là, sérieux je bloque

 

Merci par avance de ton aide.

John

 

Lien vers le commentaire
Partager sur d’autres sites

Salut

 

(vlax-for sheet (vlax-get filo 'sheets)
 (princ (strcat "\n" (vlax-get sheet 'name)))
)

 

@+

 

ps : avec un (setq ExcelApp (vlax-create-object "Excel.Application")), si ton fichier est déjà ouvert, tu auras une erreur

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Merci Patrick pour ta réponse.

J'ai pu m'en sortir et créer la liste de noms des feuilles d'un fichier Excel.

Avec les fonctions de Gile, GetExcel, je peux sortir sous forme de liste les données qui m'intéresse mais je suis confronté à un dernier problème.

 

Il faudrait que je trouve la référence d'une cellule de la première colonne.

Je m'explique, dans mon fichier excel, j'ai plusieurs colonnes avec les mêmes entêtes de colonnes.

La première colonne correspond au numéro de point.

Je n'arrive pas à créer une fonction qui me permettrait en rentrant le numéro de point (par exemple "38" ou "P36") de trouver la référence de la cellule (par exemple A2 ou A325) et ainsi pouvoir par exemple ne créer la liste avec GetExcel que des données comprises entre les lignes définies (par exemple de A2 et A325).

 

La recherche dans une feuille excel définie ne s'effectuerait que dans la première colonne A et dès que la fonction trouve la valeur entrée, elle me retourne la référence de la cellule.

 

Je suis bloqué et il ne me manque que çà pour terminer mon lisp.

Si vous avez 2min pour vous pencher sur le sujet, ce serait bien sinon si c'est trop compliqué, c'est pas grave. Merci par avance de votre aide.

 

John

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

J'avoue ne pas bien comprendre ce que tu utilises pour lire la feuille Excel : les routines de GetExcel (qui ne sont pas de moi, exceptées quelques unes, mais de Terry Miller) ou la fonction LISP gc-XlRead (definie en .NET) donnée dans ce sujet ?

 

 

Je n'arrive pas à créer une fonction qui me permettrait en rentrant le numéro de point (par exemple "38" ou "P36") de trouver la référence de la cellule (par exemple A2 ou A325) et ainsi pouvoir par exemple ne créer la liste avec GetExcel que des données comprises entre les lignes définies (par exemple de A2 et A325).

Dans tous les cas (GetExcel ou gc-XlRead) une liste de sous-listes de chaînes est retournée (une liste par rangée, une chaîne par donnée).

 

GetExcel permet de limiter la liste retournée (dans la variable globale *ExcelData@) de la cellule A1 à une cellule spécifiée). gc-XlRead retourne la feuille entière. À moins d'avoir à faire une feuille vraiment énorme, le plus dispendieux en temps est l'ouverture d'Excel.

 

La liste retournée se traite ensuite comme n'importe quelle liste en LISP et si tu veux retrouver une ligne depuis la valeur de la première colonne (la première valeur de la sous liste), il suffit d'utiliser la fonction assoc :

(assoc "38" *ExcelData@)

ou

(assoc "P36" LaListe)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile,

 

Merci de te réponse.

Je t'explique ma démarche.

Je veux importer des points dans Autocad en ayant le fichier Excel Ouvert pour repréer le nom des feuilles à traiter. Par conséquent, je fais ma liste de noms des feuilles avec les commandes que tu m'as indiqué ci-dessus, je ferme ensuite la liason et libère les ressources de excel.

J'ai suivi l'exemple de Patrick avec un

 vlax-get-or-create-object 

car mon fichier excel est ouvert.

Ensuite, je récupére les données d'Excel avec gc-XlRead plus rapide à mon goût.

Je sais que ce n'est pas tu m'as conseillé mais je n'arrive pas à utiliser GetExcel ou encore GetCell.

Ensuite, je tri la liste récupérer avec gc-XlRead pour pouvoir traiter que certains points.

Cette méthode marche très bien et est très rapide.

Seulement, ce n'est pas ce que tu m'as conseillé. Je sais.

 

J'aurais aimé tout faire en Lisp et ne pas utiliser gc-XlRead mais je ne sais pas comment récupérer la référence d'une cellule en ne rentrant que le numéro de point de la première colonne d'une feuille comme décrit dans mon message précedent.

 

Sinon, oui je pourrais faire tout en Lisp mais là je suis bloqué.

J'espère n'avoir pas trop été confus et être compréhensible.

Je précise, j'ai fini mon lisp, j'ai pu faire ce que j'ai voulu avec la fonction gc-XlRead mais ce n'est pas très propre comme démarche.

Merci encore de ton aide.

John.

 

 

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile

 

J'ai une autre question

Avec la fonction gc-XlRead, lorsque la fonction lit des cellules contenant des nombres, il arrondit les résultats à 4 chiffres après la virgule ou bien il retourne la totalité des décimales contenues dans les cellules. Par conséquent, il est préférable dans mon cas d'utiliser les fonctions de AdoExcelLisp avec gc-XlDbRead. Mais en utilisant gc-XlDbRead j'ai des problèmes avec mon lisp

Du coup, serait il possible de modifier la fonction gc-XlRead avec l'extraction de toutes les décimales ?

Merci par avance de ta réponse.

John.[Edité le 14/8/2010 par chris_mtp]

 

[Edité le 14/8/2010 par chris_mtp]

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je ne comprends pas ce que tu dis, gc-XlRead n'arrondit pas pas les nombres.

 

Si tu veux tout faire en LISP, tu as deux solution :

 

- apprendre Visual LISP pour pouvoir utiliser les composants COM Excel qui sont les mêmes qu'en VBA Excel mais utilisés avec la syntaxe LISP (GetExecl peut servir d'exemple pour les principales).

 

- faire ce que je recommande : enregistrer tes feuilles Excel au format CSV et les lire simplement en LISP...

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile

 

Si j'utilise gc-XlRead, j'ai en retour une liste du type

 

"1" "494687.6423" "206640.4516" "199.5672065" 

 

alors qu'avec gc-XlDbRead, j'ai en retour une liste du type

 

"1" "494687.642348306" "206640.451570744" "199.567206472286" 

 

d'où mon incompréhension. Si tu as une solution, c'est bien sinon c'est pas grave.

 

La fonction gc-XlRead marche très bien, enregistrer mes feuilles en CSV et les traiter seraient trop long et utiliser GetExcel pose des problèmes de syntaxe.

Je suis arrivé à faire ce que je voulais avec mon lisp.

Il y a juste cette petite erreur que je ne comprends pas.

Si tu as 2min, merci sinon c'est pas grave.

 

John.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Effectivement, gc-XlRead retourne les nombres avec le nombre de décimales tels qu'affiché dans Excel. C'est dû à l'utilisation du presse-papier Windows qui m'avait été recommandé par Alexander Rivilis sur TheSwamp pour optimiser le code.

 

Je suis donc revenu à ma première méthode pour la DLL ci-dessous :

ExcelLisp.zip

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Merci Gile.

Là ca marche nickel avec toutes les décimales.

Un petit bémol cependant, si dans la feuille Excel, j'ai une colonne Date, la fonction me la transforme en nombre mais je vais trouvé une solution pour contourner ce problème.

Merci encore de ton aide et Bravo.

 

John.

Lien vers le commentaire
Partager sur d’autres sites

Salut

 

Juste une question.

Pourquoi ne pas lire la valeur d'une cellule alors que tu as déjà tout programmé ?

Ce n'est pas pour dénigrer les fonctions que (gile) a donné, bien au contraire car elles sont oh combien utiles pour ceux qui ne savent pas programmer Excel, mais au point ou tu en es, cela fait doublon

 

(setq feuille (vlax-get-property (vlax-get filo 'sheets) 'item 1)) ; pointer sur la 1er Feuille
(setq cellule (vlax-get-property feuille 'range "B5")) ; Lecture de la cellule B5
(vlax-get cellule 'value2) ; Valeur de la cellule

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Patrick,

 

Merci pour ta réponse mais j'en reviens à mon problème décrit en réponse 12.

Si j'arrive à faire une fonction qui me trouve la référence d'un numéro de point dans la colonne A d'uen feuille Excel, alors que je connaitrais la dernière cellule d'excel que doit lire GetExcel et je pourrais tout faire en lisp.

 

Actuellement, je fais tous lire par la fontion de Gile et je tri ensuite ma liste sous forme de numéro de points.

Le but serait par exemple de trouver que le numéro P35 se trouve à la ligne A[surligneur] 3256[/surligneur] et donc de lire la feuille Excel avec Getexcel du type

 

(GetExcel "C:\\Dossier\\Fichier.xls" "Feuil1" "K [surligneur] 3256[/surligneur] ") 

.

 

Mon problème vient de trouver le numéro de la ligne correspondant au numéro de point de traiter.

Du point 1 au P35 par exemple.

Donc dans mon exemple de la cellule A1 à la ligne K [surligneur]3256 [/surligneur]

 

En espérant avoir été clair, merci par avance de ton aide.

John.

Lien vers le commentaire
Partager sur d’autres sites

Pour parcourir toutes les lignes de la feuille

(vlax-get (vlax-get (vlax-get feuille 'usedrange) 'rows) 'count)

 

Et toutes les colonnes

(vlax-get (vlax-get (vlax-get feuille 'usedrange) 'columns) 'count)

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

J'y suis arrivé en écoutant vos conseils à lire une feuille Excel tout en lisp mais sérieux c'est trop long et trop complexe. Et là ne j'ai pas vraiment le temps en ce moment.

Et par contre, j'ai les mêmes problèmes pour les arrondi.

En lisp, j'ai un retour sur les coordonnées à 4 décimales alors que dans Excel, il y a en plus, 9 voir 10.

 

Merci Patrick mais je vais continuer comme çà avec l'ancienne méthode, ca marche bien.

Gile, je te demanderai une seule petite modification de la DLL ExcelLisp,

Si on peut lire la dernière colonne d'une ligne contenant une valeur comme un texte et non un nombre ca m'aiderait sérieusement.

 

Je m'explique, la dernière colonne de toutes mes feuilles est une date et ExcelLisp me retourne un nombre de cette même dernière colonne. Ce nombre correspond au nombre de jours écoulés de la date en question jusqu'au 1er Janvier 1990. Du coup, je ne peux pas retrouver ma date exacte lors du traitement de mes données.

 

Si cette dernière petite modification est possible, merci par avance Gile.

John.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile

 

Je vais finalement utiliser gc-XlDbRead plus fiable plus rapide et plus sûr.

Par contre, quand dans ma prenière colonne j'ai un numéro du type "O1" ou "P36" par exemple, la fonction me retourne un "" comme premier élements de ma sous liste alors que quand c'est un numéro simple du type "582" ou "693", il me le retourne correctement.

 

Je ne sais pas si tu peux y faire quelque chose en modifiant la DLL ou quoi.

 

Avec gc-XlRead, j'ai

 

 ("P356" "465954.8293" "753614.70005" "22.00337" "738" "" "" "" "" "" "40378")

 

Avec gc-XlDbRead, j'ai

 ("" "465954.8293" "753614.70005" "22.00337" "738" "" "" "" "" "" "19/07/2010 00:00:00")

 

La date avec gc-XlDbRead est formaté correctement, toutes les décimales sont retournés mais pas le numéro du point, Toujours à mon avis le presse papier non ?

Si tu as 2min, merci.

John

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité