none
C#讀取Excel檔時,欄位有值卻會出現string empty的exception RRS feed

  • 一般討論

  • 我使用C#寫了一個可以讀取Excel檔轉成xml檔的程式,但是我發現如果Excel檔的欄位經過複製後貼上,當程式在讀取時就有可能會出現欄位是空值的錯誤,想請問先進是不是在Excel檔複製貼上時,要做什麼處理。
    2011年7月1日 上午 06:20

所有回覆

  • 是否複製貼上的欄位內容尚未被確認(Commit)所引起的?
    2011年7月1日 上午 11:53
  • HI:

    可以詢問一下您讀取Excel的API嗎?

    OLEDB或 Microsoft.Office.Interop.Excel或NPOI?


    Shadow與愉快的程式碼伙伴
    自High文不定期更新XD
    2011年7月1日 下午 05:00
  • 我使用的是OLEDB,謝謝
    2011年7月4日 上午 01:07
  • 不好意思,我試了一下Excel,貼上應該沒有確認的選項,謝謝指教。
    2011年7月4日 上午 01:09
  • 您好

    是否能提供程式與有問題的 Excel 檔案,並且說明錯誤在哪一行

    多提供一些資訊,可能會讓網友比較好了解您的問題


    歡迎參觀我的Blog.NET菜鳥自救會
    2011年7月4日 上午 02:20
    版主
  • 是不是有設定要轉幾行呢?如果程式設定轉5行而已,而匯入的excel確有6行,那可能有這個問題,不如你貼CODE上來看看吧XD
    coding or not
    2011年7月4日 上午 03:00
  • 如果你預期儲存格會有 copy/paste 的欄位,建議你還是用 NPOI 或 Object Model 方式去存取。

    因為在預設的情況下,copy/paste 不一定會填入實值 (ex: 公式),在沒有實值的情況下,OLE DB 根本不知道去哪抓資料,所以才會有空值的現象。


    小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
    雲端學堂Facebook: http://www.facebook.com/pages/StudyAzurecom-yun-duan-xue-tang/155855707799579
    2011年7月4日 上午 03:22
    版主
  • Hi:

    把IMEX設為1,如果您是逐列讀取資料的話,請用Convert.ToString()做強制轉型

    個人自己試過Excel在Copy-Paste(值、函數)後,程式仍然還是可以讀取到值(或函數算出來的結果)

     

     //1.檔案位置
     private string FileName = "D:\\test.xls";
    
     //2.提供者名稱
     private string ProviderName = "Microsoft.Jet.OLEDB.4.0;";
    
     //3.Excel版本
     private string ExtendedString = "'Excel 8.0;";
    
     //4.第一行是否為標題
     private string Hdr = "Yes;";
    
     //5.IMEX=1 當做文字讀取
     private string IMEX = "1';";
    
    
    
     //=============================================================
    
     private void Form1_Load(object sender, EventArgs e)
    
     {
    
      //連線字串
      string cs =
       "Data Source=" + FileName + ";" +
       "Provider=" + ProviderName +
       "Extended Properties=" + ExtendedString +
       "HDR=" + Hdr +
       "IMEX=" + IMEX;
    
    
    
      DataTable dt = new DataTable();
      dt.Columns.Add("Column1");
    
      
    
      using (OleDbConnection cn = new OleDbConnection(cs))
      {
      cn.Open();
      try
      {
       using (OleDbCommand cmd = new OleDbCommand("SELECT * from [" + "Sheet1" + "$]", cn))
       {
       //資料繫結方式
       //OleDbDataReader reader = cmd.ExecuteReader();
       //dt.Load(reader);
    
    
    
       //一列一列讀取方式
       OleDbDataReader reader = cmd.ExecuteReader();
       while (reader.Read())
       {
        DataRow row = dt.NewRow();
        dt.Rows.Add(Convert.ToString(reader[0]));//用Convert.ToString()強制轉型
       }
       reader.Close();
    
       }
    
    
      }
    
      catch (Exception ex)
      {
       MessageBox.Show(ex.Message);
      }
    
    
    
      }
    
      //最後呈現
      dataGridView1.DataSource = dt;
    
     }
    

     

     

     

    不知道以下這篇會不會跟你的問題有關?

    http://sanchen.blogspot.com/2007/08/imex1-oledb-excel-null.html



    在機碼 HKLM\Software\Microsoft\Jet\4.0\Engines\Excel 有一個 TypeGuessRows 值, 預設是 8, 表示會先讀取前 8 列來決定每一個欄位的型態, 所以如果前 8 列的資料都是數字, 到了第 9 列以後出現的文字資料都會變成 null, 要解決這個問題, 只要把 TypeGuessRows 機碼值改成 0,


    Shadow與愉快的程式碼伙伴
    自High文不定期更新XD

    2011年7月4日 上午 09:29
  • hi~

    是否方便貼上你的 code 與大家討論一下呢?  這樣或許會比較快喲~


    逐步學習,逐夢踏實;腳步要踩穩,這樣下一步才不會跌倒。 http://www.dotblogs.com.tw/nobel12
    2011年7月4日 下午 01:40
  • 各位先進,這是小弟的code,請各位不吝給予指教,謝謝。   

    錯誤就是在標示為粗體的那一行,在後來檢查是否為空值時會true,但明明excel那一筆資料卻是有值的(經複製貼上後)。       

    public bool Init()

                         {

                                    string path = Path.GetFullPath(@"building.xls");

                                    if (File.Exists(path))

                                    {

                                               string strCon = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " + path + ";Extended Properties='Excel 8.0;HDR=YES'";

                                               OleDbConnection objConn = new OleDbConnection(strCon);

                                               string strCom = " SELECT * FROM [Sheet1$] ";

                                               objConn.Open();

     

                                               OleDbDataAdapter objCmd = new OleDbDataAdapter(strCom, objConn);

                                               DataSet objDS = new DataSet();

                                               objCmd.Fill(objDS);

                                               objConn.Close();

     

                                               nInfoMax = objDS.Tables[0].Rows.Count;

                                               if (nInfoMax == 0)

                                               {

                                                         return false;

                                               }

                                               int iComSetColumn = 5;

                                               sGateway = objDS.Tables[0].Rows[0][iComSetColumn].ToString().Split(':')[1];

                                               sDNS = objDS.Tables[0].Rows[1][iComSetColumn].ToString().Split(':')[1];

                                               sServerIP = objDS.Tables[0].Rows[2][iComSetColumn].ToString().Split(':')[1];

                                               sWebSite = objDS.Tables[0].Rows[3][iComSetColumn].ToString().Split(':')[1] +":"+ objDS.Tables[0].Rows[3][iComSetColumn].ToString().Split(':')[2];

                                               sTotal = objDS.Tables[0].Rows[4][iComSetColumn].ToString().Split(':')[1];

                                               //sModelName = objDS.Tables[0].Rows[0][7].ToString();     

                                               for (int i = 0; i < nInfoMax; i++)

                                               {

                                                         listBuildingNum.Add(objDS.Tables[0].Rows[i][0].ToString());

                                                         listIP.Add(objDS.Tables[0].Rows[i][2].ToString());

                                                         listLightID.Add(objDS.Tables[0].Rows[i][1].ToString());

                                                         listGateIP.Add(objDS.Tables[0].Rows[i][3].ToString());

                                                         list8318IP.Add(objDS.Tables[0].Rows[i][4].ToString());                             

                                               }

                                               return true;

                                    }

                                    else {

                                               return false;

                                    }

                         }


    2011年7月5日 上午 01:28
  • 小歐您好,我已經貼上我的code,謝不吝給予指教,謝謝。
    2011年7月5日 上午 01:32
  • Shinyo.her您好,我已經貼上我的code,謝不吝給予指教,謝謝。
    2011年7月5日 上午 01:32
  • Nobel12您好,我已經貼上我的code,謝不吝給予指教,謝謝。
    2011年7月5日 上午 01:56
  • 您好

    是否能提供有問題的 Excel 檔案?


    歡迎參觀我的Blog.NET菜鳥自救會
    2011年7月5日 上午 02:01
    版主
  • 我已經把有問題的 Excel 檔案上傳了,網址如下。謝謝。

    http://www.fileserve.com/file/r9uFBys

    2011年7月5日 上午 03:27
  • 看過資料 有效資料只有16筆

    但程式抓到 25筆

    我後來嘗試著把A B C三欄的儲存格的框線格式清除

    再重設實際有資料的儲存格框線格式

    就可以正常抓到 16筆


    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度
    2011年7月5日 上午 06:18
  • 我抓下來看過了~  也是正常....抓到16筆
    逐步學習,逐夢踏實;腳步要踩穩,這樣下一步才不會跌倒。 http://www.dotblogs.com.tw/nobel12
    2011年7月5日 上午 06:58
  • 這個解法我也有發現,只要把空的行刪個約50行後,就不會有問題了。

    但仍希望能避免這個問題的產生。

    2011年7月5日 上午 08:04
  • 目前問題尚未解決,如果有解決的方法,小弟會拿上來跟大家分享,也謝謝您的回覆。
    2011年8月11日 上午 07:55
  • FAQ

    http://social.msdn.microsoft.com/Search/zh-TW/?Refinement=112&query=Excel%20%e5%9e%83%e5%9c%be%e8%a1%8c


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2011年8月11日 下午 01:10
  • 我的印象中

    改用

    Provider = Microsoft.ACE.OLEDB.12.0 ; Data Source = " + path + ";Extended Properties='Excel 12.0;HDR=YES

    應該可以解決

    2011年9月1日 上午 07:08