[C#] Créer un fichier Excel

Créer un fichier Excel [C#] - C#/.NET managed - Programmation

Marsh Posté le 28-04-2006 à 10:35:22    

Salut,
 
J'arrive pas à trouver un moyen pour créer un document Excel à partir d'une application écrite en C#.
 
J'ai toujours la solution du csv, ou du fichier html renommé en xls, mais je préfèrerais faire un truc simplement.
 
Sauf que j'ai plusieurs soucis :
- Je ne trouve de la doc que pour faire de l'automation avec Office 10 ou 11 (il y a des offices 97 et 2000 -Office 7 & 8- encore là où l'appli va être déloyée)
- Moi j'ai la 2003 (11), sauf qu'il me manque les "PIA" d'Excel. Et impossible de trouver où les télécharger (y'a un lien dans la MSDN, mais ça tombe sur une liste de dwl qui n'ont rien à voir)
 
Vous avez une idée ?
Reste la solution de déployer la solution avec un VBS, qui récupère les données d'un fichier XML, et qui bidouille dans Excel comme un grand -ça y'a pas de problème avec WSH- mais ça me lourde les bidouillages, après je comprends plus rien à ce que j'ai fait :o

Reply

Marsh Posté le 28-04-2006 à 10:35:22   

Reply

Marsh Posté le 28-04-2006 à 10:36:42    

Tu est en .NET? Sinon j'ai trouve un composant appele CarolsAg qui est pas mal du tout!

Reply

Marsh Posté le 28-04-2006 à 10:48:11    

Yes, je suis en .NET

Reply

Marsh Posté le 28-04-2006 à 11:52:27    

Je trouve rien sur le net à propos de CarolsAg
 
La solution du VBS :

Code :
  1. Option Explicit
  2. Sub test()
  3.     Dim xls
  4.     Dim wkb
  5.     Dim sht
  6.    
  7.     Set xls = CreateObject("Excel.Application" )
  8.     Set wkb = xls.Workbooks.Add()
  9.     Set sht = wkb.Sheets.Add()
  10.    
  11.     sht.Cells(1, 1).Value = "test"
  12.     sht.Cells(1, 2).Value = "1"
  13.     sht.Cells(1, 3).Value = "2"
  14.     sht.Cells(1, 4).Value = "=R1C2+R1C3"
  15.    
  16.     xls.Visible = True
  17. End Sub
  18. Call test()


 
Pkoi on peut pas faire simplement aussi en C# ? :cry:
Je sens que je vais m'amuser encore... Pis à débuger, ça va encore être la misère tiens...

Reply

Marsh Posté le 28-04-2006 à 12:29:23    

Bon ben...
 

Code :
  1. private void button2_Click(object sender, EventArgs e)
  2.         {
  3.             Object foo = null;
  4.             IWshRuntimeLibrary.WshShellClass shell = new IWshRuntimeLibrary.WshShellClass();
  5.             shell.Run(@"c:\excel.vbs", ref foo, ref foo);
  6.         }


 
Avec le fichier VBS qui recherche les donnés dans un fichier XML qui va bien... Mon dieu que c'est crade :o Mais au moins ça marchera quelque soit la version d'Excel...

Reply

Marsh Posté le 28-04-2006 à 12:55:54    

pour Carlos AG il s'agit de produire des fichiers EXCEL au format XML. Ces fichiers ne sont lisibles qu'avec EXCEL 2003 puisque ce format est apparu avec Microsoft Office 2003.
L'avantage d'une telle solution de reporting est qu'il ne fait pas avoir microsoft Excel sur la machine pour produire les XML compréhensible par EXCEL.  
CarlosAg à produit une lib permettant de générer facilement un fichier au format XML.  
 
plus d'infos ici sur ce format:
http://www.labo-dotnet.com/Article [...] /1547.aspx

Reply

Marsh Posté le 28-04-2006 à 13:39:36    

on peut pas dire que tu ai cherché beaucoup alors pcq le premier lien sur google c'est celui la!  
http://www.carlosag.net/Tools/Exce [...] fault.aspx

Reply

Marsh Posté le 28-04-2006 à 13:44:29    

en fait ton fichier peut avoir l'extention xls avec ca aussi mais il sera effectivement en xml et donc lisible sous Excel 2003

Reply

Marsh Posté le 28-04-2006 à 15:14:30    

Hmmm, Excel sous .NET ça pose pas de problème, si ?
 

Code :
  1. ' J'ouvre
  2. m_oExcel = New Excel.Application
  3. ' Je mets une valeur
  4. mySheet.Range(maCellule).Value = maValeure
  5. ' Je récupère une valeur
  6. Dim objResult As Object = maFeuille.Range(maCellule).Value


 
Ca reste l'appel aux objets classiques en C.
Excel.Application, puis le WorkBook, puis les Worksheets, ...


---------------
H. - 48h en fiat et j'ai déjà perdu la maitrise de mon argent
Reply

Marsh Posté le 28-04-2006 à 15:29:56    

le problème avec ole automation c'est que si ça plante, c'est un plantage massif... alors qu'avec la lib, c'est plus performant et ça ne plante pas puisque c'est que de la construction d'xml

Reply

Marsh Posté le 28-04-2006 à 15:29:56   

Reply

Marsh Posté le 28-04-2006 à 15:37:55    

de plus l'ole est souvent fort lent...

Reply

Marsh Posté le 28-04-2006 à 15:42:35    

moi23372 a écrit :

pour Carlos AG il s'agit de produire des fichiers EXCEL au format XML. Ces fichiers ne sont lisibles qu'avec EXCEL 2003 puisque ce format est apparu avec Microsoft Office 2003.
L'avantage d'une telle solution de reporting est qu'il ne fait pas avoir microsoft Excel sur la machine pour produire les XML compréhensible par EXCEL.  
CarlosAg à produit une lib permettant de générer facilement un fichier au format XML.  
 
plus d'infos ici sur ce format:
http://www.labo-dotnet.com/Article [...] /1547.aspx


ouais, ok, donc ça m'intéresse pas ;)
 
je sais écrire ces fichiers à la main, donc passer par un objet ne me sert à rien. et surtout, faut que Excel 97 puisse les relire... :/

Reply

Marsh Posté le 28-04-2006 à 15:44:35    

Xas a écrit :

Hmmm, Excel sous .NET ça pose pas de problème, si ?
 

Code :
  1. ' J'ouvre
  2. m_oExcel = New Excel.Application
  3. ' Je mets une valeur
  4. mySheet.Range(maCellule).Value = maValeure
  5. ' Je récupère une valeur
  6. Dim objResult As Object = maFeuille.Range(maCellule).Value


 
Ca reste l'appel aux objets classiques en C.
Excel.Application, puis le WorkBook, puis les Worksheets, ...


ouais, sauf que "Excel.Application", pas moyen de trouver la référence à mettre. J'ai essayé les libs .NET (Office.Tools) et les objets COM (Excel 5.0 et Excel 11.0 -me demandez pas pkoi il y a des bouts de Excel 5.0 sur mon 2003 Server :o-)
Du coup, je ne peux rien faire. En plus, il me gueule dessus parcequ'il manque une référence "Microsoft.Office.Interop", sauf que je n'ai pas cette référence... Don't know why.
 
Et sinon, ça revient au même que mon VBS, sauf qu'avec "CreateObject", l'intérêt, c'est que je ne suis pas les poings liés avec la version référencée dans mon code : il prends la version de l'objet qui se trouve sur le PC de l'utilisateur. Ca m'évite de déployer 25 versions différentes de mon EXE (et d'installer 25 versions différentes d'Office sur mon PC...)


Message édité par Arjuna le 28-04-2006 à 15:47:03
Reply

Marsh Posté le 28-04-2006 à 15:45:30    

moi23372 a écrit :

le problème avec ole automation c'est que si ça plante, c'est un plantage massif... alors qu'avec la lib, c'est plus performant et ça ne plante pas puisque c'est que de la construction d'xml


Oui, mais relis mon premier post : XML = interdit. Je suis le seul dans toute la boîte à avoir Office 2003.
Sinon, j'aurais même pas posé la question : j'aurai utilisé le format XML d'entrée de jeu, c'est un vrai bonheur à utiliser, d'autant qu'on peut y inclure des macro autrement que sous forme de *.mso liés au fichier (on fout direct le code de la macro dans une balise spécifique et zou)


Message édité par Arjuna le 28-04-2006 à 15:48:19
Reply

Marsh Posté le 28-04-2006 à 16:03:36    

C:\WINDOWS\assembly\GAC\Microsoft.Office.Interop.Excel\11.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\office.dll

 
J'ai que ça dans mes références et ça fonctionne...


---------------
H. - 48h en fiat et j'ai déjà perdu la maitrise de mon argent
Reply

Marsh Posté le 28-04-2006 à 16:04:00    

ah excuse moi... j'ai lu en diagonale. Dans ce cas la il te reste ole automation. Pas trop le choix...  
 
Sinon une autre solution consisterait tout de même à créer le fichier EXCEL en xml et de reconvertir ensuite avec XSL-FO vers un fichier Excel Classique... Mais sincèrement je crois pas que ça changerait bcp que de faire directement tout en ole automation.

Reply

Marsh Posté le 28-04-2006 à 16:05:10    

moi23372 a écrit :

le problème avec ole automation c'est que si ça plante, c'est un plantage massif... alors qu'avec la lib, c'est plus performant et ça ne plante pas puisque c'est que de la construction d'xml


Suffit de faire une petite classe qui gère les E/S avec Excel.
Un petit try/catch quand on accède aux données et quand ça plante, ben on est toujours sain et sauf coté référence.

Message cité 1 fois
Message édité par Xas le 28-04-2006 à 16:05:48

---------------
H. - 48h en fiat et j'ai déjà perdu la maitrise de mon argent
Reply

Marsh Posté le 28-04-2006 à 16:06:28    

Xas a écrit :

C:\WINDOWS\assembly\GAC\Microsoft.Office.Interop.Excel\11.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\office.dll

 
J'ai que ça dans mes références et ça fonctionne...


A priori, il me manque le premier. Je ne sais pas pkoi. Quand je fais "add reference", il n'est pas présent.

Reply

Marsh Posté le 28-04-2006 à 16:10:42    

moi23372 a écrit :

ah excuse moi... j'ai lu en diagonale. Dans ce cas la il te reste ole automation. Pas trop le choix...  
 
Sinon une autre solution consisterait tout de même à créer le fichier EXCEL en xml et de reconvertir ensuite avec XSL-FO vers un fichier Excel Classique... Mais sincèrement je crois pas que ça changerait bcp que de faire directement tout en ole automation.


Ca va surtout être la grosse prise de tête ;)
 
