OLDB讀取excel的數據類型不匹配的解決方案(ZT)

来源:http://www.cnblogs.com/Charles2008/archive/2016/06/13/5581579.html
-Advertisement-
Play Games

1 引言 在應用程式的設計中,經常需要讀取Excel數據或將Excel數據導入轉換到其他數據載體中,例如將Excel數據通過應用程式導入SQL Sever等資料庫中以備使用。筆者在開發“汽車產業鏈ASP協同商務平臺”中遇到了類似需求。某汽車整車生產企業需要將其車輛發車信息發佈到汽車產業鏈平臺上去,其 ...


1 引言 
  在應用程式的設計中,經常需要讀取Excel數據或將Excel數據導入轉換到其他數據載體中,例如將Excel數據通過應用程式導入SQL Sever等資料庫中以備使用。筆者在開發“汽車產業鏈ASP協同商務平臺”中遇到了類似需求。某汽車整車生產企業需要將其車輛發車信息發佈到汽車產業鏈平臺上去,其數據為內部ERP系統生成的Excel數據表,用戶首先將該數據表上傳至汽車產業鏈平臺,平臺將此Excel數據讀取導入到平臺內部的SQL Sever資料庫中,以供其它應用使用。汽車產業鏈平臺的開發使用的開發工具為VS.NET,使用的語言是C#,在開發的過程中發現使用Microsoft.Jet.OLEDB.4.0讀取數據會出現當某一欄位內分別含有文本和數字的混合數據時,某一類型的數據會產生丟失。本文就對此問題產生的根源進行了分析並給出了相應的解決方法。 
2 問題描述 
  Excel是Microsoft公司的電子錶格處理軟體,在現代辦公及企業信息化的應用中使用非常廣泛,正因如此,在程式設計中我們經常要通過訪問Excel文件來獲得數據,但Excel文件不是標準資料庫[1]。 
  ASP.NET也是Microsoft公司的產品,作為.NET FrameWork框架中的一個重要組成部分,其主要用於Web設計。我們在.NET中訪問讀取Excel數據時一般採用Microsoft.Jet.OLEDB.4.0[2]。現以讀取一個Excel文件auto.xls中sheet1工作表為例,工作表的內容如表1所示。 
  表1 sheet1表的數據內容 
  現將該表的數據內容讀取並顯示到到DataGrid中,簡化的代碼如下: 
  String ConnStr = " Provider = Microsoft.Jet.OLEDB.4.0; DataSource=c:/auto.xls;Extended Properties='Excel 8.0;HDR=YES';"; 
  OleDbConnection Conn=new OleDbConnection(ConnStr); 
  Conn.Open(); 
  string SQL="select * from [sheet1$]"; 
  OleDbDataAdapter da=new OleDbDataAdapter(SQL,ConnStr); 
  DataSet ds=new DataSet(); 
  da.Fill(ds); 
  DataGrid1.DataSource=ds; 
  DataGrid1.DataBind(); 
  Conn.Close(); 
  但是運行以上代碼的結果並不是期望的,它將顯示為表2所示的內容。可以發現第一個欄位中為“1042”的兩個數據項變為空。 
  表2 DataGrid1所顯示的數據內容 
  有程式設計人員將以上代碼OleDbConnection連接字元串中的Extended Properties一項作瞭如下改動,Extended Properties='Excel 8.0;HDR=NO;IMEX=1’,認為可以解決此問題。由於在開發“汽車產業鏈協同商務平臺”中碰到過類似問題,作了大量的測試後發現,添加IMEX=1後並未實質上解決此問題。表現為:如果某欄位前8條記錄中全部為純數字的話,那麼在該欄位隨後的記錄中含有字母或漢字的項將仍然變為空,但是如果該欄位前8條記錄中有一條不為純數字,將能得到預期想要的結果。 
   
