我的数据网格视图中有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行)从按钮点击中立即退出?
除此之外,当我尝试将所有dataGridview内容复制到剪贴板然后手动将其粘贴到Excel工作表时,它几乎立即发生。
那么有没有办法将所有dataGridView单元格复制到剪贴板并在点击按钮时将其粘贴到excel表格(带单元格格式)?
我有如下复制到剪贴板的代码,但我不知道如何通过打开它将其粘贴到新的Excel工作表中。
private void copyAllToolStripMenuItem_Click(object sender, EventArgs e)
{
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
请帮助举个例子。我是C#的新手。
答案 0 :(得分:60)
我通过简单的复制和粘贴方法解决了这个问题。我不知道这是最好的方法,但对我而言,它的效果很好,而且几乎是即时的。这是我的代码。
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);
}
感谢。
答案 1 :(得分:25)
这是一个很好的问题,我很惊讶找到一个清晰而完整的答案是多么困难,我发现的大部分答案都是sudo-code或者不是100%完成。
我能够创建一个完整的解决方案,根据Jake的答案将数据从我的DataGridView复制并保存到excel文件中,所以我发布了我的完整解决方案,希望它可以帮助其他新来者像我一样:)
首先,您需要项目中的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();
}
}
答案 2 :(得分:8)
我不想偷@Jake和@ Cornelius的回答,所以我尝试编辑它。但它被拒绝了。
无论如何,我必须指出的唯一改进是关于在粘贴后避免excel中的额外空白列。添加一行dataGridView1.RowHeadersVisible = false;
会隐藏所谓的&#34;行标题&#34;它显示在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);
}
答案 3 :(得分:7)
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());
}
}
答案 4 :(得分:3)
Interop很慢并且有其他问题,使用剪贴板似乎是不可扩展的。 以下是另外两种方法
直接使用Excel 2007+文件而不是使用Excel,它会更快(更快)。您可以使用Microsoft的SDK OpenXML(http://openxmldeveloper.org/)。学习OpenXML的最佳方法是下载Productivity工具(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包装。
通过OLEDB使用excel。这允许您使用Excel,就好像它是一个dababase。有关示例和详细信息,请参阅http://www.codeproject.com/Articles/8500/Reading-and-Writing-Excel-using-OLEDB或Performance of OLEDB to read Excel。
我从ClosedXML开始。
答案 5 :(得分:3)
Best是使用closedxml.codeplex.com Library.Refer it @ 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();
答案 6 :(得分:2)
我喜欢杰克的解决方案。执行以下操作可解决无标题的问题
xlWorkSheet.Cells[1, 1] = "Header 1";
xlWorkSheet.Cells[1, 2] = "Header 2";
xlWorkSheet.Cells[1, 3] = "Header 3";
当然这只会让你知道标题应该是提前的。
答案 7 :(得分:1)
这就是我用于gridview的内容,尝试将其用于数据,它完美运行:
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();
}
答案 8 :(得分:1)
这个答案是针对第一个问题,为什么需要花费很多时间,它提供了另一种将DataGridView导出到Excel的解决方案。
MS Office Interop很慢,甚至Microsoft也不建议在服务器端使用Interop,也不能用于导出大型Excel文件。有关详细信息,请参阅Microsoft的why not to use OLE Automation。
Interop以XLS文件格式(旧的Excel 97-2003文件格式)保存Excel文件,并且对Office 2003的支持已结束。 Microsoft Excel使用Office 2007发布了XLSX文件格式,并建议使用OpenXML SDK而不是Interop。但是XLSX文件实际上并不是那么快,并且不能很好地处理大型Excel文件,因为它们基于XML文件格式。这就是为什么Microsoft还发布了Office 2007的XLSB文件格式,这是推荐用于大型Excel文件的文件格式。它是二进制格式。因此,最好和最快的解决方案是保存XLSB文件。
您可以使用此C# Excel library来保存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的格式,请查看此代码示例,了解如何export datagridview to Excel in C#。
答案 9 :(得分:0)
此行仅适用于Windows窗体上的DataGridView控件:
...
volumes:
- .:/var/www
- node_modules:/var/www/node_modules
此问题解决了相同的问题,但针对WPF框架的DataGrid控件:
DataObject dataObj = dataGridView1.GetClipboardContent();
答案 10 :(得分:0)
如果您的DataGridView的RightToLeft
设置为Yes
,那么您的数据将反向复制。因此,您应该使用以下代码正确复制数据。
private void copyAlltoClipboard()
{
dgvItems.RightToLeft = RightToLeft.No;
dgvItems.SelectAll();
DataObject dataObj = dgvItems.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
dgvItems.RightToLeft = RightToLeft.Yes;
}
答案 11 :(得分:0)
或者,您可以在不使用Office dll的情况下执行快速导出,因为Excel可以解析csv文件而不会出现问题。
执行以下操作(对于少于65.536行的标题):
user.ts code
var submitData =
{
first_name: formData.firstName,
last_name: formData.lastName,
email: formData.email,
password: formData.password,
address_1: formData.address1,
address_2: formData.address2,}
his.appService.createUser(submitData).subscribe((result: any) => {
if (result != '') {
答案 12 :(得分:0)
我认为这是导出datagridview的最简单且即时的方法。
try
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel Documents (*.xlsx)|*.xlsx";
sfd.FileName = "ProfitLoss.xlsx";
if (sfd.ShowDialog() == DialogResult.OK)
{
DataTable dts = new DataTable();
for (int i = 0; i < grdProfitAndLoss.Columns.Count; i++)
{
dts.Columns.Add(grdProfitAndLoss.Columns[i].Name);
}
for (int j = 0; j < grdProfitAndLoss.Rows.Count; j++)
{
DataRow toInsert = dts.NewRow();
int k = 0;
int inc = 0;
for (k = 0; k < grdProfitAndLoss.Columns.Count; k++)
{
if (grdProfitAndLoss.Columns[k].Visible == false) { continue; }
toInsert[inc] = grdProfitAndLoss.Rows[j].Cells[k].Value;
inc++;
}
dts.Rows.Add(toInsert);
}
dts.AcceptChanges();
ExcelUtlity obj = new ExcelUtlity();
obj.WriteDataTableToExcel(dts, "Profit And Loss", sfd.FileName, "Profit And Loss");
MessageBox.Show("Exported Successfully");
}
}
catch (Exception ex)
{
}
答案 13 :(得分:0)
我添加这个答案是因为,尽管其他方法都比OpenXML DOM更快,并且比COM / Interop更快,更可靠,但其他方法都没有使用OpenXMLWriter,并且因为其他一些方法都使用了剪贴板,我要提醒您注意,因为它的输出不可靠。
详细信息可以在下面的链接中的答案中找到,但是该示例适用于DataTable,但是您可以通过更改行/列循环以引用dgv而不是dt来使其适合使用DataGridView。