Avec OLE, ça devrait aller.
Je récupère mon DS. J'en fait un "WriteXml", je passe en paramètre à mon VBS le fichier généré.
Je le parse avec MSXML dans le VBS, et je construis dynamiquement mon document Excel via une instance d'Excel ouverte.
Quand j'ai fini, j'affiche la fenêtre et je rends la main au programme.
Comme ça le gus choisi d'enregistrer ou non le fichier, et l'appli peut continuer à tourner pendant ce temps. C'est à la limite mieux qu'avec une lib, parceque Excel est directement ouvert avec le fichier comme ça ;)
 
Couche de décodage du flux XML à part, j'ai testé et ça marche. Je termine le reste de l'appli, et après je passe à ça. Je vais plus être emmerdé par l'absence d'IDE pour VBS (pratique pour retrouver le nom des méthodes d'un objet créé avec "CreateObject" :D) qu'autrechose, pour le reste ça va marcher comme une bête acro Excel (d'ailleurs, je crois que je vais commencer par le faire sous forme de Macro avant d'en faire un VBS).

Reply

Marsh Posté le 28-04-2006 à 16:12:02    

Xas a écrit :

Suffit de faire une petite classe qui gère les E/S avec Excel.
Un petit try/catch quand on accède aux données et quand ça plante, ben on est toujours sain et sauf coté référence.


Borf, un bon gros "On Error Resume Next" dans mon VBS et c'est bon :D
En plus, l'intérêt c'est que le VBS sera appelé par un Shell.Run() donc même s'il plante, ça foutra pas en l'air mon appli, qui tourne dans un processus totalement séparé :)


