2017-08-07 7 views
0

私は、OpenXMLを使ってExcelファイルを読むプログラムを書いています。ファイルには日付も含まれているので、それらを認識する関数が必要です。ここでstackoverflow私はこの解決策を見つけた:How to distinguish inline numbers from OLE Automation date numbers in OpenXML SpreadSheet?NumberingFormatsは常にnullですが、なぜですか?

私は私のコードにそれを適用するためにしようと試みましたが、私は次のエラーを取得するたびに:

「『System.NullReferenceException』種類の未処理の例外がOpenXML_Prova.exe

で発生しました追加情報: オブジェクト参照がオブジェクト インスタンスに設定されていません。"

GetDateTimeCellFormatsの最初の行にあり、NumberingFormatsは常にnullと見えます。

using DocumentFormat.OpenXml; 
using DocumentFormat.OpenXml.Packaging; 
using DocumentFormat.OpenXml.Spreadsheet; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Threading.Tasks; 



namespace OpenXML_Prova 
{ 
    class Program 
    { 

     DocumentFormat.OpenXml.Spreadsheet.NumberingFormats numb = new NumberingFormats(); 

     static uint[] builtInDateTimeNumberFormatIDs = new uint[] { 14, 15, 16, 17, 18, 19, 20, 21, 22, /*27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 45, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58 */}; 
     static Dictionary<uint, NumberingFormat> builtInDateTimeNumberFormats = builtInDateTimeNumberFormatIDs.ToDictionary(id => id, id => new NumberingFormat { NumberFormatId = id }); 
     static Regex dateTimeFormatRegex = new Regex(@"((?=([^[]*\[[^[\]]*\])*([^[]*[ymdhs]+[^\]]*))|.*\[(h|mm|ss)\].*)", RegexOptions.Compiled); 

     static void Main(string[] args) { 
      Program prova = new Program(); 
      prova.ReadFile(); 
     } 

     void ReadFile() 
     { 

      var filePath = @"C:\\Users\\m.p\\Desktop\\report_fatturato_brevissimo.xlsx"; 
      using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false)) 
       { 
        WorkbookPart workbookPart = doc.WorkbookPart; 
        SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First(); 
        SharedStringTable sst = sstpart.SharedStringTable; 

        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); 
        Worksheet sheet = worksheetPart.Worksheet; 

        var cells = sheet.Descendants<Cell>(); 
        var rows = sheet.Descendants<Row>(); 

        Console.WriteLine("Row count = {0}", rows.LongCount()); 
        Console.WriteLine("Cell count = {0}", cells.LongCount()); 

        // Or... via each row 
        foreach (Row row in rows) 
        { 
         foreach (Cell c in row.Elements<Cell>()) 
         { 
          if ((c.DataType != null) && (c.DataType == CellValues.SharedString)) 
          { 
           int ssid = int.Parse(c.CellValue.Text); 
           string str = sst.ChildElements[ssid].InnerText; 
           Console.Write/*Line*/(/*"Shared string {0}: {1}", ssid, */str + "\t"); 
          } 
          else 
          { 
           if (IsDateTimeCell(workbookPart, c) == true) 
           { 
            int ssid = int.Parse(c.CellValue.Text); 
            DateTime date = DateTime.FromOADate(Double.Parse(c.CellValue.Text)); 
            Console.Write/*Line*/(/*"Shared string {0}: {1}", ssid, */date + "\t"); 
           } 
           else if (c.CellValue != null) 
           { 
            Console.Write/*Line*/(/*"Cell contents: {0}", */c.CellValue.Text + "\t"); 
           } 
          } 
         } 
         Console.WriteLine(""); 
        } 
       } 
      } 
      Console.Read(); 
     } 


     public static Dictionary<uint, NumberingFormat> GetDateTimeCellFormats(WorkbookPart wbPart) 
     { 

//Error on the following instruction: NumberingFormats seems to be always null 
      var dateNumberFormats = wbPart.WorkbookStylesPart.Stylesheet.NumberingFormats 
       .Descendants<NumberingFormat>() 
       .Where(nf => dateTimeFormatRegex.Match(nf.FormatCode.Value).Success) 
       .ToDictionary(nf => nf.NumberFormatId.Value); 

      var cellFormats = wbPart.WorkbookStylesPart.Stylesheet.CellFormats 
       .Descendants<CellFormat>(); 

      var dateCellFormats = new Dictionary<uint, NumberingFormat>(); 
      uint styleIndex = 0; 
      foreach (var cellFormat in cellFormats) 
      { 
       if (cellFormat.ApplyNumberFormat != null && cellFormat.ApplyNumberFormat.Value) 
       { 
        if (dateNumberFormats.ContainsKey(cellFormat.NumberFormatId.Value)) 
        { 
         dateCellFormats.Add(styleIndex, dateNumberFormats[cellFormat.NumberFormatId.Value]); 
        } 
        else if (builtInDateTimeNumberFormats.ContainsKey(cellFormat.NumberFormatId.Value)) 
        { 
         dateCellFormats.Add(styleIndex, builtInDateTimeNumberFormats[cellFormat.NumberFormatId.Value]); 
        } 
       } 

       styleIndex++; 
      } 

      return dateCellFormats; 
     } 

     //Usage Example 
     public static bool IsDateTimeCell(WorkbookPart wbPart, Cell cell) 
     { 
      if (cell.StyleIndex == null) 
       return false; 

      var dateTimeCellFormats = GetDateTimeCellFormats(wbPart); 

      return dateTimeCellFormats.ContainsKey(cell.StyleIndex); 
     } 


    } 
} 

答えて

0

OpenXML has 164 built-in formats Excelのスプレッドシートのセルでの基本的なフォーマットのために使用しています。ここでは

は完全なコードです。デフォルトのDateTime形式は、これらの組み込み型の一部です。

Excel(カスタム形式)で新しい形式を作成した場合のみ、StylesheetNumberingFormatsセクションに追加されます。

私はあなたが次にあなたが日時書式を検出するためにいくつかのコードを追加する必要がありますNullReferenceException

if (wbPart.WorkbookStylesPart.Stylesheet.NumberingFormats != null) {

を避けるために、NumberingFormatsをチェックするには、以下のようなあなたのコードをラップ示唆しています。 このSO article triesは、可能な日時スタイルを決定します。より詳細な仕様書への参照については、上記のコメントと最初のリンクを参照してください。

関連する問題