¿Cómo exportar datos de DataGridView de forma instantánea a Excel al hacer clic en el botón?

Tengo 10k filas y 15 columnas en mi vista de cuadrícula de datos. Quiero exportar estos datos a una hoja de Excel o haga clic en el botón. Ya he intentado con el siguiente código.

private void btExport_Click(object sender, EventArgs e) { Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application(); Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing); Microsoft.Office.Interop.Excel._Worksheet worksheet = null; app.Visible = true; worksheet = workbook.Sheets["Sheet1"]; worksheet = workbook.ActiveSheet; for(int i=1;i<dataGridView1.Columns.Count+1;i++) { worksheet.Cells[1, i] = dataGridView1.Columns[i-1].HeaderText; } for (int i=0; i < dataGridView1.Rows.Count-1 ; i++) { for(int j=0;j<dataGridView1.Columns.Count;j++) { if (dataGridView1.Rows[i].Cells[j].Value != null) { worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString(); } else { worksheet.Cells[i + 2, j + 1] = ""; } } } } 

Esto funciona para mí, pero lleva mucho tiempo completar el proceso de exportación.

¿Es posible exportar desde dataGridView (con 10k filas) para excel instantáneamente al hacer clic en un botón?

Aparte de esto, cuando intenté copiar todos los contenidos de DataGridview al tablero de clip y luego pegarlo en la hoja de Excel de forma manual, ocurre casi al instante.

Entonces, ¿hay alguna manera de copiar todas las celdas dataGridView al tablero de clip y pegarlo en la hoja de Excel (con formato de celda) al hacer clic en un botón?

Tengo el código para copiar al portapapeles como se muestra a continuación, pero no sé cómo pegarlo en una nueva hoja de Excel abriéndolo.

  private void copyAllToolStripMenuItem_Click(object sender, EventArgs e) { dataGridView1.SelectAll(); DataObject dataObj = dataGridView1.GetClipboardContent(); if (dataObj != null) Clipboard.SetDataObject(dataObj); } 

Por favor ayuda con un ejemplo. Soy nuevo en C #.

Lo resolví con un simple método de copiar y pegar. No sé si es la mejor manera de hacerlo, pero para mí funciona bien y casi instantáneamente. Aquí está mi código.

  private void copyAlltoClipboard() { dataGridView1.SelectAll(); DataObject dataObj = dataGridView1.GetClipboardContent(); if (dataObj != null) Clipboard.SetDataObject(dataObj); } private void button3_Click_1(object sender, EventArgs e) { copyAlltoClipboard(); Microsoft.Office.Interop.Excel.Application xlexcel; Microsoft.Office.Interop.Excel.Workbook xlWorkBook; Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet; object misValue = System.Reflection.Missing.Value; xlexcel = new Excel.Application(); xlexcel.Visible = true; xlWorkBook = xlexcel.Workbooks.Add(misValue); xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1]; CR.Select(); xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true); } 

Gracias.

Esta es una gran pregunta y me sorprendió lo difícil que fue encontrar una respuesta clara y completa, la mayoría de las respuestas que encontré fueron sudo-code o no estaban 100% completas.

Pude crear una solución completa para copiar y guardar los datos de mi DataGridView en un archivo Excel basado en la respuesta de Jake, así que estoy publicando mi solución completa con la esperanza de que pueda ayudar a otros recién llegados a c # like myself 🙂

En primer lugar, necesitará la referencia Microsoft.Office.Interop.Excel en su proyecto. Vea MSDN sobre cómo agregarlo.