Message édité par Arjuna le 28-04-2006 à 16:12:19
Reply

Marsh Posté le 10-05-2006 à 11:35:33    

Bon, pour ceux que ça intéresse, je suis donc finalement arrivé à la phase de développement où je pouvais plus faire sans cette fonctionnalité :D
 
Du coup j'ai torché ça en 1 heure, ça marche pour moi. C'est à complèter, mais ça pourrais aider à démarrer une personne bloquée comme moi.
 

Code :
  1. Option Explicit
  2. ' Titre : DS2XLS
  3. ' Auteur : MagicBuzz
  4. ' Version : 1.0
  5. ' Date : 10-05-2006
  6. '
  7. ' Script VBS qui génère un document Excel à partir d'un extract "ToXml()" d'un Objet DataSet de .NET
  8. ' Ce script est censé fonctionner sur n'importe quelle version de Windows, et n'importe quelle version d'Excel
  9. ' Bon, rien n'est garanti non plus hein...
  10. ' Constantes
  11. ' Ces GUID génériques ont l'avantage d'être idetiques pour toutes les versions
  12. ' Il faut alors faire confiance à Microsoft pour ne pas changer la structure des objets d'une version à l'autre
  13. Const EXCEL_GUID = "Excel.Application"
  14. Const MSXML_GUID = "MSXML.DOMDocument"
  15. ' Méthodes
  16. Sub Main()
  17.     ' Excel objects
  18.     Dim xls
  19.     Dim wkb
  20.     Dim sht
  21.    
  22.     ' DOM objects
  23.     Dim dom
  24.     Dim declaration
  25.     Dim table
  26.     Dim colonne
  27.     Dim ligne
  28.    
  29.     ' Common variables
  30.     Dim tabName
  31.     Dim arrColonnes()
  32.    
  33.     ' Compteurs
  34.     Dim i
  35.     Dim j
  36.    
  37.     ' Création d'une instance d'Excel
  38.     Set xls = CreateObject(EXCEL_GUID)
  39.     ' On ne l'affiche pas
  40.     'xls.Visible = True
  41.    
  42.     ' Ajout d'un espace de travail (par défaut, Excel s'ouvre vide)
  43.     Set wkb = xls.Workbooks.Add()
  44.    
  45.     ' L'espace de travail contient de base 3 sheets. On en vire deux et on renomme la dernière
  46.     ' En effet, un espace de travail doit au moins toujours contenir une feuille...
  47.     For i = wkb.WorkSheets.Count To 2 Step -1
  48.         wkb.WorkSheets(i).Delete
  49.     Next
  50.     wkb.WorkSheets(1).Name = "tmpSheet"
  51.    
  52.     ' Ouverture du document XML contenant les données du dataset à sauvegarder
  53.     Set dom = CreateObject(MSXML_GUID)
  54.     dom.Load "export.xml"
  55.    
  56.     ' Recherche du tag de description des DataTables
  57.     Set declaration = dom.DocumentElement.SelectNodes("xs:schema/xs:element/xs:complexType/xs:choice/xs:element" )
  58.    
  59.     ' C'est parti !
  60.     For Each table In declaration
  61.         tabName = GetAttributeByName(table, "name" )
  62.         Set sht = wkb.WorkSheets.Add()
  63.         sht.Name = tabName
  64.         ReDim arrColonnes(1)
  65.         i = 0
  66.         For Each colonne In table.SelectNodes("xs:complexType/xs:sequence/xs:element" )
  67.             i = i + 1
  68.             ReDim Preserve arrColonnes(i)
  69.             ' En-tête
  70.             arrColonnes(i) = GetAttributeByName(colonne, "name" )
  71.             sht.Cells(1, i).Value = GetAttributeByName(colonne, "name" )
  72.             sht.Cells(1, i).Interior.ColorIndex = 36
  73.             sht.Cells(1, i).Font.Bold = True
  74.             ' Formattage du type de la colonne
  75.             Select Case GetAttributeByName(colonne, "type" )
  76.                 Case "xs:string"
  77.                     sht.Columns(i).NumberFormat = "@"
  78.                 Case "xs:decimal"
  79.                     sht.Columns(i).NumberFormat = "0.00"
  80.                 Case Else
  81.                     ' Ouais, ben désolé, moi je me sert que de string et decimal...
  82.                     sht.Columns(i).Interior.ColorIndex = 3
  83.                     MsgBox("Type inconnu : " & GetAttributeByName(colonne, "type" ))
  84.             End Select
  85.         Next
  86.        
  87.         ' Maintenant, on parcours l'ensemble des éléments correspondant au datatable en cours de lecture
  88.         j = 1
  89.         For Each ligne In dom.DocumentElement.SelectNodes(tabName)
  90.             j = j + 1
  91.             For i = 1 To UBound(arrColonnes)
  92.                 ' On recopie bêtement le contenu du tag portant le nom de la colonne désirée
  93.                 sht.Cells(j, i).Value = ligne.SelectSingleNode(arrColonnes(i)).Text
  94.             Next
  95.         Next
  96.        
  97.         ' Ca c'est pour faire joli (si faire se peut)
  98.         sht.Columns.EntireColumn.AutoFit
  99.     Next
  100.    
  101.     ' Vous vous rappelez de la sheet renommée ? Ben on la zigouille maintenant
  102.     wkb.WorkSheets("tmpSheet" ).Delete
  103.    
  104.     ' On indique qu'on ferme l'espace de travail en enregistrant le document (une popup d'enregistrement apparaît)
  105.     wkb.Close(true)
  106.    
  107.     ' On quitte Excel
  108.     xls.Quit
  109. End Sub
  110. Function GetAttributeByName(node, attributeName)
  111.     ' Impossible d'utiliser les collections nommées en VBS. Du coup on fait avec les moyens du bords...
  112.     Dim tmpRet
  113.     Dim att
  114.     tmpRet = ""
  115.     For Each att in node.attributes
  116.         If att.Name = attributeName Then
  117.             tmpRet = att.Value
  118.             Exit For
  119.         End If
  120.     Next
  121.    
  122.     GetAttributeByName = tmpRet
  123. End Function
  124. ' Démarrage du programme
  125. Call Main()