3 問題分析 
  產生這種問題的根源與Excel ISAM[3](Indexed Sequential Access Method,即索引順序存取方法)驅動程式的限制有關,Excel ISAM 驅動程式通過檢查前幾行中實際值確定一個 Excel 列的類型,然後選擇能夠代表其樣本中大部分值的數據類型[4]。也即Excel ISAM查找某列前幾行(預設情況下是8行),把占多的類型作為其處理類型。例如如果數字占多,那麼其它含有字母等文本的數據項就會置空;相反如果文本居多,純數字的數據項就會被置空。 
  現具體分析在第1節程式代碼Extended Properties項中的HDR和IMEX所代表的含義。HDR用來設置是否將Excel表中第一行作為欄位名,“YES”代表是,“NO”代表不是即也為數據內容;IMEX是用來告訴驅動程式使用Excel文件的模式,其值有0、1、2三種,分別代表導出、導入、混合模式。當我們設置IMEX=1時將強制混合數據轉換為文本,但僅僅這種設置並不可靠,IMEX=1只確保在某列前8行數據至少有一個是文本項的時候才起作用,它只是把查找前8行數據中數據類型占優選擇的行為作了略微的改變。例如某列前8行數據全為純數字,那麼它仍然以數字類型作為該列的數據類型,隨後行里的含有文本的數據仍然變空。 
  另一個改進的措施是IMEX=1與註冊表值TypeGuessRows配合使用,TypeGuessRows 值決定了ISAM 驅動程式從前幾條數據採樣確定數據類型,預設為“8”。可以通過修改“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel”下的該註冊表值來更改採樣行數。但是這種改進還是沒有根本上解決問題,即使我們把IMEX設為“1”, TypeGuessRows設得再大,例如1000,假設數據表有1001行,某列前1000行全為純數字,該列的第1001行又是一個文本,ISAM驅動的這種機制還是讓這列的數據變成空。 
   
4 解決方法 
  從以上的分析中可以得知,當某列數據中含有混合類型時,在.NET中使用Microsoft.Jet.OLEDB.4.0來讀取Excel文件造成數據丟失是不可避免的,要解決這個問題只能考慮採用其它數據讀取方法。 
  在.NET中讀取Excel文件的另外一種方法是回到使用傳統COM組件,這種方法在很多技術文章或論文中都有涉及,本文不作贅述。需要指出的是,使用COM組件來讀取Excel文件數據的效率較低,在作釋放的時候有可能碰到不可預知的錯誤,特別開發Web應用的程式應該慎重使用。 

本文提出另外一種利用讀取CSV純文本格式解決此問題的方法。 
  (1)在讀取Excel的.xls類型的文本數據之前,先將其轉換為.csv格式,在Excel中直接另存為這種格式就可以達到轉換的目的。CSV文件又稱為逗號分隔的文件,是一種純文本文件,它以“,”分隔數據列,本文表1的數據表用CSV格式存儲後用純文本編輯器打開的表現形式如表3所示。 
  表3 採用CSV格式保存的表1數據 
  需要指出的是,CSV文件也可以用Ole DB或ODBC的方式讀取,但是如果採用這些方式讀取其數據又會回到丟失數據的老路上,ISAM機制同樣會發揮作用。 
  (2)採用普通的讀取文本文件的方法打開文件,讀取第一行,用“,”作為分隔符獲得各欄位名,在DataTable中創建對應的各欄位,欄位的類型可以統一創建成“String”。 
   
本文原文 
  (3)逐行讀取數據行, 用“,”作為分隔符獲得某行各列的數據並填入DataTable相應的欄位中。 
  實現的簡化代碼如下: 
  String line; 
  String [] split = null; 
  DataTable table=new DataTable("auto"); 
  DataRow row=null; 
  StreamReader sr=new StreamReader("c:/auto.csv",System.Text.Encoding.Default); 
  //創建與數據源對應的數據列 
  line = sr.ReadLine(); 
  split=line.Split(','); 
  foreach(String colname in split){ 
  table.Columns.Add(colname,System.Type.GetType("System.String")); } 
  //將數據填入數據表 
  int j=0; 
  while((line=sr.ReadLine())!=null){ 
   j=0; 
   row = table.NewRow(); 
   split=line.Split(','); 
   foreach(String colname in split){ 
   row[j]=colname; 
   j++;} 
   table.Rows.Add(row);} 
   sr.Close(); 
  //顯示數據 
  dataGrid1.DataSource=table.DefaultView; 
  dataGrid1.DataBind(); 
   
5 結語 
  在應用程式的設計中,需要訪問Excel數據的情況非常普遍,本文以在.NET中對訪問含有混合類型數據的Excel表格擬採取的方法進行探討。當然,如果不存在混合類型的數據使用Microsoft.Jet.OLEDB為較佳方案。對於不是使用.NET開發的情況,本論文的分析和所提供的方法亦可參考。


