从.Net中的Excel导入时的科学记数法

时间:2009-01-09 21:40:24

标签: c# .net excel oledb

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

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

导入数据时,这些数字会转换为科学记数法。反正有没有阻止这种情况发生?

-Chris

11 个答案:

答案 0 :(得分:5)

此问题的一个解决方法是更改​​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/

答案 1 :(得分:3)

OleDb库 ,通常会在Excel电子表格中弄乱您的数据。这很大程度上是因为它将所有内容强制为固定类型的列布局,猜测,每列的类型来自每列中前8个单元格中的值。如果它猜错了,你最终会将数字字符串转换为科学符号。布莱什!

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

答案 2 :(得分:3)

使用此连接字符串:

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

答案 3 :(得分:1)

如果您使用Open XML SDK 2.0 Productivity Tool查看实际的.XSLX文件(或者只是解压缩文件并在记事本中查看XML),您将看到Excel 2007实际上以科学格式存储原始数据。

例如,0.00001存储为1.0000000000000001E-5

<x:c r="C18" s="11" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:v>1.0000000000000001E-5</x:v>
</x:c>

在Excel中查看单元格,它在单元格和公式栏中显示为0.00001。所以OleDB导致这个问题并非总是如此。

答案 4 :(得分:0)

我发现最简单的方法是选择Zip格式,而不是大号'数字'列的文本格式。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

在google上查找IMEX = 1连接字符串选项和TypeGuessRows注册表设置。 事实上,没有简单的方法可以解决这个问题,因为读者通过查看前几行(默认为8行)来推断列数据类型。如果行包含所有数字,那么你运气不好。

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

更改注册表很痛苦(并非总是可行),但我建议之后恢复原始值。

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

总而言之,有很多黑客可以解决这个问题,但没有什么是万无一失的。

答案 7 :(得分:0)

我遇到了同样的问题,但是无需借助Excel COM界面或第三方软件就可以解决这个问题。它涉及一些处理开销,但似乎对我有用。

  1. 首先读取数据以获取列名称
  2. 然后使用这些列中的每一列创建一个新的DataSet,将每个DataType设置为字符串。
  3. 再次将数据读入此新内容 数据集。瞧 - 科学 符号现在已经消失,所有内容都以字符串形式读入。
  4. 这里有一些代码说明了这一点,作为一个额外的奖励,它甚至是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.
                            }
                        }
                    }
                }
            }
        }
    }
    

答案 8 :(得分:0)

我用Google搜索了这个状态.. 这是我的解决步骤

  • 对于模板excel文件

1格式Excel coloumn as Text 2-写宏以禁用Number - &gt;的错误警告文本转换

  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 ....

答案 9 :(得分:0)

我有兴趣知道是否有人得到了答案。我一直在互联网上,并尝试了IMEX和HDR的所有组合。 IMEX = 1是唯一一个我设法提取日期,货币和一般数字值的人。但是大数字仍然显示出科学性。我只需要阅读文件和更改电子表格,注册表,第三方不是一个选项。

答案 10 :(得分:0)

我从其他地方得到了一个解决方案,但是对我来说效果很好。 无需更改任何代码,只需将excel列单元格的格式设置为“常规”,而不是其他任何格式(如“数字”或“文本”),则即使从[$ Sheet1]中选择*或从[$ Sheet1]中选择Column_name也会读取即使是9位数以上的大数值也很完美