125 votes

Comment exporter une DataTable vers Excel

Comment puis-je exporter un DataTable à Excel en C# ? J'utilise Windows Forms. Le site DataTable est associé à un DataGridView contrôle. Je dois exporter des enregistrements de DataTable à Excel.

0 votes

La méthode la plus simple consiste à effectuer une boucle foreach imbriquée sur les éléments et les sous-éléments.

0 votes

REMARQUE : si vous essayez de transmettre des valeurs d'une table de données à un objet puis à Excel, vous devez également traiter les erreurs de type de données. Par exemple, les Guids tueront votre affectation avec une exception HRESULT : 0x800A03EC. Une solution pour éviter de tester les types de données est d'utiliser "ToString()" lorsque vous remplissez votre objet. Excel reconvertira les chiffres au format numérique de lui-même. FlashTrev a abordé le problème connexe des dates et heures.

0 votes

Je recommande la réponse à cette question : stackoverflow.com/a/536699/1367391

155voto

hmqcnoesy Points 3397

Je recommande ClosedXML -

Vous pouvez transformer une table de données en une feuille de calcul Excel avec quelques très code lisible :

XLWorkbook wb = new XLWorkbook();
DataTable dt = GetDataTableOrWhatever();
wb.Worksheets.Add(dt,"WorksheetName");

Le développeur est réactif et serviable. Le projet est activement développé, et la documentation est superbe.

7 votes

L'ajout de ~ 6 Mo de bibliothèques référencées ne rendrait-il pas l'application un peu lourde ?

6 votes

Bonne question @MicheleVirgilio. Je n'ai pas fait de tests pour quantifier l'impact. Mais pour ce que ça vaut, cela ne m'a jamais gêné dans aucun des projets où je l'ai utilisé, en fait, je ne peux pas dire que je l'ai jamais remarqué.

0 votes

Ce code m'a retourné un excel avec une seule colonne avec la valeur ClosedXML.Excel.XLWorkbook

102voto

Cuong Le Points 29324

Essayez un code simple, pour convertir les DataTable en fichier Excel au format csv :

var lines = new List<string>();

string[] columnNames = dataTable.Columns
    .Cast<DataColumn>()
    .Select(column => column.ColumnName)
    .ToArray();

var header = string.Join(",", columnNames.Select(name => $"\"{name}\""));
lines.Add(header);

var valueLines = dataTable.AsEnumerable()
    .Select(row => string.Join(",", row.ItemArray.Select(val => $"\"{val}\"")));

lines.AddRange(valueLines);

File.WriteAllLines("excel.csv", lines);

Cela va écrire un nouveau fichier excel.csv dans le le répertoire de travail actuel qui est généralement soit l'endroit où se trouve le .exe, soit l'endroit d'où vous le lancez.

1 votes

Quelle excellente réponse, mec. Je n'ai pas la possibilité de donner plus d'un vote positif à ta réponse, sinon j'aurais pu donner encore plus de 100 votes positifs.

2 votes

@Cuong Le - Si la cellule a deux virgules, alors il y aura un problème à "string.Join(",")".

0 votes

@Cuong Le où sera "excel.csv" l'emplacement ?

44voto

tuncalik Points 249

Une option élégante consiste à écrire une méthode d'extension (voir ci-dessous) pour la classe DataTable du cadre .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 de la classe DataTable :

public static class My_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 given
    public static void ExportToExcel(this DataTable tbl, string excelFilePath = null) {
        try {
            if (tbl == null || tbl.Columns.Count == 0)
                throw new Exception("ExportToExcel: Null or empty input table!\n");

            // load excel, and create a new workbook
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();

            // single worksheet
            Excel._Worksheet workSheet = excelApp.ActiveSheet;

            // column headings
            for (var i = 0; i < tbl.Columns.Count; i++) {
                workSheet.Cells[1, i + 1] = tbl.Columns[i].ColumnName;
            }

            // rows
            for (var i = 0; i < tbl.Rows.Count; i++) {
                // to do: format datetime values before printing
                for (var j = 0; j < tbl.Columns.Count; j++) {
                    workSheet.Cells[i + 2, j + 1] = tbl.Rows[i][j];
                }
            }

            // check file path
            if (!string.IsNullOrEmpty(excelFilePath)) {
                try {
                    workSheet.SaveAs(excelFilePath);
                    excelApp.Quit();
                    MessageBox.Show("Excel file saved!");
                }
                catch (Exception ex) {
                    throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
                                        + ex.Message);
                }
            } else { // no file path is given
                excelApp.Visible = true;
            }
        }
        catch (Exception ex) {
            throw new Exception("ExportToExcel: \n" + ex.Message);
        }
    }
}

