我有一个循环DataTable
的函数,并使用Excel File
SpreadSheetLight
将其保存为C#
注意循环DataTable
并保存其Excel File
输出需要时间,具体取决于DataGrid
所拥有的单元格数,行数和列数,或DataTable
所在的位置摘自。
在我的函数中使用BackgroundWorker
之前,该函数正确执行。没有BackgroundWorker
的唯一旁注当然是UI在代码执行时冻结。并且通过利用BackgroundWorker
我知道我可以通过在另一个线程上处理保存功能来消除这种情况。
但在我的函数中应用BackgroundWorker
后,整个保存功能都会中断。它抛出了Object Reference not set to an instance of an Object
,但我调试并跟踪并确保传递的两个变量都包含值,并且不为null。我使用的循环与之前相同,我甚至尝试使用For Loop
。
这是我遇到的一个片段。如您所见,下面的窗口显示cell
和value
变量都包含内容。然后抛出我的空参考。
此外,这是我的功能的完整代码
public void exportSingleDataGridToExcelFile(DataTable dt) {
using(var sfd = new SaveFileDialog()) {
sfd.FileName = string.Format("WIP Monitoring-{0}", DateTime.Now.ToString("MM.dd.yyyy"));
sfd.Filter = "Excel File (*.xlsx)|*.xlsx";
if(sfd.ShowDialog() == DialogResult.OK) {
clb.Enabled = false;
cb.Enabled = false;
btn.Visible = false;
pb.Visible = true;
pb.Value = 50;
using(var excel = new SLDocument()) {
var style = excel.CreateStyle();
style.SetHorizontalAlignment(DocumentFormat.OpenXml.Spreadsheet.HorizontalAlignmentValues.Center);
style.SetVerticalAlignment(DocumentFormat.OpenXml.Spreadsheet.VerticalAlignmentValues.Center);
var bgw = new BackgroundWorker();
bgw.WorkerReportsProgress = true;
bgw.DoWork += (ss, ee) => {
var worker = ss as BackgroundWorker;
var count = (dt.Rows.Count + 1) * dt.Columns.Count;
var steps = (double) count / 100;
var prog = 0.0;
var row = 0;
var col = 0;
//Get Column Headers
foreach(DataColumn dc in dt.Columns) {
var cell = string.Format("{0}1", col.getExCol());
var value = dc.ColumnName;
excel.SetCellValue(cell, value);
excel.AutoFitColumn(string.Format("{0}1", col.getExCol()));
excel.SetCellStyle(string.Format("{0}1", col.getExCol()), style);
prog += steps;
worker.ReportProgress(((int) prog * 100));
col++;
}
col = 0;
//Get Cell Data
foreach(DataRow dr in dt.Rows) {
foreach(DataColumn dc in dt.Columns) {
var cell = string.Format("{0}{1}", col.getExCol(), row);
var value = dr[dc].ToString();
excel.SetCellValue(cell, value);
excel.AutoFitColumn(cell, row);
excel.SetCellStyle(cell, style);
prog += steps;
worker.ReportProgress(((int) prog * 100));
col++;
}
col = 0;
row++;
}
};
bgw.ProgressChanged += (ss, ee) => {
pb.Value = ee.ProgressPercentage / 100;
};
bgw.RunWorkerCompleted += (ss, ee) => {
try {
excel.SaveAs(sfd.FileName);
form.Close();
} catch(Exception ex) {
MessageBox.Show(ex.Message, "Error while saving", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
bgw.RunWorkerAsync();
}
}
}
}
最初,相同的代码在我实现BackgroundWorker
之前就已经有效了。
答案 0 :(得分:2)
当您的后台工作程序执行时,SLDocuemnt
中的excel
实例内的某些内容很可能是null
。
您正在excel
声明中创建using
。这意味着在using
块结束时,excel
将被处置。但是在该块中,您启动了一个使用此excel
变量的后台工作程序。
后台工作程序肯定比using
阻止运行的时间更长,因此当您尝试访问它并执行引发异常的行时,excel
已经被释放。
立即解决方案将不在此处使用using
。但也许最好在背景工作者的方法中实例化excel
变量 ,因为看起来你无论如何都不需要它。
答案 1 :(得分:1)
我非常确定您的excel
变量在读取异常时是Null的变量。不是方法调用中的值。
我怀疑这是由于你的背景工作所致。