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

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

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

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

-克里斯

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

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

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

如果您使用Open XML SDK 2.0生产力工具查看实际的.XSLX文件(或者简单地解压文件并在记事本中查看XML),您将看到Excel 2007实际上以科学格式存储原始数据。

例如0.00001被存储为1.0000000000000001E-5

 <x:cr="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并不总是这样造成这个问题。

使用这个连接string:

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

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

 5.0130370071e+012 4.08 36808 

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

 5013037007084 £4.08 Monday, October 09, 2000 

我发现最简单的方法是selectZip格式,而不是文本格式大的“数字”列。

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

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

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

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

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

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

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

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

这里有一些代码说明了这一点,作为一个额外的好处,它甚至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. } } } } } } } 

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

  • 对于模板excel文件

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

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

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

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