Mi código:

 using Excel = Microsoft.Office.Interop.Excel; private void btnExportToExcel_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Excel Documents (*.xls)|*.xls"; sfd.FileName = "Inventory_Adjustment_Export.xls"; if (sfd.ShowDialog() == DialogResult.OK) { // Copy DataGridView results to clipboard copyAlltoClipboard(); object misValue = System.Reflection.Missing.Value; Excel.Application xlexcel = new Excel.Application(); xlexcel.DisplayAlerts = false; // Without this you will get two confirm overwrite prompts Excel.Workbook xlWorkBook = xlexcel.Workbooks.Add(misValue); Excel.Worksheet xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); // Format column D as text before pasting results, this was required for my data Excel.Range rng = xlWorkSheet.get_Range("D:D").Cells; rng.NumberFormat = "@"; // Paste clipboard results to worksheet range Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1]; CR.Select(); xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true); // For some reason column A is always blank in the worksheet. ¯\_(ツ)_/¯ // Delete blank column A and select cell A1 Excel.Range delRng = xlWorkSheet.get_Range("A:A").Cells; delRng.Delete(Type.Missing); xlWorkSheet.get_Range("A1").Select(); // Save the excel file under the captured location from the SaveFileDialog xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue); xlexcel.DisplayAlerts = true; xlWorkBook.Close(true, misValue, misValue); xlexcel.Quit(); releaseObject(xlWorkSheet); releaseObject(xlWorkBook); releaseObject(xlexcel); // Clear Clipboard and DataGridView selection Clipboard.Clear(); dgvItems.ClearSelection(); // Open the newly saved excel file if (File.Exists(sfd.FileName)) System.Diagnostics.Process.Start(sfd.FileName); } } private void copyAlltoClipboard() { dgvItems.SelectAll(); DataObject dataObj = dgvItems.GetClipboardContent(); if (dataObj != null) Clipboard.SetDataObject(dataObj); } private void releaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; MessageBox.Show("Exception Occurred while releasing object " + ex.ToString()); } finally { GC.Collect(); } } 

No tenía la intención de robar la respuesta de @Jake y @ Cornelius, así que intenté editarla. pero fue rechazado De todos modos, la única mejora que tengo que señalar es evitar una columna en blanco adicional en Excel después de pegar. Agregando una línea dataGridView1.RowHeadersVisible = false; oculta el llamado “Encabezado de fila” que aparece en la parte más a la izquierda de DataGridView, por lo que no se selecciona y se copia al portapapeles cuando se hace dataGridView1.SelectAll();

 private void copyAlltoClipboard() { //to remove the first blank column from datagridview dataGridView1.RowHeadersVisible = false; dataGridView1.SelectAll(); DataObject dataObj = dataGridView1.GetClipboardContent(); if (dataObj != null) Clipboard.SetDataObject(dataObj); } private void button3_Click_1(object sender, EventArgs e) { copyAlltoClipboard(); Microsoft.Office.Interop.Excel.Application xlexcel; Microsoft.Office.Interop.Excel.Workbook xlWorkBook; Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet; object misValue = System.Reflection.Missing.Value; xlexcel = new Excel.Application(); xlexcel.Visible = true; xlWorkBook = xlexcel.Workbooks.Add(misValue); xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1]; CR.Select(); xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true); } 
 using Excel = Microsoft.Office.Interop.Excel; private void btnExportExcel_Click(object sender, EventArgs e) { try { Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; Microsoft.Office.Interop.Excel.Workbook workbook = excel.Workbooks.Add(System.Reflection.Missing.Value); Microsoft.Office.Interop.Excel.Worksheet sheet1 = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets[1]; int StartCol = 1; int StartRow = 1; int j = 0, i = 0; //Write Headers for (j = 0; j < dgvSource.Columns.Count; j++) { Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[StartRow, StartCol + j]; myRange.Value2 = dgvSource.Columns[j].HeaderText; } StartRow++; //Write datagridview content for (i = 0; i < dgvSource.Rows.Count; i++) { for (j = 0; j < dgvSource.Columns.Count; j++) { try { Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[StartRow + i, StartCol + j]; myRange.Value2 = dgvSource[j, i].Value == null ? "" : dgvSource[j, i].Value; } catch { ; } } } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } 

Interop es lento y tiene otros problemas, el uso del portapapeles parece no ser extensible. Aquí hay otras dos maneras de hacer esto

  1. Trabaje con archivos de Excel 2007+ directamente en lugar de trabajar con Excel, será mucho (mucho) más rápido. Puede usar OpenXML ( http://openxmldeveloper.org/ ) que es el SDK de Microsoft. La mejor forma de aprender OpenXML es descargar la herramienta Productivity ( http://www.microsoft.com/en-us/download/details.aspx?id=5124) , toma un archivo existente y genera el código requerido para crearlo. . Otra opción, quizás más simple, es usar ClosedXML ( http://closedxml.codeplex.com/ ). Parece mucho más fácil de usar (mira el ejemplo http://closedxml.codeplex.com/wikipage?title=Showcase&referringTitle=Home ), pero no tengo experiencia con él. Estoy seguro de que hay otras bibliotecas que funcionan bien con Excel.

  2. Trabaja con Excel a través de OLEDB. Esto le permite trabajar con Excel como si fuera una base de datos. Consulte http://www.codeproject.com/Articles/8500/Reading-and-Writing-Excel-using-OLEDB o Performance of OLEDB para leer Excel y obtener más ejemplos.

Comenzaría con ClosedXML.

Lo mejor es el uso de la biblioteca de closedxml.codeplex.com. Recomiéndalo @ https://closedxml.codeplex.com/wikipage?title=Adding%20DataTable%20as%20Worksheet&referringTitle=Documentation

 var wb = new ClosedXML.Excel.XLWorkbook(); DataTable dt = GetTheDataTable();//Refer documentation wb.Worksheets.Add(dt); Response.Clear(); Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; Response.AddHeader("content-disposition", "attachment;filename=\"FileName.xlsx\""); using (var ms = new System.IO.MemoryStream()) { wb.SaveAs(ms); ms.WriteTo(Response.OutputStream); ms.Close(); } Response.End(); 

Me gusta la solución de Jake. El problema sin encabezado se resuelve haciendo lo siguiente

 xlWorkSheet.Cells[1, 1] = "Header 1"; xlWorkSheet.Cells[1, 2] = "Header 2"; xlWorkSheet.Cells[1, 3] = "Header 3"; 

por supuesto, esto solo funciona si sabes cuáles deberían ser los encabezados antes de tiempo.

eso es lo que uso para mi gridview, intente usarlo para los datos de año, funciona perfectamente:

  GridView1.AllowPaging = false; GridView1.DataBind(); StringBuilder sb = new StringBuilder(); for (int k = 0; k < GridView1.Columns.Count; k++) { //add separator sb.Append(GridView1.Columns[k].HeaderText+";"); } //append new line sb.Append("\r\n"); for (int i = 0; i < GridView1.Rows.Count; i++) { for (int k = 0; k < GridView1.Columns.Count; k++) { sb.Append(GridView1.Rows[i].Cells[k].Text+";"); } sb.AppendLine(); } 

Esta respuesta es para la primera pregunta, por qué lleva tanto tiempo y ofrece una solución alternativa para exportar DataGridView a Excel.

MS Office Interop es lento e incluso Microsoft no recomienda el uso de Interop en el lado del servidor y no se puede usar para exportar grandes archivos de Excel. Para obtener más detalles, vea por qué no usar la automatización OLE desde el punto de vista de Microsoft.

Interop guarda los archivos de Excel en formato de archivo XLS (formato de archivo antiguo de Excel 97-2003) y el soporte para Office 2003 ha finalizado. Microsoft Excel lanzó el formato de archivo XLSX con Office 2007 y recomienda el uso de OpenXML SDK en lugar de Interop. Pero los archivos XLSX no son tan rápidos y no manejan muy bien grandes archivos de Excel porque están basados ​​en el formato de archivo XML. Esta es la razón por la cual Microsoft también lanzó el formato de archivo XLSB con Office 2007, formato de archivo recomendado para grandes archivos de Excel. Es un formato binario. Entonces, la mejor y más rápida solución es guardar archivos XLSB.

Puede usar esta biblioteca C # Excel para guardar archivos XLSB, pero también admite formatos de archivo XLS y XLSX.

Consulte el siguiente ejemplo de código como alternativa para exportar DataGridView a Excel:

 // Create a DataSet and add the DataTable of DataGridView DataSet dataSet = new DataSet(); dataSet.Tables.Add((DataTable)dataGridView); //or ((DataTable)dataGridView.DataSource).Copy() to create a copy // Export Excel file ExcelDocument workbook = new ExcelDocument(); workbook.easy_WriteXLSBFile_FromDataSet(filePath, dataSet, new EasyXLS.ExcelAutoFormat(EasyXLS.Constants.Styles.AUTOFORMAT_EASYXLS1), "Sheet1"); 

Si también necesita exportar el formato de DataGridView, consulte este ejemplo de código sobre cómo exportar datagridview a Excel en C # .