【问题标题】:OleDb not reading all rows from excel file, in spite of using IMEX=1尽管使用了 IMEX=1,但 OleDb 没有从 excel 文件中读取所有行
【发布时间】:2012-11-23 05:28:42
【问题描述】:

我在 C# 中使用 Microsoft.ACE.OLEDB.12.0 驱动程序来读取和写入 excel 文件 (XLS)。 我的读者的扩展属性看起来像:Excel 8.0;HDR=NO;IMEX=1; 而作家看起来像:Excel 8.0;HDR=NO;IMEX=0;

这是场景: 我从一个 excel 文件中读取,比如说 input.xls ,然后创建一个新的 output.xls 文件并使用我的 writer 写入它。 现在我在 MS Excel 中打开文件 output.xls,然后再添加几行。

接下来,我将 output.xls 作为输入提供给我的程序,当我调试时,我发现它只读取最初使用 OleDb 编写的行。它不会读取我添加的任何新行,并且写入器会吐出已读取的行。

这就是 OleDb 的工作方式吗?即,将数据库视为被它锁定,并且不重视外部插入。 或者我如何创建和保存文件有问题吗?

private void Initialize(string fileName, FileType fileType)
    {
        string connectionString = GetConnectionString(fileName, fileType);

        string sheet;
        using (OleDbConnection connection = OpenConnection(connectionString))
        {
            DataTable sheets = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

        }

        tableName = "[ListingDetails]";

        conn = new OleDbConnection();
        conn.ConnectionString = connectionString;
        conn.Open();
        cmd1 = new OleDbCommand();
        cmd1.Connection = conn;
        cmd1.CommandText = string.Format(CultureInfo.InvariantCulture, @"CREATE TABLE {0} {1}", tableName, fieldstring);
        int x = cmd1.ExecuteNonQuery();

    }


public void InsertRow(string[] data)
    {
        StringBuilder fieldString = new StringBuilder();
        fieldString.Append("(");
        foreach (var h in headers)
        {
             fieldString.Append(" ["+h+"], ");
        }
        fieldString.Remove(fieldString.Length - 2, 2);
        fieldString.Append(")");
        StringBuilder dataString = new StringBuilder();
        dataString.Append("('");
        foreach (var d in data)
        {
            if(d!=null)
                dataString.Append(d.Replace("'", "''") + "', '");
            else
                dataString.Append("', '");
        }
        dataString.Remove(dataString.Length - 4, 4);
        dataString.Append("')");
        cmd1.CommandText = string.Format(CultureInfo.InvariantCulture, @"INSERT INTO {0} {1} values {2}", tableName, fieldString, dataString);
        int x = cmd1.ExecuteNonQuery();

    }

为了关闭文件,我只是做一个conn.Close();

我怀疑我在 Initialize() 方法中创建/使用工作表的方式。

附:我看过一个类似的问题,但问题似乎是数据和 IMEX 标志未设置为 1。让我事先告诉你,这不是一个重复的问题。

谢谢

【问题讨论】:

  • 可能与您添加行的方式有关。您确定要在添加文件后保存文件吗?即使您打开了文件,OleDb 检索数据也不会有任何问题。你能显示一些代码吗?
  • 已编辑以包含代码。

标签: c# .net excel oledb


【解决方案1】:

我使用了下面的代码,这实际上是对您的代码的简化,但有一些小的改动。它每次都有效,我什至可以打开 Excel 并在执行代码时观察插入的行。然后,我可以对文件进行编辑,然后在文件仍处于打开状态并且 从未保存更改的情况下将它们加载到数据网格中

private void Initialize(string fileName, string tableName)
{
    string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Mode=ReadWrite;Extended Properties=\"Excel 8.0;HDR=NO\"";
    string fieldstring = "(ID int, Field1 char(255), Field2 char(255))";

    using (OleDbConnection conn = new OleDbConnection(connectionString))
    {
        conn.Open();

        using (OleDbCommand cmd = new OleDbCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = string.Format(CultureInfo.InvariantCulture, @"CREATE TABLE [{0}] {1}", tableName, fieldstring);
            cmd.ExecuteNonQuery();
        }

        conn.Close();
    }
}

public void InsertRow(string fileName, string tableName, string data)
{
    string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Mode=ReadWrite;Extended Properties=\"Excel 8.0;HDR=YES\"";
    string headers = "ID,Field1,Field2";

    using (OleDbConnection conn = new OleDbConnection(connectionString))
    {
        conn.Open();

        using (OleDbCommand cmd = new OleDbCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = string.Format(CultureInfo.InvariantCulture, @"INSERT INTO [{0}$] ({1}) values({2})", tableName, headers, data);
            txtQuery.Text = cmd.CommandText;
            cmd.ExecuteNonQuery();
        }

        conn.Close();
    }
}

创建文件

Initialize("C:\\path\\to\\file\\Test File.xls", "ListingDetails");

插入测试行

for (int i = 0; i < 10; i++)
{
    InsertRow("C:\\path\\to\\file\\Test File.xls", "ListingDetails",
        "'" + i.ToString() + "','test" + (i + 2).ToString() + "','test" + (i + 5).ToString() + "'");
}

我清理了围绕 OleDb 对象的创建和处置的代码。这可能会给您带来问题,我不确定,但这样至少您知道一切都已正常完成。

希望这会有所帮助。

【讨论】:

  • 我在上面试过你的代码。作者工作正常,但我的 OleDb 阅读器现在甚至无法读取一行。早些时候它曾经读取由 OleDb 编写器写入的行,但没有读取使用 Excel 插入的新行,但现在它读取 0 行。另外,您能否对 $ 在表名中的用法有所了解,因为我仍然不确定它的用法。谢谢
  • @Sankarnm 这很奇怪。您能否显示完整的连接字符串以及用于检索数据的 SQL?您是否收到任何错误,或者它只是没有返回任何内容?工作表名称中的“$”是在更新和检索期间寻址工作表所必需的(尽管显然不是在创建过程中)。
  • 好的,我已经解决了。问题是,当我读取文件时,我查询所有工作表,并在执行select * 时使用第一张工作表的名称作为表名。在我的例子中,它返回的工作表名称是ListingDetails,而不是ListingDetails$。通过附加 $ 来修复它。感谢您的投入,Sid。
  • @Sankarnm 没问题。很高兴我能帮助你。如果对您有帮助,请随意投票和/或勾选答案;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多