Reply

Marsh Posté le 10-05-2006 à 12:13:11    

sinon :
ftp://ftp2.developpez.be/developp [...] ficeCs.pdf
 
c'est un pdf qui explique comment generer des docs office au sens large

Reply

Marsh Posté le 10-05-2006 à 14:35:05    

Perso, j'utilise la librairie Koogra sur sourceforge, totalement independante d'excel (aucunement besoin d'avoir office sur la machine). Par contre, faut se faire la grille à la mano :D

Reply

Marsh Posté le 10-05-2006 à 14:54:04    

Merci pour le lien :)
 
Par contre, même si c'est crade, je conserve ma version : ton exemple repose sur les COM "de base" c'est à dire que je dois lier la DLL à ma version d'Excel.
 
Résultat, si je veux que l'appli soit compatible avec plusieurs versions d'Office, je dois installer chaque version d'Excel sur mon poste, puis compiler une version de mon programme pour chaque version d'Excel.
Je préfère donc utiliser mon bignou à deux balles, qui :
-> Instancie depuis C# un environnement de commande, quelle que soit la version de Windows
-> Lance Excel et joue dedans, quelle que soit la version d'Office
 
Bon, après, je suis d'accord, ça reste un bon gros script de grand-mère mais bon, on peut pas tout avoir...

