2

我正在尝试将数据行从 sql 导出到 excel,但我的插入命令似乎每次都失败。我花了很多时间试图创建这个,但我最终还是碰壁了。

excel 文档是由 IRS 生成的,我们不能大声修改第 16 行以上的任何内容。第 16 行是标题行,下面的所有内容都需要是来自 sql 的数据。标题名称中都有空格,这似乎是我遇到麻烦的地方。

从第 16 行开始,列名称为:参加者名字、参加者姓氏、参加者 PTIN、计划编号、CE 小时奖励计划、完成日期

这就是我试图写到excel的方式

private void GenerateReport()
{
    FileInfo xlsFileInfo = new FileInfo(Server.MapPath(CE_REPORTS_PATH + CE_PTIN_TEMPLATE + EXTENSION));

    string connectionString = String.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes'", xlsFileInfo.FullName);

    //create connection
    OleDbConnection oleDBConnection = new OleDbConnection(connectionString);
    oleDBConnection.Open();

    //create the adapter with the select to get 
    OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$A16:F16]", oleDBConnection);

    // Create the dataset and fill it by using the adapter.
    DataTable dataTable = new DataTable();
    adapter.FillSchema(dataTable, SchemaType.Source);
    adapter.Fill(dataTable);

    string[] colNames = new string[dataTable.Columns.Count];
    string[] colParms = new string[dataTable.Columns.Count];

    for (int i = 0; i < dataTable.Columns.Count; i++)
    {
        colNames[i] = String.Format("[{0}]", dataTable.Columns[i].ColumnName);
        colParms[i] = "?";
    }

    // Create Insert Command
    adapter.InsertCommand = new OleDbCommand(String.Format("INSERT INTO [Sheet1$] ({0}) values ({1})", string.Join(",", colNames), string.Join(",", colParms)), oleDBConnection);

    // Create Paramaters
    for (int i = 0; i < dataTable.Columns.Count; i++)
    {
        OleDbParameter param = new OleDbParameter(String.Format("@[{0}]", dataTable.Columns[i].ColumnName), OleDbType.Char, 255, dataTable.Columns[i].ColumnName);
        adapter.InsertCommand.Parameters.Add(param);
    }

    // create a new row
    DataRow newCERecord = dataTable.NewRow();

    // populate row with test data
    for (int i = 0; i < dataTable.Columns.Count; i++)
    {
        newCERecord[i] = "new Data";
    }
    dataTable.Rows.Add(newCERecord);

    // Call update on the adapter to save all the changes to the dataset
    adapter.Update(dataTable);

    oleDBConnection.Close();     
}

调用 adapter.Update(dataTable) 时发生的错误如下

$exception  {"The INSERT INTO statement contains the following unknown field name: 'Attendee First Name'. Make sure you have typed the name correctly, and try the operation again."}   System.Exception {System.Data.OleDb.OleDbException}

这令人沮丧,因为我直接从 colNames[i] = String.Format("[{0}]", dataTable.Columns[i].ColumnName) 获得的列名中提取每个字段。我发现我需要 [] 来说明列名中的空格,但此时我不确定问题出在哪里。当我查看 excel 文件时,一切对我来说似乎都是正确的。

4

1 回答 1

4

实际上,我为您找到了一篇已完成整个代码的 Microsoft 文章 - 您可以复制和粘贴您最喜欢的任何解决方案。这是链接:

http://support.microsoft.com/kb/306023

CopyRecordset虽然他们确实解释了我提到的那个(使用制表符分隔的文件),但似乎是你最简单的方法。

编辑:为了完整起见,这是我的原始答案。请参阅上面的链接以获取更多详细信息以及可能的更好解决方案。

这不是对您问题的回答,而是对改变您的方法的建议(如果可以的话)。通过 COM 调用添加数据时,Excel 往往非常慢,我假设 OleDB 在内部使用 COM。根据我的经验,将数据输出到 Excel 的最快(同时也是最不痛苦的方法)是生成一个包含所有数据的制表符分隔的文本文件,然后将文件导入 Excel 并使用 COM 互操作在工作表上执行任何格式设置. 当我以这种方式生成 Excel 报告时,我的大多数报告的生成速度比使用 Excel COM 对象模型快近 100 倍。(我不知道这对于 OleDB 调用是否相同,因为我从未将 OleDB 与 Excel 一起使用,但我愿意打赌 OleDB 适配器在内部使用 COM。)

这也可以解决您的嵌入空间问题,因为制表符将是列分隔符。

在您的特定情况下,我会将文本文件导入 Excel 到新工作表中,然后将其复制并粘贴到 IRS 工作表中的正确位置。完成后,可以删除临时工作表。

于 2012-10-09T19:53:37.140 回答