OLEDB 連接EXCEL的連接字元串 IMEX的問題

       今天碰到一個問題需要想EXCEL表中寫數據,折騰了好久才發現是IMEX惹得禍,所以記錄下提醒自己,也希望大家不要出同樣的錯。 

碰到問題:使用語句 "insert into [Sheet1$] (大類) values ('test')" 無法插入 。 

原因:Provider=Microsoft.Jet.OLEDB.4.0;Data Source='2008-08.xls'; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1' 

解決方法: 去掉IMEX=1 

補充: 
       向EXCEL插入數據時 數據類型是由前8行數據中數據類型占優選擇 例如:分數一列前前8行為空值 插入5為字元串格式,如果前8行為數字格式 插入5為數字格式關於IMEX的資料: 

       IMEX是用來告訴驅動程式使用Excel文件的模式,其值有0、1、2三種,分別代表導出、導入、混合模式。當我們設置IMEX=1時將強制混合數據轉換為文本,但僅僅這種設置並不可靠,IMEX=1只確保在某列前8行數據至少有一個是文本項的時候才起作用,它只是把查找前8行數據中數據類型占優選擇的行為作了略微的改變。例如某列前8行數據全為純數字,那麼它仍然以數字類型作為該列的數據類型,隨後行里的含有文本的數據仍然變空。 

  另一個改進的措施是IMEX=1與註冊表值TypeGuessRows配合使用,TypeGuessRows 值決定了ISAM 驅動程式從前幾條數據採樣確定數據類型,預設為“8”。可以通過修改“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft \Jet\4.0\Engines\Excel”下的該註冊表值來更改採樣行數。但是這種改進還是沒有根本上解決問題,即使我們把IMEX設為“1”, TypeGuessRows設得再大,例如1000,假設數據表有1001行,某列前1000行全為純數字,該列的第1001行又是一個文本,ISAM驅動的這種機制還是讓這列的數據變成空。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄: 支持操作系統 IIS配置 安裝。 網路核心Windows伺服器托管包 部署應用程式 在IIS配置網站 創建一個數據保護註冊表項 常見的錯誤 額外的資源 目錄: 支持操作系統 IIS配置 安裝。 網路核心Windows伺服器托管包 部署應用程式 在IIS配置網站 創建一個數據保護註冊表項 常見 ...
  • API: http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 請求prepay_id得 ...
  • 序:在功能性比較強大的後臺管理網站處於各種角度考慮多有應用許可權管理功能。以公司內部管理系統為例,管理員根據不同員工所在不同部門賦予其不同許可權,或者根據上下級隸屬關係實現“金字塔”管理(註:本次所授許可權管理為不可動態編輯模式,即無法進行二級以上許可權分割)。本文內容有不盡不實之處懇請指正。 正文:如下效 ...
  • 本文內容 引入 IHttpModule 概述 創建自定義 HTTP 模塊的步驟 演示創建自定義 HTTP 模塊 HTTP 模塊的工作方式 HTTP 模塊與 Global.asax 文件 參考資料 引入 本文在 VS 2008 和 IIS 6 環境下概述如何利用 IHttpModule 自定義 HTT ...
  • 分類:C#、VS2015 創建日期:2016-06-14 教材:十二五國家級規劃教材《C#程式設計及應用教程》(第3版) 一、配套源程式(VS2015版)的運行截圖 VS2015版的配套源程式在一個解決方案中包含了教材中的所有例題、習題、上機練習、綜合設計的全部源程式,運行時,你只需要展開左側對應的... ...
  • CLR規範要求重載操作符重載方法必須是public和static方法 C#要求操作符重載方法至少有一個參數的類型與當前定義的這個方法類型相同 為了減少運行時開銷,編譯器會直接針對基元類型執行運算,並直接生成操作這些類型的實例的中間代碼(IL)指令,所以在Framework標準庫中沒有定義基元類型的操 ...
  • Asp.net MVC 和web api 的action 在獲取從前臺傳入的數據是有很大不同 前臺使用ajax的方式向後臺發起post的請求 Content-Type:application/json 使用以下json對象 在mvc中可以使用這兩種格式的json均能獲取到的user的username ...
  • 1.以管理員身份運行CMD; 2.在CMD里輸入F:\>vs_enterprise.exe /uninstall /force ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...