Reply

Marsh Posté le 10-05-2006 à 15:00:03    

Citation :


' Constantes' Ces GUID génériques ont l'avantage d'être idetiques pour toutes les versions' Il faut alors faire confiance à Microsoft pour ne pas changer la structure des objets d'une version à l'autre
Const EXCEL_GUID = "Excel.Application"


Si tu regardes la base des registres, tu verras que [HKEY_CLASSES_ROOT\] Excel.Application [\CurVer] pointe vers la version qui est installé sur l'ordinateur
Donc no soucay pour les versions suivantes.


Message édité par breizhbugs le 10-05-2006 à 15:00:28
Reply

Marsh Posté le 10-05-2006 à 15:22:30    

Ben oui justement :)
Ce qui permet de distribuer le même script quelle que soit la version installée.
Le programme est capable de retrouver la DLL un peut comme l'association des fichiers : on installe un nouvel outil qui se déclare comme étant le destinataire de cet appel et hop ! pas besoin de changer les liaisons dans le programme :)

Reply

Marsh Posté le 10-08-2006 à 09:54:33    

Arjuna a écrit :

Moi j'ai la 2003 (11), sauf qu'il me manque les "PIA" d'Excel. Et impossible de trouver où les télécharger (y'a un lien dans la MSDN, mais ça tombe sur une liste de dwl qui n'ont rien à voir)

 

Vous avez une idée ?

 


http://support.microsoft.com/defau [...] r%3B897646
 
Tu pouvais les créer toi aussi à partir des fichiers .tlb correspondants et l'outils TlbImp fourni avec Microsoft Visual Studio .NET..

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed