Как экспортировать данные dataGridView мгновенно в Excel по нажатию кнопки?
У меня есть 10k строк и 15 столбцов в моем представлении таблицы данных. Я хочу экспортировать эти данные в лист excel o нажмите кнопку. Я уже пробовал с нижеприведенным кодом.
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] = "";
}
}
}
}
Это работает для меня, но требуется много времени, чтобы завершить процесс экспорта.
Можно ли экспортировать из dataGridView (с 10k строк)в excel мгновенно по нажатию кнопки?
Кроме этого, когда я попытался скопировать все содержимое dataGridview в clip board, а затем вставить его чтобы excel лист вручную, это происходит почти мгновенно.
Итак, есть ли способ скопировать все ячейки dataGridView в clip board и вставить их в excel sheet (с форматированием ячеек) одним нажатием кнопки?
У меня есть код для копирования в буфер обмена, как показано ниже, но я не знаю, как вставить его в новый лист excel, открыв его.
private void copyAllToolStripMenuItem_Click(object sender, EventArgs e)
{
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Пожалуйста, помогите с примером. Я новичок в C#.
9 ответов:
Я решил эту проблему простым методом копирования и вставки. Я не знаю, что это лучший способ сделать это, но для меня это работает хорошо и почти мгновенно. Вот мой код.
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); }
Спасибо.
Это отличный вопрос, и я был удивлен тем, как трудно было найти ясный и полный ответ, большинство ответов, которые я нашел, были либо sudo-кодом, либо не на 100% полными.
Я смог создать полное решение для копирования и сохранения данных из моего DataGridView в файл excel на основе ответа Джейка, поэтому я публикую свое полное решение в надежде, что оно может помочь другим новичкам в c#, таким как я:)
Во-первых, вам понадобится ссылка
Microsoft.Office.Interop.Excel
в вашем проект. Смотрите MSDN о том, как его добавить.Мой Код:
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(); } }
Я не намерен воровать ответить @Джейк и @Корнелиуса, поэтому я попробовал его редактировать. но оно было отвергнуто. В любом случае, единственное улучшение, на которое я должен обратить внимание, заключается в том, чтобы избежать дополнительного пустого столбца в excel после вставки. Добавление одной строки
dataGridView1.RowHeadersVisible = false;
скрывает так называемый "заголовок строки", который появляется в левой большей части DataGridView, и поэтому он не выбирается и не копируется в буфер обмена, когда вы делаете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()); } }
Взаимодействие происходит медленно и имеет другие проблемы, использование буфера обмена кажется нерасширяемым. Вот два других способа сделать это
Работа с файлами Excel 2007+ напрямую вместо работы с Excel, это будет намного (намного) быстрее. Вы можете использовать OpenXML (http://openxmldeveloper.org/), который является SDK Microsoft. Лучший способ изучить OpenXML-загрузить средство повышения производительности (http://www.microsoft.com/en-us/download/details.aspx?id=5124) , он принимает существующий файл и генерирует код, необходимый для его создания. Другой, возможно более простой, вариант-использовать ClosedXML (http://closedxml.codeplex.com/). он кажется намного проще в использовании (посмотрите на пример http://closedxml.codeplex.com/wikipage?title=Showcase&referringTitle=Home ), но у меня нет опыта в этом. Я уверен, что есть и другие библиотеки, которые переносят работу с Excel.
Работа с excel через OLEDB. Это позволяет работать с Excel, как будто это дабабаза. Видеть http://www.codeproject.com/Articles/8500/Reading-and-Writing-Excel-using-OLEDB илипроизводительность OLEDB для чтения Excel для примеров и более подробной информации.
Я бы начал с ClosedXML.
Лучше всего использовать использование closedxml.codeplex.com библиотека.Обратитесь к нему @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();
Мне нравится решение Джейка. Проблема без заголовка решается следующим образом
xlWorkSheet.Cells[1, 1] = "Header 1"; xlWorkSheet.Cells[1, 2] = "Header 2"; xlWorkSheet.Cells[1, 3] = "Header 3";
Конечно, это работает только в том случае, если вы знаете, какие заголовки должны быть заранее.
Вот что я использую для своего gridview, попробуйте использовать его для yr-данных , он отлично работает:
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(); }
Это ответ на первый вопрос, почему он занимает так много времени, и он предлагает альтернативное решение для экспорта DataGridView в Excel.
MS Office Interop работает медленно, и даже Microsoft не рекомендует использовать Interop на стороне сервера и не может использоваться для экспорта больших файлов Excel. Подробнее см. В разделе почему бы не использовать OLE Automation С точки зрения Microsoft.
Interop сохраняет файлы Excel в формате XLS (старый формат Excel 97-2003) и поддерживает для офиса 2003 год закончился. Microsoft Excel выпустила XLSX формат файла с Office 2007 и рекомендует использовать OpenXML SDK вместо Interop. Но XLSX-файлы на самом деле не так быстры и не очень хорошо обрабатывают большие файлы Excel, потому что они основаны на формате XML. Вот почему Microsoft также выпустила XLSB формат файла с Office 2007, формат файла, который рекомендуется для больших файлов Excel. Это двоичный формат. Поэтому лучшим и быстрым решением является сохранение XLSB файлов.
Вы можете используйте эту библиотекуC# Excel для сохранения файлов XLSB, но она также поддерживает форматы файлов XLS и XLSX.
Смотрите следующий пример кода в качестве альтернативы экспорта DataGridView в 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");
Если Вам также нужно экспортировать форматирование DataGridView, проверьте этот пример кода о том, как экспортировать datagridview в Excel в C#.