基本上我需要将一堆数据插入Excel文件。创建OleDB连接似乎是最快的方式,但我已经看到遇到了内存问题。当我执行INSERT查询时,进程使用的内存似乎在不断增长。我把它们缩小到仅当我输出到Excel文件时(内存保持稳定而没有输出到Excel)。我关闭并重新打开每个工作表之间的连接,但这似乎不会影响内存使用(Dispose()也是如此)。数据写成功,因为我可以用相对较小的数据集进行验证。如果有人有洞察力,我们将不胜感激。
在构造函数中调用initializeADOConn()
initADOConnInsertComm()创建插入参数化插入查询
每当写入新记录时,都会调用writeRecord()。根据需要创建新工作表。
public bool initializeADOConn()
{
/* Set up the connection string and connect.*/
string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + this.destination + ";Extended Properties=\"Excel 8.0;HDR=YES;\"";
//DbProviderFactory factory =
//DbProviderFactories.GetFactory("System.Data.OleDb");
conn = new OleDbConnection(connectionString);
conn.ConnectionString = connectionString;
conn.Open();
/* Intialize the insert command. */
initADOConnInsertComm();
return true;
}
public override bool writeRecord(FileListerFileInfo file)
{
/* If all available sheets are full, make a new one. */
if (numWritten % EXCEL_MAX_ROWS == 0)
{
conn.Close();
conn.Open();
createNextSheet();
}
/* Count this record as written. */
numWritten++;
/* Get all of the properties of the FileListerFileInfo record and add
* them to the parameters of the insert query. */
PropertyInfo[] properties = typeof(FileListerFileInfo).GetProperties();
for (int i = 0; i < insertComm.Parameters.Count; i++)
insertComm.Parameters[i].Value = properties[i].GetValue(file, null);
/* Add the record. */
insertComm.ExecuteNonQuery();
return true;
}
编辑:
不,我根本不使用Excel。我故意避免使用Interop.Excel,因为它的性能很差(至少从我的涉猎方面来看)。
答案 0 :(得分:2)
答案是是,您描述的公式 等于错误的时间。
如果你有一个方便的数据库(SQL Server或Access对此很好),你可以将所有插入到数据库表中,然后将表一次性导出到Excel电子表格中。
一般来说,数据库擅长处理大量插入内容,而电子表格则不然。
答案 1 :(得分:1)
以下是一些想法:
目标工作簿是否打开?有一个错误(Memory leak occurs when you query an open Excel worksheet by using ActiveX Data Objects),其中IIRC实际上是Jet的OLE DB提供程序(您正在使用),尽管在上面的文章中未对此进行确认。
无论如何,批量插入似乎是要走的路。
您可以使用相同的Jet OLE DB提供程序来执行此操作:您只需要一行表。你甚至可以在飞行中制作一个。要创建新的Excel工作簿,请使用连接字符串中不存在的xls文件执行CREATE TABLE
DDL,并且提供程序将为您创建工作簿,并使用工作表来表示该表。您已连接到Excel工作簿,因此可以执行此操作:
CREATE TABLE [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
(
x FLOAT
);
(更好的IMO将是制作Jet数据库,即.mdb文件)。
使用INSERT
创建虚拟行:
INSERT INTO [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable (x)
VALUES (0);
然后,仍然使用与目标工作簿的连接,您可以使用类似于以下内容的方法在一次命中中将值的派生表(DT1)创建为INSERT
:
INSERT INTO MyExcelTable (key_col, data_col)
SELECT DT1.key_col, DT1.data_col
FROM (
SELECT 22 AS key_col, 'abc' AS data_col
FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
UNION ALL
SELECT 55 AS key_col, 'xyz' AS data_col
FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
UNION ALL
SELECT 99 AS key_col, 'efg' AS data_col
FROM [EXCEL 8.0;DATABASE=C:\MyFabricatedWorkbook;HDR=YES].OneRowTable
) AS DT1;
答案 2 :(得分:0)
您是否可以找到以批量容量插入的方式,而不是一次写一条记录?我尽量不使用疯狂的DataSet东西,但是有没有办法让你的所有插入首先发生在本地,然后让它们一举上升? 此进程是否在后台打开Excel?这些过程后来会死吗?