我已经编写了一些代码,可以将Azure数据库中的数据复制到Excel文件中。这可以在这个问题的最后找到。
问题是当我有一个表的10k行时,填充excel表需要永远。显然,这对于Excel来说并不理想,但在这一点上它必须以这种方式完成。我想知道是否有更快的方法对此进行编码。 当然,创建Excel工作表是瓶颈,因为C#会在几秒钟内抓取数据集。如果我进入Excel并查看数据,然后右键单击并使用标题进行复制并将其粘贴到Excel表格中,它也会在几秒钟内完成。
我可以通过编程方式执行此操作吗?
private void createExcelFile()
{
string fileName = "FvGReport.xlsx";
string filePath = HttpContext.Current.Request.MapPath("~/App_Data/" + fileName); //check www.dotnetperls.com/mappath
string sqlQuery = "";
List<string> sheetNames = new List<string>();
foreach (ListItem item in ddlSummary_Supplier.Items)
{
string sqlSummary = "SELECT * FROM FvGSummaryAll WHERE Supplier_Code = '" + item.Text + "'; ";
sqlQuery = sqlQuery + sqlSummary;
sheetNames.Add("Summary " + item.Text);
string sqlPaymentsSummary = "SELECT * FROM FvGSummaryPayment WHERE Supplier_Code = '" + item.Text + "'; ";
sqlQuery = sqlQuery + sqlPaymentsSummary;
sheetNames.Add("PaymentSummary " + item.Text);
}
DataSet dataSet = new DataSet();
//string sqlQuery = @"SELECT * FROM FvGData WHERE Supplier_Code = 'SFF Pacific'; SELECT * FROM FvGSummaryPayment";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(sqlQuery, connection);
adapter.Fill(dataSet);
}
//this reference conflicts with System.Data as both have DataTable. So defining it here.
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelWorkBook = null;
Microsoft.Office.Interop.Excel.Worksheet excelWorkSheet = null;
ExcelApp.Visible = true;
excelWorkBook = ExcelApp.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
//excel rows start at 1 not 0
try
{
for (int i = 1; i < dataSet.Tables.Count; i++)
{
excelWorkBook.Worksheets.Add(); //Adds new sheet in Excel WorkBook
}
for (int i = 0; i < dataSet.Tables.Count; i++)
{
int dsRow = 1;
excelWorkSheet = excelWorkBook.Worksheets[i + 1];
//Writing Columns Name in Excel Sheet
for (int col = 1; col < dataSet.Tables[i].Columns.Count; col++)
{
excelWorkSheet.Cells[dsRow, col] = dataSet.Tables[i].Columns[col - 1].ColumnName;
}
dsRow++;
for (int xlRow = 0; xlRow < dataSet.Tables[i].Rows.Count; xlRow++)
{
//Excel row and col positions for writing row = 1, col = 1
for (int col = 1; col < dataSet.Tables[i].Columns.Count; col++)
{
excelWorkSheet.Cells[dsRow, col] = dataSet.Tables[i].Rows[xlRow][col - 1].ToString();
}
dsRow++;
}
excelWorkSheet.Name = sheetNames[i]; //Renaming ExcelSheets
}
excelWorkBook.SaveAs(filePath);
excelWorkBook.Close();
ExcelApp.Quit();
Marshal.ReleaseComObject(excelWorkSheet);
Marshal.ReleaseComObject(excelWorkBook);
Marshal.ReleaseComObject(ExcelApp);
}
catch (Exception ex)
{
lblNoData.Text = ex.ToString();
}
finally
{
foreach (Process process in Process.GetProcessesByName("Excel"))
{
process.Kill();
}
}
downloadExcel(filePath, fileName);
}
答案 0 :(得分:0)
根据我的经验,看起来你正在使用Office Automation,这在这类事情上通常很慢。我建议将输出保存为分隔文件(.csv)并使用自动化用Excel打开该文件(或文件),然后将其另存为电子表格。
答案 1 :(得分:0)
我建议你尝试使用一些ETL工具,特别是如果你不时再这样做的话。例如,如果您使用Talend,那么您将连接到数据库,并且架构将自行提取。获取SQL输入组件并将其连接到Excel组件,您就完成了。大约需要5分钟,没有一行代码
答案 2 :(得分:0)
我不确定你的意思永远&#39;但是为了比较我有一个过程,写一个46,124行的OpenXML电子表格,每行约500个字符,不到17秒。这是由C#进程生成的,该进程位于与数据库服务器相同的托管设施的单独服务器上。
如果可以选择写入CSV,那么这将是性能最佳的解决方案。 OpenXML将为您提供下一个最佳性能,我发现以下文章在我尝试整理过程时最有帮助:
Read-and-Write-Microsoft-Excel-with-Open-XML-SDK
关于内存 - 您需要将两件事放入内存,传入数据和传出文件。无论您撰写的文件类型是什么,您都希望使用SqlDataReader
代替dataSet
。这意味着您的传入数据在内存中一次只能有一行(而不是全部10K)。在编写文件(CSV或OpenXML)时,如果直接写入磁盘(FileStream)而不是内存(MemoryStream),那么你只需要在内存中占用一点点。
特别是如果您运行的是在您的网站中运行的代码,您不希望一次性使用大量内存,因为.NET / IIS无法很好地处理这些内存。