【问题标题】:Why is first empty line ignored in Excel import with OleDb为什么使用 OleDb 导入 Excel 时忽略第一个空行
【发布时间】:2012-04-04 11:59:31
【问题描述】:

使用 .Net 的 OleDb,我尝试导入一个 Excel 表,其中第一行可以为空。我想保留 DataTable 中的空行,以便以后能够将单元格映射到 Excel 样式的单元格名称“A1,A2,...”。但无论我做什么,第一行都被删除了。

Excel 文件如下所示:

 -   -   -
 ABC XY  ZZ
 1   2   3
 4   4   5

其中“-”是一个空单元格。 (我对导入格式没有影响。)

简化代码:

        string cnnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"file.xls\";Extended Properties=\"Excel 8.0;HDR=No;IMEX=1\"";
        string mySheet = "Sheet1$";

        OleDbConnection connection = new OleDbConnection(cnnStr);
        DataSet Contents = new DataSet();
        using (OleDbDataAdapter adapter = new OleDbDataAdapter("select * from [" + mySheet + "]", connection))
        {
            adapter.Fill(Contents);
        }

        Console.WriteLine(Contents.Tables[0].Rows.Count); // prints: 3
        Console.WriteLine(Contents.Tables[0].Rows[0].ItemArray[0]); // prints: ABC

知道如何保留该空行吗?

ps:我找到了How to count empty rows when reading from Excel,但无法重现。

【问题讨论】:

  • 如果第二行是您的实际标题行,为什么需要保留空行?否则,如果它是您需要保留的一致特征,您能否不简单地在转换中插入一个空行?
  • 正如我所说,我想将单元格映射到 Excel 样式的单元格名称(A1、B2 等)。更具体地说:如果 Excel 包含不需要的值或未知的标题名称,我想告诉用户“单元格 A2 中的值不正确”。目前,如果不存在空行,则此方法有效。对于空行,编号会移动。
  • 我现在也有同样的问题。你解决了吗?
  • @RossBrigoli:不,我没有。

标签: c# .net excel oledb


【解决方案1】:

该问题似乎与 OLEDB 提供程序的 TypeGuessRows 功能有关。简而言之,Excel 列中的数据可以是任何类型。 OLEDB 提供程序通过扫描工作表的前 8 行来猜测数据类型以确定多数类型 - 样本中值最多的数据类型。任何不属于多数类型的东西都会被丢弃。

See this blog post for a more detailed explanation.

以及讨论该行为的 MS KB Article

(跳至 TypeGuessRows 行为的解决方法部分)

作为测试,我创建了一个类似于您发布的示例的文件,但将所有列格式化为文本并保存了该文件。运行您发布的代码,我可以看到返回了 4 行,第一行是空字符串。

您可能还想尝试修改注册表以查看将 TypeGuessRows 设置更改为 0(扫描文件中的所有数据以确定每列的数据类型)是否有助于返回第一个空白行。我的预感是这无济于事。

【讨论】:

  • 我知道这一点,但似乎不相关:我不处理 8+ 行,效果与文本/数字相同,注册表值不会改变任何东西(已测试)。 “将所有列格式化为文本”会包含第一行,因为对第一行单元格之一的任何格式更改都被视为“内容”(在富文本中)。更改第一行中一个单元格的背景颜色具有相同的效果。适配器似乎只需要一个完全未触及的未格式化的空第一行(当您刚从第二行开始时就是这种情况)。 :(
【解决方案2】:

OleDbDataAdapter 将第一行视为标题。 为了获得第一行,从数据表的标题创建一个数据行。 并在第一个位置插入。

  DataTable dt = Contents.Tables[0];

  DataRow dr = new DataRow();
  int i = 0;
  foreach (DataColumn column in dt.Columns)
  {
    dr[i] = column.ColumnName.ToString();
    i++;
  }
  dt.Rows.InsertAt(dr, 0);

【讨论】:

  • 我相信这不是真的。当第一行包含任何单元格中的任何值时,它将作为 DataTable 的一部分返回,例如行数为 4。在我的情况下,ColumnName 还包含 F1、F2、F3、... - 请注意,connStr 包含 HDR=No,但是将其设置为 yes 具有相同的效果:忽略第一行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-15
相关资源
最近更新 更多