Comment puis-je exporter un DataTablefichier vers Excel en C #? J'utilise Windows Forms. Le DataTableest associé à un DataGridViewcontrôle. Je dois exporter des enregistrements DataTablevers Excel.
Le moyen le plus simple est de faire une boucle foreach imbriquée sur les éléments et sous-éléments.
Saeid Yazdani
REMARQUE: si vous essayez de transmettre des valeurs d'une table de données à un objet puis à Excel, vous devez également effectuer la gestion des erreurs de type de données. Par exemple, Guids supprimera votre affectation avec une exception HRESULT: 0x800A03EC. Une solution sans tester les types de données consiste à utiliser «ToString ()» lors du remplissage de votre objet. Excel convertira les nombres au format numérique tout seul. FlashTrev a abordé la question connexe de la date / heure.
L'ajout d'environ 6 Mo de bibliothèques référencées ne rendrait pas l'application peu lourde?
ʞᴉɯ
4
Bonne question @MicheleVirgilio. Je n'ai fait aucun test pour quantifier un impact. Mais pour ce que ça vaut, cela ne m'a dérangé dans aucun des projets que je l'ai utilisé, en fait je ne peux pas dire que je l'ai déjà remarqué.
hmqcnoesy
Ce code m'a renvoyé un excellent avec une seule colonne avec une valeurClosedXML.Excel.XLWorkbook
C'est un piège
78
Essayez un code simple, pour convertir DataTable en fichier Excel au format csv:
Cela écrira un nouveau fichier excel.csvdans le répertoire de travail actuel, qui est généralement soit l'emplacement du fichier .exe, soit l'endroit où vous le lancez.
Quelle excellente réponse, mec. Je n'ai pas la possibilité de donner plus d'un vote positif à votre réponse, sinon j'aurais pu donner même plus de 100 votes positifs.
Ashok kumar
2
@Cuong Le - Si la cellule a deux virgules, alors ce sera un problème à "string.Join (", ")"
suneel ranga
@Cuong Le où sera l' "excel.csv"emplacement?
Jogi
2
@suneelranga - Si une cellule (c'est-à-dire dans row.ItemArray) contient une ,(virgule), alors selon la norme CSV, cette cellule doit être entourée de guillemets ",", puis apparaître dans le fichier comme d'habitude. Donc, oui - cela posera un problème car ce code ne détecte pas ,et n'applique pas les guillemets.
Tom Leys
1
@ Si8 une fois enregistré, vous pouvez faire un Process.Start (votre fichier) et il l'ouvrira pour eux. C'est à peu près aussi proche que possible, je crois ..
TimmRH
40
Une option élégante consiste à écrire une méthode d'extension (voir ci-dessous) pour la classe DataTable du framework .net.
Cette méthode d'extension peut être appelée comme suit:
using System;
using System.Collections.Generic;
using System.Linq;
using Excel=Microsoft.Office.Interop.Excel;
using System.Data;
using System.Data.OleDb;DataTable dt;// fill table data in dt here ...// export DataTable to excel// save excel file without ever making it visible if filepath is given// don't save excel file, just make it visible if no filepath is given
dt.ExportToExcel(ExcelFilePath);
Méthode d'extension pour la classe DataTable:
publicstaticclassMy_DataTable_Extensions{// Export DataTable into an excel file with field names in the header line// - Save excel file without ever making it visible if filepath is given// - Don't save excel file, just make it visible if no filepath is givenpublicstaticvoidExportToExcel(thisDataTable tbl,string excelFilePath =null){try{if(tbl ==null|| tbl.Columns.Count==0)thrownewException("ExportToExcel: Null or empty input table!\n");// load excel, and create a new workbookvar excelApp =newExcel.Application();
excelApp.Workbooks.Add();// single worksheetExcel._Worksheet workSheet = excelApp.ActiveSheet;// column headingsfor(var i =0; i < tbl.Columns.Count; i++){
workSheet.Cells[1, i +1]= tbl.Columns[i].ColumnName;}// rowsfor(var i =0; i < tbl.Rows.Count; i++){// to do: format datetime values before printingfor(var j =0; j < tbl.Columns.Count; j++){
workSheet.Cells[i +2, j +1]= tbl.Rows[i][j];}}// check file pathif(!string.IsNullOrEmpty(excelFilePath)){try{
workSheet.SaveAs(excelFilePath);
excelApp.Quit();MessageBox.Show("Excel file saved!");}catch(Exception ex){thrownewException("ExportToExcel: Excel file could not be saved! Check filepath.\n"+ ex.Message);}}else{// no file path is given
excelApp.Visible=true;}}catch(Exception ex){thrownewException("ExportToExcel: \n"+ ex.Message);}}}
@ alex.pulver cela ne fonctionne pas non plus lorsque j'ai essayé de l'utiliser sur un serveur. Bon point à mentionner.
Si8
Cela fonctionnera mais c'est lent. Il est préférable de copier dans le presse-papiers et de coller dans Excel. Si vous travaillez sur plus de 1000 enregistrements, cela prendra un certain temps.
Alex M
25
Solution basée sur l' article de tuncalik (merci pour l'idée), mais en cas de grandes tables, elle fonctionne beaucoup plus vite (et est un peu moins claire).
publicstaticclassMy_DataTable_Extensions{/// <summary>/// Export DataTable to Excel file/// </summary>/// <param name="DataTable">Source DataTable</param>/// <param name="ExcelFilePath">Path to result file name</param>publicstaticvoidExportToExcel(thisSystem.Data.DataTableDataTable,stringExcelFilePath=null){try{intColumnsCount;if(DataTable==null||(ColumnsCount=DataTable.Columns.Count)==0)thrownewException("ExportToExcel: Null or empty input table!\n");// load excel, and create a new workbookMicrosoft.Office.Interop.Excel.ApplicationExcel=newMicrosoft.Office.Interop.Excel.Application();Excel.Workbooks.Add();// single worksheetMicrosoft.Office.Interop.Excel._WorksheetWorksheet=Excel.ActiveSheet;object[]Header=newobject[ColumnsCount];// column headings for(int i =0; i <ColumnsCount; i++)Header[i]=DataTable.Columns[i].ColumnName;Microsoft.Office.Interop.Excel.RangeHeaderRange=Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1,1]),(Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1,ColumnsCount]));HeaderRange.Value=Header;HeaderRange.Interior.Color=System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray);HeaderRange.Font.Bold=true;// DataCellsintRowsCount=DataTable.Rows.Count;object[,]Cells=newobject[RowsCount,ColumnsCount];for(int j =0; j <RowsCount; j++)for(int i =0; i <ColumnsCount; i++)Cells[j, i]=DataTable.Rows[j][i];Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[2,1]),(Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[RowsCount+1,ColumnsCount])).Value=Cells;// check fielpathif(ExcelFilePath!=null&&ExcelFilePath!=""){try{Worksheet.SaveAs(ExcelFilePath);Excel.Quit();System.Windows.MessageBox.Show("Excel file saved!");}catch(Exception ex){thrownewException("ExportToExcel: Excel file could not be saved! Check filepath.\n"+ ex.Message);}}else// no filepath is given{Excel.Visible=true;}}catch(Exception ex){thrownewException("ExportToExcel: \n"+ ex.Message);}}}
La réponse de tuncalik a pris presque une minute pour moi, c'est à 1 seconde si cela prend du temps ... J'étais en fait surpris.
Wilsu
2
C'est l'échantillon le plus rapide que j'ai essayé, excellent travail. J'ai dû utiliser Marshal pour publier le fichier après. Excel.Quit(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);
Dave Kelly
Faut-il installer Office?
Parshuram Kalvikatte
Fonctionne parfaitement autrement, mais ma couleur de fond Header Back est toujours définie sur Noir lors de l'utilisation de cette solution dans l'application console. Quelle pourrait être la raison??
Zaveed Abbasi le
15
Essayez cette fonction en transmettant le chemin de la table de données et du fichier où vous souhaitez exporter
publicvoidCreateCSVFile(refDataTable dt,string strFilePath){try{// Create the CSV file to which grid data will be exported.StreamWriter sw =newStreamWriter(strFilePath,false);// First we will write the headers.//DataTable dt = m_dsProducts.Tables[0];int iColCount = dt.Columns.Count;for(int i =0; i < iColCount; i++){
sw.Write(dt.Columns[i]);if(i < iColCount -1){
sw.Write(",");}}
sw.Write(sw.NewLine);// Now write all the rows.foreach(DataRow dr in dt.Rows){for(int i =0; i < iColCount; i++){if(!Convert.IsDBNull(dr[i])){
sw.Write(dr[i].ToString());}if(i < iColCount -1){
sw.Write(",");}}
sw.Write(sw.NewLine);}
sw.Close();}catch(Exception ex){throw ex;}}
Notez que cela n'utilisera pas vraiment les cellules du tableau dans le document Excel, à la place tout pour chaque ligne sera imprimé sur la première cellule de chaque ligne.
Banshee
@Banshee Non, Excel comprend parfaitement les fichiers CSV.
NickG
Cela ne fonctionne pas non plus avec mon Excel. Les données de chaque ligne se trouvent dans la première cellule.
Mitulát báti
5
Le moyen le meilleur et le plus simple
privatevoid exportToExcel(DataTable dt){/*Set up work book, work sheets, and excel application*/Microsoft.Office.Interop.Excel.Application oexcel =newMicrosoft.Office.Interop.Excel.Application();try{string path =AppDomain.CurrentDomain.BaseDirectory;object misValue =System.Reflection.Missing.Value;Microsoft.Office.Interop.Excel.Workbook obook = oexcel.Workbooks.Add(misValue);Microsoft.Office.Interop.Excel.Worksheet osheet =newMicrosoft.Office.Interop.Excel.Worksheet();// obook.Worksheets.Add(misValue);
osheet =(Microsoft.Office.Interop.Excel.Worksheet)obook.Sheets["Sheet1"];int colIndex =0;int rowIndex =1;foreach(DataColumn dc in dt.Columns){
colIndex++;
osheet.Cells[1, colIndex]= dc.ColumnName;}foreach(DataRow dr in dt.Rows){
rowIndex++;
colIndex =0;foreach(DataColumn dc in dt.Columns){
colIndex++;
osheet.Cells[rowIndex, colIndex]= dr[dc.ColumnName];}}
osheet.Columns.AutoFit();string filepath ="C:\\Temp\\Book1";//Release and terminate excel
obook.SaveAs(filepath);
obook.Close();
oexcel.Quit();
releaseObject(osheet);
releaseObject(obook);
releaseObject(oexcel);
GC.Collect();}catch(Exception ex){
oexcel.Quit();
log.AddToErrorLog(ex,this.Name);}}
(s'il vous plaît soyez ici) s'il y a plus d'un fichier Excel ouvert, cette fonction de publication les détruit-elle tous ou seulement celui passé en paramètre?
Elliott Addi
1
Interopérabilité Excel:
Cette méthode empêche les dates de passer du jj-mm-aaaa au mm-jj-aaaa
publicboolDataTableToExcelFile(DataTable dt,string targetFile){constbool dontSave =false;bool success =true;//Exit if there is no rows to exportif(dt.Rows.Count==0)returnfalse;object misValue =System.Reflection.Missing.Value;List<int> dateColIndex =newList<int>();Excel.Application excelApp =newExcel.Application();Excel.Workbook excelWorkBook = excelApp.Workbooks.Add(misValue);Excel.Worksheet excelWorkSheet = excelWorkBook.Sheets("sheet1");//Iterate through the DataTable and populate the Excel work sheettry{for(int i =-1; i <= dt.Rows.Count-1; i++){for(int j =0; j <= dt.Columns.Count-1; j++){if(i <0){//Take special care with Date columnsif(dt.Columns(j).DataTypeistypeof(DateTime)){
excelWorkSheet.Cells(1, j +1).EntireColumn.NumberFormat="d-MMM-yyyy;@";
dateColIndex.Add(j);}//else if ... Feel free to add more Formatselse{//Otherwise Format the column as text
excelWorkSheet.Cells(1, j +1).EntireColumn.NumberFormat="@";}
excelWorkSheet.Cells(1, j +1)= dt.Columns(j).Caption;}elseif(dateColIndex.IndexOf(j)>-1){
excelWorkSheet.Cells(i +2, j +1)=Convert.ToDateTime(dt.Rows(i).ItemArray(j)).ToString("d-MMM-yyyy");}else{
excelWorkSheet.Cells(i +2, j +1)= dt.Rows(i).ItemArray(j).ToString();}}}//Add Autofilters to the Excel work sheet
excelWorkSheet.Cells.AutoFilter(1,Type.Missing,Excel.XlAutoFilterOperator.xlAnd,Type.Missing,true);//Autofit columns for neatness
excelWorkSheet.Columns.AutoFit();if(File.Exists(exportFile))File.Delete(exportFile);
excelWorkSheet.SaveAs(exportFile);}catch{
success =false;}finally{//Do this irrespective of whether there was an exception or not.
excelWorkBook.Close(dontSave);
excelApp.Quit();
releaseObject(excelWorkSheet);
releaseObject(excelWorkBook);
releaseObject(excelApp);}return success;}
Si vous ne vous souciez pas des dates inversées, utilisez le lien Voir qui montre comment remplir toutes les cellules de la feuille de calcul Excel en une seule ligne de code:
Utilisez simplement la bibliothèque CloseMXL.Excel . C'est facile et assez rapide aussi.
Classe
privateDataTable getAllList(){string constr =ConfigurationManager.ConnectionStrings["RConnection"].ConnectionString;
using (SqlConnection con =newSqlConnection(constr)){
using (SqlCommand cmd =newSqlCommand("SELECT EmpId, gender, EmpName, pOnHold FROM Employee WHERE EmpId= '"+AnyVariable+"' ORDER BY EmpName")){
using (SqlDataAdapter da =newSqlDataAdapter()){DataTable dt =newDataTable();
cmd.CommandType=CommandType.Text;
cmd.Connection= con;
da.SelectCommand= cmd;
da.Fill(dt);
dt.Columns[0].ColumnName="Employee Id";
dt.Columns[1].ColumnName="Gender";
dt.Columns[2].ColumnName="Employee Name";
dt.Columns[3].ColumnName="On Hold";return dt;}}}}
Puis une autre méthode qui récupère l'ensemble de données
publicDataSet getDataSetExportToExcel(){DataSet ds =newDataSet();DataTable dtEmp =newDataTable("CLOT List");
dtEmp = getAllList();
ds.Tables.Add(dtEmp);
ds.Tables[0].TableName="Employee";//If you which to use Mutliple Tabsreturn ds;}
Now you Button Click Event
protectedvoid btn_Export_Click(object sender,EventArgs e){DataSet ds = getDataSetExportToExcel();
using (XLWorkbook wb =newXLWorkbook()){
wb.Worksheets.Add(ds);
wb.Style.Alignment.Horizontal=XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold=true;Response.Clear();Response.Buffer=true;Response.Charset="";Response.ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";Response.AddHeader("content-disposition","attachment;filename=EmployeeonHoldList.xlsx");
using (MemoryStreamMyMemoryStream=newMemoryStream()){
wb.SaveAs(MyMemoryStream);MyMemoryStream.WriteTo(Response.OutputStream);Response.Flush();Response.End();}}}
Vous pouvez utiliser ma bibliothèque SwiftExcel . Il est particulièrement utile lorsque les performances et la faible utilisation de la mémoire sont en place car il écrit les données directement dans le fichier:
using (var ew =newExcelWriter("C:\\temp\\test.xlsx")){for(var row =1; row <=100; row++){for(var col =1; col <=10; col++){
ew.Write($"row:{row}-col:{col}", col, row);}}}
Je voulais ajouter cette réponse car j'ai passé beaucoup de temps à rechercher une méthode rapide et fiable pour ce faire et aucun exemple complet d'utilisation d'OpenXMLWriter à cette fin n'existait nulle part que je puisse trouver.
Premièrement, COM / Interop (que la plupart des autres réponses utilisent) convient à cet effet, mais il souffre de certaines sensibilités. Je l'ai utilisé pendant des décennies et il est généralement stable, mais lors de la mise en œuvre d'un entrepôt de données frontal pour des centaines d'utilisateurs, j'ai trouvé qu'il était soumis à trop de problèmes en fonction de la machine et de ce que l'utilisateur faisait, alors je suis passé à OpenXML. OpenXML DOM est assez bon à cet effet, mais c'est plus lent que d'utiliser OpenXMLWriter. Lorsque vous entrez dans de grands ensembles de données (100K +) avec beaucoup de colonnes, DOM est beaucoup plus lent qu'OpenXMLWriter, donc j'utilise ce dernier. La méthode ci-dessous écrit plus de 420 000 lignes avec plus de 30 champs en moins de 30 secondes.
J'espère que les commentaires seront suffisants pour guider quiconque dans ce qu'il fait. Il est simplifié en ce qu'il écrit toutes les valeurs dans le fichier sous forme de chaînes, mais vous pouvez implémenter une logique pour écrire divers types de données (et utiliser divers formats de cellules) en fonction du contenu de vos données. Vous pouvez également l'adapter pour une utilisation sur un DataGridView (au lieu d'un DataTable) en modifiant juste quelques éléments (à savoir les boucles à travers les colonnes / lignes).
Une référence à DocumentFormat.OpenXML (d / l avec le SDK OpenXML) et WindowsBase est requise.
ImportsDocumentFormat.OpenXmlImportsDocumentFormat.OpenXml.SpreadsheetImportsDocumentFormat.OpenXml.PackagingPublicSubExportToExcelXML(ByRef dt AsDataTable, filename AsString)Dim wbp AsWorkbookPart, wsp AsWorksheetPart'IfthisDataTable has more rows in it than can fit inExcel,throw an exception
If dt.Rows.Count>1048575ThenThrowNewException("The DataTable is too large to export to Excel.")'Delete any previous file of the same name that may exist.File.Delete(filename)'Create an OpenXMLSpreadsheetDocument...Using xls =SpreadsheetDocument.Create(filename,SpreadsheetDocumentType.Workbook)'Add a WorkbookPart to the SpreadsheetDoc, then add a WorksheetPart to the WorkbookPart.
wbp = xls.AddWorkbookPart()
wsp = wbp.AddNewPart(OfWorksheetPart)'Now we need to add the "StyleSheet" to the WorkbookPart(that we just added above).This will allow us to apply formatting to our Cells.'Add the WbStylesPart and the StyleSheet.Dim stp AsWorkbookStylesPart= wbp.AddNewPart(OfWorkbookStylesPart)Dim ss AsNewStylesheet'Create the only two Fonts we're going to use (Regular and Bold).Dim fBold AsNewFont
fBold.Append(NewBold)Dim fnts AsNewFonts
fnts.Append(NewFont)'This creates the default (unmodified, regular) Font. It's added first, so its index is0.
fnts.Append(fBold)'This creates the Bold font. It's added second, so its index is1.'Create the default Fill/Border settings (these have to be here, even though I don't set any custom fills/borders).Dim flls AsNewFillsDim brdrs AsNewBorders
flls.Append(NewFill)
brdrs.Append(NewBorder)'Now I have to add formats (NumberFormat and CellFormat).First, you create a NumberFormat.Thisis basically the pattern of
' the format (i.e."@"forText).For now, I only need a Text format, but I can add more patterns if needed.' I give the format an ID of 164, since 163iswhere the built-inExcel formats end.Dim nbrfmts AsNewNumberingFormats
nbrfmts.Append(NewNumberingFormatWith{.NumberFormatId=164,.FormatCode="@"})'Create the first two CellFormats:Default, which will have an index of 0 and "Header"(Bold/Centered) with an index of 1.Dim cellfmts AsNewCellFormats()
cellfmts.Append(NewCellFormat()With{.FontId=0,.NumberFormatId=164,.FillId=0,.BorderId=0})
cellfmts.Append(NewCellFormat()With{.FontId=1,.NumberFormatId=164,.Alignment=NewAlignment()With{.WrapText=True,.Horizontal=HorizontalAlignmentValues.Center}})'Add all of the Fonts/Fills/Borders/etc to the StyleSheet and add it all to the WorkbookStylesPart.
ss.Append(fnts)
ss.Append(flls)
ss.Append(brdrs)
ss.Append(cellfmts)
ss.NumberingFormats= nbrfmts
stp.Stylesheet= ss
stp.Stylesheet.Save()'Now create an OpenXMLWriter using the WorksheetPart to write the cells to the worksheet.Using oxw AsOpenXmlWriter=OpenXmlWriter.Create(wsp)'Write the start element for the Worksheet and the Columns...
oxw.WriteStartElement(NewWorksheet)
oxw.WriteStartElement(NewColumns())'Now I'm going to loop through the columns in the DataTable...For c AsInteger=0To dt.Columns.Count-1'Now we'll get the width for the column.Todothis, we loop through all of the rows and measure the width of the text
' using the defaultExcelFont(currently Font:CalibriSize:11) and return the largest width (in pixels) to use below.' Why not do this loop below (when I loop through the rows to write the Cells)? Because you can't.You have to
' write the Column XML first before writing the SheetData/Row/Cell XML (I confirmed this by trying it), so there's
' no way (that I'm aware of) to avoid looping through all of the rows twice if you want to AutoFit.'Setup vars we'll use for getting the column widths (below).Dim g =System.Drawing.Graphics.FromHwnd(IntPtr.Zero)Dim fnt =NewSystem.Drawing.Font("Calibri",11)Dim wid AsDouble=0'Get the width of the header (because if this is wider than the widest value, we'll use the header text's width).' I found that adding 2 pixels to the width was necessary to get the column as wide asExcel would make it.Dim tmp AsDouble= g.MeasureString(dt.Columns(c).ColumnName,NewSystem.Drawing.Font(fnt,System.Drawing.FontStyle.Bold)).Width+2'Loop through the rows in the dt and get the width of the value in that row/col. If it's wider than the widest
' width we've encountered thus far, use the new wider width as our basis.ForEach row AsDataRowIn dt.RowsIf tmp > wid Then wid = tmp
tmp = g.MeasureString(row(c).ToString, fnt).WidthNext'Set the column attributes and write it to the file. The Width is set using a formula that converts from pixels to Excel's column width values.Dim oxa AsNewList(OfOpenXmlAttribute)From{NewOpenXmlAttribute("min",Nothing, c +1),NewOpenXmlAttribute("max",Nothing, c +1),NewOpenXmlAttribute("width",Nothing,System.Math.Round((wid -12+5)/7D+1,2))}
oxw.WriteStartElement(NewColumn(), oxa)
oxw.WriteEndElement()Next'CLoseout the Columns collection.
oxw.WriteEndElement()'Write the start element for the SheetData...
oxw.WriteStartElement(NewSheetData)'Write the start element for the Header row.
oxw.WriteStartElement(NewRow)'Loop through the Columnsin the dt.ForEach col AsDataColumnIn dt.Columns'Write a cell for this column's Header.AllHeader cells are written with a DataType of String("str").' I ALSO apply the "Header"CellFormat(StyleIndex1) to all of the HeaderCells.This makes them Bold and Centered.WriteCell(oxw, col.ColumnName,"str",1)Next'Closeout the Header row.
oxw.WriteEndElement()'Loop through all of the rows in the dt...ForEach row AsDataRowIn dt.Rows'Write a StartElementforthis row...
oxw.WriteStartElement(NewRow)'Loop through all of the columns in the dt...For c AsInteger=0To dt.Columns.Count-1'Write a valueinthis row/column to the Excel file. I use the datatype of "String" and the defaultCellFormat/StyleIndex.WriteCell(oxw, row(c).ToString,"str",0)Next'Closeoutthis row.
oxw.WriteEndElement()Next'Closeout the Worksheet and SheetData elements...
oxw.WriteEndElement()
oxw.WriteEndElement()EndUsing'Now we're going to create an OpenXMLWriter using the WorkbookPart(that we created above)...Using oxw AsOpenXmlWriter=OpenXmlWriter.Create(wbp)'Add starting elements for the Workbook and Sheets collection.
oxw.WriteStartElement(NewWorkbook())
oxw.WriteStartElement(NewSheets())'Add the Sheet(name the Sheet after the file name minus the extension).
oxw.WriteElement(NewSheet()With{.Name=Path.GetFileNameWithoutExtension(filename),.SheetId=1,.Id= xls.WorkbookPart.GetIdOfPart(wsp)})'WriteEnd elements for the Workbook/Sheets
oxw.WriteEndElement()
oxw.WriteEndElement()EndUsingEndUsingEndSub'ThisSubis used to write a value to a Cell using OpenXMLWriter.PrivateSubWriteCell(ByRef oxw AsOpenXmlWriter,valueAsString, datatype AsString, style AsUInt32Value)Dim oxa AsNewList(OfOpenXmlAttribute)From{NewOpenXmlAttribute("t",Nothing, datatype),NewOpenXmlAttribute("s",Nothing, style)}
oxw.WriteStartElement(NewCell(), oxa)Ifvalue<>NothingThen oxw.WriteElement(NewCellValue(value))
oxw.WriteEndElement()EndSub
Merci beaucoup d'avoir consacré du temps à cette réponse. J'ai un client qui a une solution fonctionnelle dans Excel Interop, mais se plaint de sa lenteur. J'ai vu quelques autres réponses aux questions me guider vers OpenXML, mais je suis heureux d'avoir un raccourci pour commencer.
Brandon Barkley le
1
Aucun problème. J'utilise toujours COM, mais uniquement dans les environnements sur lesquels j'ai un contrôle total. J'utilise cette approche OpenXML dans une application avec quelques centaines d'utilisateurs depuis quelques mois et je n'ai eu aucun problème par rapport aux erreurs hebdomadaires avec COM. J'ai également examiné des solutions tierces, comme celles mentionnées ici, mais je préfère l'écrire moi-même afin de pouvoir la rendre aussi efficace que possible.
WATYF
0
En ce qui concerne la réponse de tuncalik , ce qui est génial, surtout si vous voulez jouer un peu avec le code :) mais il met mes dates dans Excel au format américain c'est à dire le 2 mars 2014 au Royaume-Uni est le 02/03/2014 mais aux USA son 03/02/2014 avec le mois 1er, puis le jour de la semaine après. J'ai besoin de l'avoir au format britannique, des idées s'il vous plaît?
J'ai vérifié qu'il est stocké au format britannique dans mon DataTable et mon Excel est également défini sur UK, mais pour une raison quelconque, lorsqu'il crée le document Excel, il pense qu'il est aux États-Unis (est-ce parce que Microsoft est une société américaine :)
J'essaierai d'expérimenter des codes de culture mais je ne sais pas encore où les mettre. J'ai essayé mais cela n'a eu aucun effet.
ps
J'ai dû changer une ligne pour que cela fonctionne en ajoutant un `` casting '' comme ci-dessous
// single worksheetExcel._Worksheet workSheet =(Excel._Worksheet)excelApp.ActiveSheet;
Mise à jour: J'ai réalisé le formatage des dates au Royaume-Uni en les convertissant au format LongDateTime, ce n'est qu'un travail de contournement.
Ancien fil de discussion - mais je pensais que je jetterais mon code ici. J'ai écrit une petite fonction pour écrire une table de données sur une nouvelle feuille Excel à un chemin spécifié (emplacement). Vous devrez également ajouter une référence à la bibliothèque Microsoft Excel 14.0.
je l'ai utilisé pour extrapoler comment écrire un datatable
* note dans les déclarations catch, j'ai une référence de classe statique errorhandler (vous pouvez les ignorer)
using excel =Microsoft.Office.Interop.Excel;
using System.IO;
using System.Data;
using System.Runtime.InteropServices;//class and namespace wrapper is not shown in this example privatevoidWriteToExcel(System.Data.DataTable dt,string location){//instantiate excel objects (application, workbook, worksheets)
excel.ApplicationXlObj=new excel.Application();XlObj.Visible=false;
excel._WorkbookWbObj=(excel.Workbook)(XlObj.Workbooks.Add(""));
excel._WorksheetWsObj=(excel.Worksheet)WbObj.ActiveSheet;//run through datatable and assign cells to values of datatabletry{int row =1;int col =1;foreach(DataColumn column in dt.Columns){//adding columnsWsObj.Cells[row, col]= column.ColumnName;
col++;}//reset column and row variables
col =1;
row++;for(int i =0; i < dt.Rows.Count; i++){//adding dataforeach(var cell in dt.Rows[i].ItemArray){WsObj.Cells[row, col]= cell;
col++;}
col =1;
row++;}WbObj.SaveAs(location);}catch(COMException x){ErrorHandler.Handle(x);}catch(Exception ex){ErrorHandler.Handle(ex);}finally{WbObj.Close();}}
Cela fonctionne bien, cependant, vous ne tuez jamais les processus Excel par la suite, donc je suggère d'ajouter ceci, en remplaçant votre SaveAsligne telle qu'elle est incluse ici: 'XlObj.DisplayAlerts = false; WbObj.SaveAs (emplacement); WbObj.Close (); XlObj.Quit (); Marshal.ReleaseComObject (WsObj); Marshal.ReleaseComObject (WbObj); Marshal.ReleaseComObject (XlObj); ' Pour utiliser la Marshal.ReleaseComObjectméthode, ajoutez l' using System.Runtime.InteropServicesassembly à votre projet.
GrammatonCleric
0
Une façon de le faire serait également avec ACE OLEDB Provider (voir aussi les chaînes de connexion pour Excel ). Bien sûr, vous devrez installer et enregistrer le fournisseur. Vous devriez l'avoir, si Excel est installé, mais c'est quelque chose que vous devez prendre en compte lors du déploiement de l'application.
Voici l'exemple de l'appel de la méthode d'assistance à partir de ExportHelper:ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");
L'assistant pour l'exportation vers un fichier Excel à l'aide d'ACE OLEDB:
publicclassExportHelper{privateconststringExcelOleDbConnectionStringTemplate="Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\";";/// <summary>/// Creates the Excel file from items in DataTable and writes them to specified output file./// </summary>publicstaticvoidCreateXlsFromDataTable(DataTable dataTable,string fullFilePath){string createTableWithHeaderScript =GenerateCreateTableCommand(dataTable);
using (var conn =newOleDbConnection(String.Format(ExcelOleDbConnectionStringTemplate, fullFilePath))){if(conn.State!=ConnectionState.Open){
conn.Open();}OleDbCommand cmd =newOleDbCommand(createTableWithHeaderScript, conn);
cmd.ExecuteNonQuery();foreach(DataRow dataExportRow in dataTable.Rows){AddNewRow(conn, dataExportRow);}}}privatestaticvoidAddNewRow(OleDbConnection conn,DataRow dataRow){string insertCmd =GenerateInsertRowCommand(dataRow);
using (OleDbCommand cmd =newOleDbCommand(insertCmd, conn)){AddParametersWithValue(cmd, dataRow);
cmd.ExecuteNonQuery();}}/// <summary>/// Generates the insert row command./// </summary>privatestaticstringGenerateInsertRowCommand(DataRow dataRow){var stringBuilder =newStringBuilder();var columns = dataRow.Table.Columns.Cast<DataColumn>().ToList();var columnNamesCommaSeparated =string.Join(",", columns.Select(x => x.Caption));var questionmarkCommaSeparated =string.Join(",", columns.Select(x =>"?"));
stringBuilder.AppendFormat("INSERT INTO [{0}] (", dataRow.Table.TableName);
stringBuilder.Append(columnNamesCommaSeparated);
stringBuilder.Append(") VALUES(");
stringBuilder.Append(questionmarkCommaSeparated);
stringBuilder.Append(")");return stringBuilder.ToString();}/// <summary>/// Adds the parameters with value./// </summary>privatestaticvoidAddParametersWithValue(OleDbCommand cmd,DataRow dataRow){var paramNumber =1;for(int i =0; i <= dataRow.Table.Columns.Count-1; i++){if(!ReferenceEquals(dataRow.Table.Columns[i].DataType,typeof(int))&&!ReferenceEquals(dataRow.Table.Columns[i].DataType,typeof(decimal))){
cmd.Parameters.AddWithValue("@p"+ paramNumber, dataRow[i].ToString().Replace("'","''"));}else{objectvalue=GetParameterValue(dataRow[i]);OleDbParameter parameter = cmd.Parameters.AddWithValue("@p"+ paramNumber,value);if(valueisdecimal){
parameter.OleDbType=OleDbType.Currency;}}
paramNumber = paramNumber +1;}}/// <summary>/// Gets the formatted value for the OleDbParameter./// </summary>privatestaticobjectGetParameterValue(objectvalue){if(valueisstring){returnvalue.ToString().Replace("'","''");}returnvalue;}privatestaticstringGenerateCreateTableCommand(DataTable tableDefination){StringBuilder stringBuilder =newStringBuilder();bool firstcol =true;
stringBuilder.AppendFormat("CREATE TABLE [{0}] (", tableDefination.TableName);foreach(DataColumn tableColumn in tableDefination.Columns){if(!firstcol){
stringBuilder.Append(", ");}
firstcol =false;string columnDataType ="CHAR(255)";switch(tableColumn.DataType.Name){case"String":
columnDataType ="CHAR(255)";break;case"Int32":
columnDataType ="INTEGER";break;case"Decimal":// Use currency instead of decimal because of bug described at // http://social.msdn.microsoft.com/Forums/vstudio/en-US/5d6248a5-ef00-4f46-be9d-853207656bcc/localization-trouble-with-oledbparameter-and-decimal?forum=csharpgeneral
columnDataType ="CURRENCY";break;}
stringBuilder.AppendFormat("{0} {1}", tableColumn.ColumnName, columnDataType);}
stringBuilder.Append(")");return stringBuilder.ToString();}}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using excel =Microsoft.Office.Interop.Excel;
using EL =ExcelLibrary.SpreadSheet;
using System.Drawing;
using System.Collections;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace _basic
{publicclassExcelProcesser{publicvoidWriteToExcel(System.Data.DataTable dt){
excel.ApplicationXlObj=new excel.Application();XlObj.Visible=false;
excel._WorkbookWbObj=(excel.Workbook)(XlObj.Workbooks.Add(""));
excel._WorksheetWsObj=(excel.Worksheet)WbObj.ActiveSheet;object misValue =System.Reflection.Missing.Value;try{int row =1;int col =1;foreach(DataColumn column in dt.Columns){//adding columnsWsObj.Cells[row, col]= column.ColumnName;
col++;}//reset column and row variables
col =1;
row++;for(int i =0; i < dt.Rows.Count; i++){//adding dataforeach(var cell in dt.Rows[i].ItemArray){WsObj.Cells[row, col]= cell;
col++;}
col =1;
row++;}WbObj.SaveAs(fileFullName, excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);}catch(Exception ex){MessageBox.Show(ex.Message);}finally{WbObj.Close(true, misValue, misValue);}}}
Cette solution pousse essentiellement des List<Object>données vers Excel, elle utilise DataTable pour y parvenir, j'ai implémenté une méthode d'extension, donc fondamentalement, deux choses sont nécessaires. 1. Une méthode d'extension.
publicstaticclassReportHelper{publicstaticstringToExcel<T>(thisIList<T> data){PropertyDescriptorCollection properties =TypeDescriptor.GetProperties(typeof(T));DataTable table =newDataTable();foreach(PropertyDescriptor prop in properties){//table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);if(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)]!=null){
table.Columns.Add(GetColumnHeader(prop),Nullable.GetUnderlyingType(prop.PropertyType)?? prop.PropertyType);}}//So it seems like when there is only one row of data the headers do not appear//so adding a dummy blank row which fixed the issues//Add a blank Row - Issue # 1471DataRow blankRow = table.NewRow();
table.Rows.Add(blankRow);foreach(T item in data){DataRow row = table.NewRow();foreach(PropertyDescriptor prop in properties)//row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;if(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)]!=null){
row[GetColumnHeader(prop)]= prop.GetValue(item)??DBNull.Value;}
table.Rows.Add(row);}
table.TableName="Results";var filePath =System.IO.Path.GetTempPath()+"\\"+System.Guid.NewGuid().ToString()+".xls";
table.WriteXml(filePath);return filePath;}privatestaticstringGetColumnHeader(PropertyDescriptor prop){return((FGMS.Entity.Extensions.ReportHeaderAttribute)(prop.Attributes[typeof(FGMS.Entity.Extensions.ReportHeaderAttribute)])).ReportHeaderText;}}
Décorez vos classes DTO avec l'attribut [ReportHeaderAttribute("Column Name")]
Tout ce qui doit être une colonne dans Excel doit être décoré avec [ReportHeaderAttribute("Column Name")]
Puis simplement
Var userList =Service.GetUsers()//Returns List of UserDTO;var excelFilePath = userList.ToExcel();HttpResponseMessage result =newHttpResponseMessage(HttpStatusCode.OK);var stream =newFileStream(excelFilePath,FileMode.Open);
result.Content=newStreamContent(stream);
result.Content.Headers.ContentType=newMediaTypeHeaderValue("application/vnd.ms-excel");
result.Content.Headers.ContentDisposition=newContentDispositionHeaderValue("attachment"){FileName="UserList.xls"};return result;
et si l'op ne veut pas créer des DTO pour chaque table contre laquelle ils vont l'exécuter? Comme par exemple pour chacune de mes 1 000 tables faites cela. L'ajout de l'attribut d'en-tête de rapport n'est pas à la volée - beaucoup de codage là-bas et cela avant même de travailler sur le vrai travail. Ne pas frapper votre solution - juste en soulignant que le principe de la paresse n'est pas utilisé ici car cette solution ajoute l'étape de création de DTO puis de compilation .. Je devrais dire - j'aime que vous ayez utilisé les génériques.
Ken le
0
Pour exporter des données vers Excel, vous pouvez utiliser la bibliothèque ClosedXML.Report ( https://github.com/ClosedXML/ClosedXML.Report ). Croyez-moi, c'est une merveilleuse bibliothèque et facile à utiliser pour elle. La bibliothèque n'a pas besoin d'Excel Interop. ClosedXML.Report génère un fichier Excel basé sur un modèle que vous pouvez créer dans Excel en utilisant n'importe quelle mise en forme. Par exemple:
var template =newXLTemplate(@".\Templates\report.xlsx");
using (var db =newDbDemos()){var cust = db.customers.LoadWith(c => c.Orders).First();
template.AddVariable(cust);
template.Generate();}
template.SaveAs(outputFile);
Private tmr AsSystem.Windows.Forms.TimerPrivateSubTestExcel()HandlesButton1.Click'// Initial data: SQL Server table with 6 columns and 293000 rows.'// Data table holding all dataDim dt AsNewDataTable("F161")'// Create connectionDim conn AsNewSqlConnection("Server=MYSERVER;Database=Test;Trusted_Connection=Yes;")Dim fAdapter AsNewSqlDataAdapterWith{.SelectCommand=NewSqlCommand($"SELECT * FROM dbo.MyTable", conn)}'// Fill DataTable
fAdapter.Fill(dt)'// Create Excel applicationDim xlApp AsNewExcel.ApplicationWith{.Visible=True}'// Temporarily disable screen updating
xlApp.ScreenUpdating=False'// Create brand new workbookDim xlBook AsExcel.Workbook= xlApp.Workbooks.Add()Dim xlSheet AsExcel.Worksheet=DirectCast(xlBook.Sheets(1),Excel.Worksheet)'// Get number of rowsDim rows_count = dt.Rows.Count'// Get number of columnsDim cols_count = dt.Columns.Count'// Here 's the core idea: after receiving data
'// you need to create an array and transfer it to sheet.'// Why array?'// Because it's the fastest way to transfer data to Excel's sheet.'// So, we have two tasks:'// 1) Create array'// 2) Transfer array to sheet'// ========================================================='// TASK 1: Create array'// ========================================================='// In order to create array, we need to know that'// Excel's Rangeobject expects 2-D array whose lower bounds
'// of both dimensions start from 1.'// This means you can't use C# array.'// You need to manually create such array.'// Since we already calculated number of rows and columns,'// we can use these numbers in creating array.Dim arr =Array.CreateInstance(GetType(Object),{rows_count, cols_count},{1,1})'// Fill arrayFor r =0To rows_count -1For c =0To cols_count -1
arr(r +1, c +1)= dt.Rows(r)(c)NextNext'// ========================================================='// TASK 2: Transfer array to sheet'// ========================================================='// Now we need to transfer array to sheet.'// So, how transfer array to sheet fast?'// '// THE FASTEST WAY TO TRANSFER DATA TO SHEET IS TO ASSIGN ARRAY TO RANGE.'// We could, of course, hard-code values, but Resize property'// makes this work a breeze:
xlSheet.Range("A1").Resize.Resize(rows_count, cols_count).Value= arr
'// If we decide to dump data by iterating over array,'// it will take LOTS of time.'// For r = 1 To rows_count'// For c = 1 To cols_count'// xlSheet.Cells(r, c) = arr(r, c)'// Next'// Next'// Here are time results:'// 1) Assigning array to Range: 3 seconds'// 2) Iterating over array: 45 minutes'// Turn updating on
xlApp.ScreenUpdating=True
xlApp =Nothing
xlBook =Nothing
xlSheet =Nothing'// Here we have another problem:'// creating array took lots of memory (about 150 MB).'// Using 'GC.Collect()', by unknown reason, doesn't help here.'// However, if you run GC.Collect() AFTER this procedure is finished'// (say, by pressing another button and calling another procedure),'// then the memory is cleaned up.'// I was wondering how to avoid creating some extra button to just release memory,'// so I came up with the idea to use timer to call GC.'// After 2 seconds GC collects all generations.'// Do not forget to dispose timer since we need it only once.
tmr =NewTimer()AddHandler tmr.Tick,Sub()
GC.Collect()
GC.WaitForPendingFinalizers()
GC.WaitForFullGCComplete()
tmr.Dispose()EndSub
tmr.Interval=TimeSpan.FromSeconds(2).TotalMilliseconds()
tmr.Start()EndSub
publicclassTestObject{publicintCol1{get;set;}publicintCol2{get;set;}publicstringCol3{get;set;}publicDateTimeCol4{get;set;}}[TestMethod]publicvoidLoadFromCollection_MemberList_Test(){///programming/32587834/epplus-loadfromcollection-text-converted-to-number/32590626#32590626varTestObjectList=newList<TestObject>();for(var i =0; i <10; i++)TestObjectList.Add(newTestObject{Col1= i,Col2= i*10,Col3=(i*10)+"E4"});//Create a test filevar fi =newFileInfo(@"c:\temp\LoadFromCollection_MemberList_Test.xlsx");if(fi.Exists)
fi.Delete();
using (var pck =newExcelPackage(fi)){//Do NOT include Col1var mi =typeof(TestObject).GetProperties().Where(pi => pi.Name!="Col1").Select(pi =>(MemberInfo)pi).ToArray();var worksheet = pck.Workbook.Worksheets.Add("Sheet1");
worksheet.Cells.LoadFromCollection(TestObjectList,true,TableStyles.Dark1,BindingFlags.Public|BindingFlags.Instance, mi);
pck.Save();}}
Réponses:
Je recommanderais ClosedXML -
Vous pouvez transformer un DataTable en une feuille de calcul Excel avec du code très lisible:
Le développeur est réactif et serviable. Le projet est activement développé et la documentation est superbe.
la source
ClosedXML.Excel.XLWorkbook
Essayez un code simple, pour convertir DataTable en fichier Excel au format csv:
Cela écrira un nouveau fichier
excel.csv
dans le répertoire de travail actuel, qui est généralement soit l'emplacement du fichier .exe, soit l'endroit où vous le lancez.la source
"excel.csv"
emplacement?,
(virgule), alors selon la norme CSV, cette cellule doit être entourée de guillemets","
, puis apparaître dans le fichier comme d'habitude. Donc, oui - cela posera un problème car ce code ne détecte pas,
et n'applique pas les guillemets.Une option élégante consiste à écrire une méthode d'extension (voir ci-dessous) pour la classe DataTable du framework .net.
Cette méthode d'extension peut être appelée comme suit:
Méthode d'extension pour la classe DataTable:
la source
ExcelFilePath != null && ExcelFilePath != ""
pourrait être!String.IsNullOrEmpty(ExcelFilePath)
Solution basée sur l' article de tuncalik (merci pour l'idée), mais en cas de grandes tables, elle fonctionne beaucoup plus vite (et est un peu moins claire).
la source
Excel.Quit(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);
Essayez cette fonction en transmettant le chemin de la table de données et du fichier où vous souhaitez exporter
la source
Le moyen le meilleur et le plus simple
la source
private void releaseObject(object o) { try { while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) { } } catch { } finally { o = null; } }
Interopérabilité Excel:
Excel Interop - Efficacité et performances
CSV:
la source
Classe
Puis une autre méthode qui récupère l'ensemble de données
Now you Button Click Event
la source
Vous pouvez utiliser ma bibliothèque SwiftExcel . Il est particulièrement utile lorsque les performances et la faible utilisation de la mémoire sont en place car il écrit les données directement dans le fichier:
Commande Nuget à installer:
la source
Je voulais ajouter cette réponse car j'ai passé beaucoup de temps à rechercher une méthode rapide et fiable pour ce faire et aucun exemple complet d'utilisation d'OpenXMLWriter à cette fin n'existait nulle part que je puisse trouver.
Premièrement, COM / Interop (que la plupart des autres réponses utilisent) convient à cet effet, mais il souffre de certaines sensibilités. Je l'ai utilisé pendant des décennies et il est généralement stable, mais lors de la mise en œuvre d'un entrepôt de données frontal pour des centaines d'utilisateurs, j'ai trouvé qu'il était soumis à trop de problèmes en fonction de la machine et de ce que l'utilisateur faisait, alors je suis passé à OpenXML. OpenXML DOM est assez bon à cet effet, mais c'est plus lent que d'utiliser OpenXMLWriter. Lorsque vous entrez dans de grands ensembles de données (100K +) avec beaucoup de colonnes, DOM est beaucoup plus lent qu'OpenXMLWriter, donc j'utilise ce dernier. La méthode ci-dessous écrit plus de 420 000 lignes avec plus de 30 champs en moins de 30 secondes.
J'espère que les commentaires seront suffisants pour guider quiconque dans ce qu'il fait. Il est simplifié en ce qu'il écrit toutes les valeurs dans le fichier sous forme de chaînes, mais vous pouvez implémenter une logique pour écrire divers types de données (et utiliser divers formats de cellules) en fonction du contenu de vos données. Vous pouvez également l'adapter pour une utilisation sur un DataGridView (au lieu d'un DataTable) en modifiant juste quelques éléments (à savoir les boucles à travers les colonnes / lignes).
Une référence à DocumentFormat.OpenXML (d / l avec le SDK OpenXML) et WindowsBase est requise.
la source
En ce qui concerne la réponse de tuncalik , ce qui est génial, surtout si vous voulez jouer un peu avec le code :) mais il met mes dates dans Excel au format américain c'est à dire le 2 mars 2014 au Royaume-Uni est le 02/03/2014 mais aux USA son 03/02/2014 avec le mois 1er, puis le jour de la semaine après. J'ai besoin de l'avoir au format britannique, des idées s'il vous plaît?
J'ai vérifié qu'il est stocké au format britannique dans mon DataTable et mon Excel est également défini sur UK, mais pour une raison quelconque, lorsqu'il crée le document Excel, il pense qu'il est aux États-Unis (est-ce parce que Microsoft est une société américaine :)
J'essaierai d'expérimenter des codes de culture mais je ne sais pas encore où les mettre. J'ai essayé mais cela n'a eu aucun effet.
ps
J'ai dû changer une ligne pour que cela fonctionne en ajoutant un `` casting '' comme ci-dessous
Mise à jour: J'ai réalisé le formatage des dates au Royaume-Uni en les convertissant au format LongDateTime, ce n'est qu'un travail de contournement.
à votre santé.
la source
Vous pouvez utiliser EasyXLS qui est une bibliothèque pour l'exportation de fichiers Excel.
Vérifiez ce code:
Voir aussi cet exemple sur la façon d' exporter des datatable pour exceller en C # .
la source
Ancien fil de discussion - mais je pensais que je jetterais mon code ici. J'ai écrit une petite fonction pour écrire une table de données sur une nouvelle feuille Excel à un chemin spécifié (emplacement). Vous devrez également ajouter une référence à la bibliothèque Microsoft Excel 14.0.
J'ai tiré de ce fil sur l'écriture de quoi que ce soit pour exceller - Comment écrire des données dans un fichier Excel (.xlsx)
je l'ai utilisé pour extrapoler comment écrire un datatable
* note dans les déclarations catch, j'ai une référence de classe statique errorhandler (vous pouvez les ignorer)
la source
SaveAs
ligne telle qu'elle est incluse ici: 'XlObj.DisplayAlerts = false; WbObj.SaveAs (emplacement); WbObj.Close (); XlObj.Quit (); Marshal.ReleaseComObject (WsObj); Marshal.ReleaseComObject (WbObj); Marshal.ReleaseComObject (XlObj); ' Pour utiliser laMarshal.ReleaseComObject
méthode, ajoutez l'using System.Runtime.InteropServices
assembly à votre projet.Une façon de le faire serait également avec ACE OLEDB Provider (voir aussi les chaînes de connexion pour Excel ). Bien sûr, vous devrez installer et enregistrer le fournisseur. Vous devriez l'avoir, si Excel est installé, mais c'est quelque chose que vous devez prendre en compte lors du déploiement de l'application.
Voici l'exemple de l'appel de la méthode d'assistance à partir de
ExportHelper
:ExportHelper.CreateXlsFromDataTable(myDataTable, @"C:\tmp\export.xls");
L'assistant pour l'exportation vers un fichier Excel à l'aide d'ACE OLEDB:
la source
utiliser la classe suivante
}
la source
Tout ce qui doit être une colonne dans Excel doit être décoré avec
[ReportHeaderAttribute("Column Name")]
Puis simplement
la source
Pour exporter des données vers Excel, vous pouvez utiliser la bibliothèque ClosedXML.Report ( https://github.com/ClosedXML/ClosedXML.Report ). Croyez-moi, c'est une merveilleuse bibliothèque et facile à utiliser pour elle. La bibliothèque n'a pas besoin d'Excel Interop. ClosedXML.Report génère un fichier Excel basé sur un modèle que vous pouvez créer dans Excel en utilisant n'importe quelle mise en forme. Par exemple:
la source
la source
Exemple de code purement (au cas où cela pourrait aider quelqu'un avec des idées), basé sur la réponse de Tomasz Wiśniewski d'ici: https://stackoverflow.com/a/21079709/2717521
Bouton d'exportation de MainWindow:
Classe ExportToExcel:
la source
Avec le package EPPlus NuGet, c'est très simple .
Notez que ce
Col1
n'est PAS dans la sortie:la source