使用EPPlus 3.1.2開啟RDLC匯出的xlsx檔,讀取ExcelPackage.Workbook.Worksheets時發生錯誤:

System.ArgumentNullException: Value cannot be null.
Parameter name: String

既然EPPlus是Open Source,照慣例 -- "Use the Source, Luke!"

追進原始碼,找到案發現場 -- ExcelWorksheet.cs LoadColumns(),爆炸點在xr.GetAttribute(“min”)傳回null,導致int.Parse()出錯。

        private void LoadColumns (XmlTextReader xr)//(string xml)
        {
            var colList = new List<IRangeID>();
            if (ReadUntil(xr, "cols", "sheetData"))
            {
            //if (xml != "")
            //{
                //var xr=new XmlTextReader(new StringReader(xml));
                while(xr.Read())
                {
                    if(xr.LocalName!="col") break;
                    int min = int.Parse(xr.GetAttribute("min"));
 
                    int style;
                    if (xr.GetAttribute("style") == null || 
                        !int.TryParse(xr.GetAttribute("style"), out style))
                    {
                        style = 0;
                    }
                    ExcelColumn col = new ExcelColumn(this, min);
//...略...

追查RDLC匯出xlsx檔中的sheet1.xml,其中<cols><col>結構如下:

  <sheetViews>
    <sheetView workbookViewId="0" showGridLines="0">
    </sheetView>
  </sheetViews>
  <cols>
    <col min="1" max="1" customWidth="1" width="10.3515625">
    </col>
    <col min="2" max="2" customWidth="1" width="78.79296875">
    </col>
  </cols>
  <sheetData>
    <row r="1" ht="17" customHeight="0">

經過一番推敲,錯誤源自<col>與</col>會觸發兩次xr.Read(),第二次讀入</col>時,因屬於EndElement,xr.GetAttribute()讀不到東西,故傳回null。猜想這段寫法平日之所以運作正常,是因為絕大部分xlsx都採用<col min="1" … /> Self-Closing Tag形式,而RDLC匯出xlsx時採取較罕見的<col></col>寫法,踩中地雷而爆炸。(Excel開檔OK,應算EPPlus的Bug)

找到原因,要解決就不是難事,在xr.Read()後,加入一行避開</col>,藥到病除! (當然,也回報到CodePlex囉~)

                while(xr.Read())
                {
                    //2012-12-06 by Jeffrey Lee, to ignore </col> End Element
                    if (xr.NodeType == XmlNodeType.EndElement) continue;
                    if(xr.LocalName!="col") break;

Comments

Be the first to post a comment

Post a comment