21 votes

Notez que cela nécessite l'installation d'Excel.

5 votes

ExcelFilePath != null && ExcelFilePath != "" pourrait être !String.IsNullOrEmpty(ExcelFilePath)

2 votes

Autre remarque : Microsoft ne recommande pas d'utiliser Interop sur un serveur support.microsoft.com/fr/us/help/257757/

30voto

Solution basée sur tuncalik (merci pour l'idée) article, mais dans le cas de grandes tables fonctionne beaucoup plus rapidement (et est un peu moins clair).

public static class My_DataTable_Extensions
{
    /// <summary>
    /// Export DataTable to Excel file
    /// </summary>
    /// <param name="DataTable">Source DataTable</param>
    /// <param name="ExcelFilePath">Path to result file name</param>
    public static void ExportToExcel(this System.Data.DataTable DataTable, string ExcelFilePath = null)
    {
        try
        {
            int ColumnsCount;

            if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0)
                throw new Exception("ExportToExcel: Null or empty input table!\n");

            // load excel, and create a new workbook
            Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
            Excel.Workbooks.Add();

            // single worksheet
            Microsoft.Office.Interop.Excel._Worksheet Worksheet = Excel.ActiveSheet;

            object[] Header = new object[ColumnsCount];

            // column headings               
            for (int i = 0; i < ColumnsCount; i++)
                Header[i] = DataTable.Columns[i].ColumnName;

            Microsoft.Office.Interop.Excel.Range HeaderRange = 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;

            // DataCells
            int RowsCount = DataTable.Rows.Count;
            object[,] Cells = new object[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 fielpath
            if (ExcelFilePath != null && ExcelFilePath != "")
            {
                try
                {
                    Worksheet.SaveAs(ExcelFilePath);
                    Excel.Quit();
                    System.Windows.MessageBox.Show("Excel file saved!");
                }
                catch (Exception ex)
                {
                    throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
                        + ex.Message);
                }
            }
            else    // no filepath is given
            {
                Excel.Visible = true;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("ExportToExcel: \n" + ex.Message);
        }
    }
}

0 votes

La réponse de tuncalik m'a pris presque une minute, celle-ci est à 1 seconde si c'est long... En fait, j'ai été surpris.

3 votes

C'est l'échantillon le plus rapide que j'ai essayé, beau travail. J'ai dû utiliser Marshal pour libérer le fichier après. Excel.Quit(); Marshal.FinalReleaseComObject(Worksheet); Marshal.FinalReleaseComObject(HeaderRange); Marshal.FinalReleaseComObject(Excel);

0 votes

Faut-il installer Office ?

15voto

Mayur Borad Points 928

Essayez cette fonction en passant la table de données et le chemin du fichier où vous voulez exporter.

public void CreateCSVFile(ref DataTable dt, string strFilePath)
{            
    try
    {
        // Create the CSV file to which grid data will be exported.
        StreamWriter sw = new StreamWriter(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;
    }
}

2 votes

Notez que cela n'utilisera pas vraiment les cellules du tableau dans le document Excel, mais que tout ce qui concerne chaque ligne sera imprimé dans la première cellule de chaque ligne.

0 votes

@Banshee Non, Excel comprend parfaitement les fichiers CSV.

1 votes

Ça ne fonctionne pas non plus avec mon Excel. Les données de chaque ligne sont dans la première cellule.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X