我可以从数据源导入 INTO excel 而无需迭代吗?
Posted
技术标签:
【中文标题】我可以从数据源导入 INTO excel 而无需迭代吗?【英文标题】:Can I import INTO excel from a data source without iteration? 【发布时间】:2010-09-20 13:53:50 【问题描述】:目前我有一个应用程序,它从 SQLite 数据库获取信息并将其放入 Excel。但是,我必须获取每个 DataRow,遍历每个项目,并将每个值放入它自己的单元格并确定突出显示。这导致将 9000 条记录文件导出到 Excel 需要 20 分钟。我相信它可以比这更快地完成。我的想法是我可以使用数据源来填充 Excel 范围,然后使用列标题和行号来格式化那些需要格式化的行。但是,当我在网上查看时,无论我似乎键入什么,它总是显示使用 Excel 作为数据库的示例,而不是导入到 Excel 中。除非我忘记了一个关键词或 to。现在,这个功能必须在代码中完成,因为它是更大应用程序的一部分。否则,我只会让 Excel 连接到数据库并自行提取信息。不幸的是,事实并非如此。任何可以帮助我快速加载 Excel 工作表的信息将不胜感激。谢谢。其他信息:必须在代码中从数据库中提取信息的另一个原因是,并非每台加载该信息的计算机都有 Excel在上面。可能会简单地告诉使用该应用程序的人导出数据并将其通过电子邮件发送给他们的主管。安装应用程序包含应用程序生成正确格式所需的 dll。示例代码(当前):
For Each strTemp In strColumns
excelRange = worksheet.Cells(1, nCounter)
excelRange.Select()
excelRange.Value2 = strTemp
excelRange.Interior.Color = System.Drawing.Color.Gray.ToArgb()
excelRange.BorderAround(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThin, Excel.XlColorIndex.xlColorIndexAutomatic, Type.Missing)
nCounter += 1
Next
现在,这只是我正在进行的迭代的示例代码。在我真正处理来自数据库的信息的地方,我正在遍历 dataTable 的 Rows,然后遍历 dataRow 中的项目并执行与上述基本相同的操作;逐个值,选择范围并将值放入单元格中,如果单元格是报表的一部分(不总是灰色),则格式化单元格,然后移动到下一组数据。我想做的是将所有数据放在excel表中(A2:??,不是一行,而是多行),然后遍历报告并格式化每一行。这样一来,我唯一一次遍历所有记录就是每条记录都是报表的一部分。
理想代码
excelRange = worksheet.Cells("A2", "P9000")
excelRange.DataSource = ds 'ds would be a queried dataSet, and I know there is no excelRange.DataSource.
'Iteration code to format cells
更新:
我知道我的示例是用 VB 编写的,但因为我的老板更喜欢 VB,所以我也在尝试编写应用程序的 VB 版本。但是,这是我使用 Recordset 的最终代码。 ConvertToRecordset 函数来自here。
private void CreatePartSheet(Excel.Worksheet excelWorksheet)
_dataFactory.RevertDatabase();
excelWorksheet.Name = "Part Sheet";
string[] strColumns = Constants.strExcelPartHeaders;
CreateSheetHeader(excelWorksheet, strColumns);
System.Drawing.Color clrPink = System.Drawing.Color.FromArgb(203, 192, 255);
System.Drawing.Color clrGreen = System.Drawing.Color.FromArgb(100, 225, 137);
string[] strValuesAndTitles = /*...Column Names...*/;
List<string> lstColumns = strValuesAndTitles.ToList<string>();
System.Data.DataSet ds = _dataFactory.GetDataSet(Queries.strExport);
ADODB.Recordset rs = ConvertToRecordset(ds.Tables[0]);
excelRange = excelWorksheet.get_Range("A2", "ZZ" + rs.RecordCount.ToString());
excelRange.Cells.CopyFromRecordset(rs, rs.RecordCount, rs.Fields.Count);
int nFieldCount = rs.Fields.Count;
for (int nCounter = 0; nCounter < rs.RecordCount; nCounter++)
int nRowCounter = nCounter + 2;
List<ReportRecord> rrPartReports = _lstReports.FindAll(rr => rr.PartID == nCounter).ToList<ReportRecord>();
excelRange = (Excel.Range)excelWorksheet.get_Range("A" + nRowCounter.ToString(), "K" + nRowCounter.ToString());
excelRange.Select();
excelRange.NumberFormat = "@";
if (rrPartReports.Count > 0)
excelRange.Interior.Color = System.Drawing.Color.FromArgb(230, 216, 173).ToArgb(); //Light Blue
foreach (ReportRecord rr in rrPartReports)
if (lstColumns.Contains(rr.Title))
excelRange = (Excel.Range)excelWorksheet.Cells[nRowCounter, lstColumns.IndexOf(rr.Title) + 1];
excelRange.Interior.Color = rr.Description.ToUpper().Contains("TAG") ? clrGreen.ToArgb() : clrPink.ToArgb();
if (rr.Description.ToUpper().Contains("TAG"))
rs.Find("PART_ID=" + (nCounter + 1).ToString(), 0, ADODB.SearchDirectionEnum.adSearchForward, "");
excelRange.AddComment(Environment.UserName + ": " + _dataFactory.GetTaggedPartPrevValue(rs.Fields["POSITION"].Value.ToString(), rr.Title));
if (nRowCounter++ % 500 == 0)
progress.ProgressComplete = ((double)nRowCounter / (double)rs.RecordCount) * (double)100;
Notify();
rs.Close();
excelWorksheet.Columns.AutoFit();
progress.Message = "Done Exporting to Excel";
Notify();
_dataFactory.RestoreDatabase();
【问题讨论】:
您目前如何创建 Excel 文档 ActiveX?它是什么版本的 Excel? @Tim Murphy - 我使用的是 Interop dll (Microsoft.Office.Interop.Excel),它的版本是 12 (Office 2007)。 【参考方案1】:你可以使用 ODBC 吗?
''http://www.ch-werner.de/sqliteodbc/
dbName = "c:\docs\test"
scn = "DRIVER=SQLite3 ODBC Driver;Database=" & dbName _
& ";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
Set cn = CreateObject("ADODB.Connection")
cn.Open scn
Set rs = CreateObject("ADODB.Recordset")
rs.Open "select * from test", cn
Worksheets("Sheet3").Cells(2, 1).CopyFromRecordset rs
顺便说一句,Excel 对 html 和内部样式表非常满意。
【讨论】:
该死,我没有深入了解 CopyFromRecrodset。不幸的是,关于样式表,1)我对它们不太熟悉,2)我不确定在创建文件时如何应用。 CSS 是否必须与 Excel 文件一起发送?如果是这样,可能不是最好的主意。 一般的想法是您构建 HTML 文档,其中包含 我选择了这个作为答案,因为它首先得到了回答。我将更新帖子以显示我使用的代码。【参考方案2】:我过去曾使用 Excel XML 文件格式直接写入输出文件或流。它可能不适合您的应用程序,但编写 XML 速度要快得多,并且可以绕过与 Excel 应用程序交互的开销。看看这个Introduction to Excel XML 帖子。
更新: 还有一些库(免费和商业)可以使创建 excel 文档更容易,例如 excellibrary 尚不支持新格式。 Create Excel (.XLS and .XLSX) file from C#的回答中还有提到
【讨论】:
我也做过类似的事情,但这仍然需要迭代每个值,因为我必须设置值然后格式化它。本质上,我知道没有excelRange.DataSource
,但我希望我能做到:excelRange = worksheet.Cells("A1", "P9000") excelRange.DataSource = ds 'ds being a queried dataSet
然后我只需要遍历报告来格式化文件。
非常好。我想我可能不得不结合使用这个和互操作,但我还不确定。我对 Parts 表做了一个简单的导出,用时不到 2 秒,但我必须看看添加工作表等。谢谢。我今天完成后可能会将其标记为答案。【参考方案3】:
Excel 可以使用 CopyFromRecordset 方法在单个操作中写入 ADO 或 DAO 记录集中的所有数据。
代码sn-p:
Sheets("Sheet1").Range("A1").CopyFromRecordset rst
【讨论】:
【参考方案4】:我通常建议使用 Excel 从 SQLite 中提取数据。使用 Excel 的“其他数据源”。然后您可以选择您的 OLE DB 提供程序,使用连接字符串 what-have-you.
不过,您的代码的真正价值听起来是格式化单元格,而不是数据传输。
也许将流程重构为:
让 Excel 导入数据 使用您的代码打开 Excel 电子表格并应用格式我不确定这是否适合您,但也许需要考虑?
【讨论】:
阅读您的回答后,我意识到我忘了说明为什么我不能从 Excel 中做到这一点。不过感谢您的回答。【参考方案5】:试试这个:
http://office.microsoft.com/en-au/excel-help/use-microsoft-query-to-retrieve-external-data-HA010099664.aspx
【讨论】:
不幸的是,这不是我可以在这个项目中使用的东西。不过感谢您的回答。【参考方案6】:也许发布一些代码,我们也许可以找到任何问题。
我会考虑这一系列事件:
在 SQLite 数据库中查询您的数据集。 将数据从 ADO.NET 对象中移出,并移入 POCO 对象中。停止使用 DataTables/Rows。 使用For Each
插入Excel。
【讨论】:
以上是关于我可以从数据源导入 INTO excel 而无需迭代吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中以编程方式从 Excel 文件中大量导入数据到 Access