c# - 在.Net中从Excel导入时的科学记数法




oledb (7)

我有一个C#/ .net作业,从Excel导入数据,然后处理它。 我们的客户端删除文件,我们处理它们(重要的,因为我没有任何控制原始文件)。

我使用OleDb库来填充一个数据集(我讨厌编写这个代码,严重的是,有没有一个.Net开发人员可以编写更多的代码?)。 该文件包含一些数字,如30829300,30071500等...这些列的数据类型是“文本”。

这些数字在我导入数据时转换为科学记数法。 无论如何要防止这种情况发生?

-克里斯


OleDb库通常会在Excel电子表格中混淆数据。 这很大程度上是因为它将所有内容都强制为一个固定类型的列布局,并根据每列中前8个单元格中的值猜测每列的类型。 如果猜测错误,则最终会将数字字符串转换为科学记数法。 布莱什!

为了避免这种情况,最好跳过OleDb并直接自己读取表单。 您可以使用Excel(也是Blech!)的COM接口或者第三方.NET Excel兼容阅读器来完成此操作。 SpreadsheetGear就是这样一个工作得很好的库,它的接口与Excel的COM接口非常相似。


您是否尝试将字段的值转换为(int)或(Int64),因为您正在阅读它?


在Google上查找IMEX = 1连接字符串选项和TypeGuessRows注册表设置。 实际上,由于读者通过查看前几行(默认为8)来推断列数据类型,所以没有简单的方法。 如果行包含所有数字,那么你是不幸的。

我以前使用的一个不幸的解决方法是使用HDR = NO连接字符串选项,并将TypeGuessRows注册表设置值设置为1,这将强制它读取第一行作为有效数据以确定其数据类型,而不是一个头。 这是一个黑客,但它的作品。 代码将第一行(包含标题)作为文本读取,然后相应地设置数据类型。

更改注册表是一个痛苦(并不总是可能的),但我建议之后恢复原来的价值。

如果您的导入数据没有标题行,则另一种选择是预处理该文件并在违规列中的每个数字前面插入一个“字符”。 这导致列数据被视为文本。

所以总而言之,有一堆黑客可以解决这个问题,但没有什么真正的万无一失。


我有这个相同的问题,但能够解决它,而不诉诸于Excel COM接口或第三方软件。 它涉及一点处理开销,但似乎为我工作。

  1. 首先读取数据以获取列名称
  2. 然后用这些列中的每一列创建一个新的DataSet,将它们的每个DataType设置为字符串。
  3. 再次将数据读入这个新的数据集。 瞧 - 科学记数法现在已经消失了,所有的东西都以字符串的形式被读入。

这里有一些代码说明了这一点,作为一个额外的好处,它甚至StyleCopped!

public void ImportSpreadsheet(string path)
{
    string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1";
    string connectionString = string.Format(
        CultureInfo.CurrentCulture,
        "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"{1}\"",
        path,
        extendedProperties);

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        using (OleDbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT * FROM [Worksheet1$]";
            connection.Open();

            using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
            using (DataSet columnDataSet = new DataSet())
            using (DataSet dataSet = new DataSet())
            {
                columnDataSet.Locale = CultureInfo.CurrentCulture;
                adapter.Fill(columnDataSet);

                if (columnDataSet.Tables.Count == 1)
                {
                    var worksheet = columnDataSet.Tables[0];

                    // Now that we have a valid worksheet read in, with column names, we can create a
                    // new DataSet with a table that has preset columns that are all of type string.
                    // This fixes a problem where the OLEDB provider is trying to guess the data types
                    // of the cells and strange data appears, such as scientific notation on some cells.
                    dataSet.Tables.Add("WorksheetData");
                    DataTable tempTable = dataSet.Tables[0];

                    foreach (DataColumn column in worksheet.Columns)
                    {
                        tempTable.Columns.Add(column.ColumnName, typeof(string));
                    }

                    adapter.Fill(dataSet, "WorksheetData");

                    if (dataSet.Tables.Count == 1)
                    {
                        worksheet = dataSet.Tables[0];

                        foreach (var row in worksheet.Rows)
                        {
                            // TODO: Consume some data.
                        }
                    }
                }
            }
        }
    }
}

我搜索了这个状态..这是我的解脱步骤

  • 对于模板excel文件

1格式的Excel颜色作为文本2-写入宏以禁用数字 - >文本转换的错误警告

  Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ErrorCheckingOptions.BackgroundChecking = Ture
End Sub
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.BackgroundChecking = False
End Sub
  • 在代码隐藏

3-在读取要导入的数据时尝试将传入的数据解析到Int64或Int32 ....


解决此问题的一个方法是更改​​您的SELECT语句,而不是SELECT *执行此操作:

"SELECT Format([F1], 'General Number')  From [Sheet1$]"
 -or-
"SELECT Format([F1], \"#####\")  From [Sheet1$]"

但是,如果您的单元格包含超过255个字符,并且出现以下错误,则这样做会炸掉:“多步OLE DB操作生成错误。检查每个OLE DB状态值(如果可用),没有工作完成。

幸运的是我的客户并不关心在这种情况下的错误。

这个网页有很多好东西可以尝试: http : //www.dicks-blog.com/archives/2004/06/03/external-data-mixed-data-types/


使用这个连接字符串:

Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"

与Excel 2010我已经注意到以下。 如果在运行OLEDB SELECT时打开Excel文件,则会获取当前版本的单元格,而不是保存的文件值。 此外,字符串值返回一个很长的数字,十进制值和日期是这样的:

5.0130370071e+012
4.08
36808

如果文件没有打开,那么返回的值是:

5013037007084
£4.08
Monday, October 09, 2000






oledb