2012-08-02 32 views
12

Làm việc với Open XML 2.0 bằng cách sử dụng C# để phân tích các tệp excel lớn. Vấn đề tôi đang chạy vào là các tế bào tôi phân tích cú pháp không có một DataType tôi sau đó kiểm tra NumberFormatId để xác định nếu nó là số thập phân, số hoặc ngày. Tôi đang tìm phạm vi NumberFormatId chính xác cho số/thập phân so với ngày tháng. Họ dường như ở khắp nơi một số số/số thập phân có định dạng 189.212.214.305 và ngày có giá trị 185, 194, 278 vv Có ai biết liệu đặc điểm kỹ thuật có xác định các phạm vi này không?C# Mở XML 2.0 SốFormatId phạm vi

Chỉnh sửa - Thông tin

Dưới đây là một ví dụ về định dạng số 194 từ tập tin bên trong thư mục style.xml xl.

Bảng excel đến từ các vùng khác nhau trên thế giới vì vậy tôi nghĩ các định dạng số khác nhau, nhưng chúng có trùng nhau không? Liệu numFmtId 194 có phải là thứ gì đó không phải là ngày trên các cài đặt văn hóa khác nhau không?

Dưới đây là cách tôi chuyển đổi c.CellValues ​​như "40574" thành ngày, nhưng vấn đề là làm thế nào để tôi biết nếu "40574" là một ngày chứ không phải là một số?

DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text)); 

Hiện tại tôi đang thực hiện việc này bằng cách kiểm tra xem không có DataType nào hơn kiểm tra CellFormat nhưng có một số vấn đề khi NumberFormatId không nằm trong kiểm tra của tôi.

private Object FormatCellValue(Cell c, SharedStringTable ssTable, CellFormats cellFormats) 
      { 
       if (c.CellValue != null) 
       { 
        // If there is no data type, this must be a string that has been formatted as a number 
        if (c.DataType == null) 
        { 
         CellFormat cf; 
         if (c.StyleIndex == null) 
         { 
          cf = cellFormats.Descendants<CellFormat>().ElementAt<CellFormat>(0); 
         } 
         else 
         { 
          cf = cellFormats.Descendants<CellFormat>().ElementAt<CellFormat>(Convert.ToInt32(c.StyleIndex.Value)); 
         } 


         if ((cf.NumberFormatId >= 14 && cf.NumberFormatId <= 22) || 
          (cf.NumberFormatId >= 165 && cf.NumberFormatId <= 180) || 
           cf.NumberFormatId == 278 || cf.NumberFormatId == 185 || cf.NumberFormatId == 196 || 
           cf.NumberFormatId == 217 || cf.NumberFormatId == 326) // Dates 
         { 

          try 
          { 

           DateTime dt; 
           dt = DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text)); 

...CODE CONTINUES 

Sửa

Trong bài cập nhật của tôi, tôi quên gửi giá trị tôi tìm thấy trong các tập tin style.xml:

<numFmt numFmtId="323" formatCode="mmm/yy;@"/> 

Vì vậy, với câu hỏi này của tôi sẽ là làm cách nào để lấy formatCode và phân tích cú pháp nó để xác định xem đó có phải là một ngày không?

Dưới đây là sản phẩm từ các cửa sổ gỡ lỗi trực tiếp của NumberFormat 323

{DocumentFormat.OpenXml.Spreadsheet.CellFormat} 
    base {DocumentFormat.OpenXml.OpenXmlCompositeElement}: {DocumentFormat.OpenXml.Spreadsheet.CellFormat} 
    Alignment: {DocumentFormat.OpenXml.Spreadsheet.Alignment} 
    ApplyAlignment: "1" 
    ApplyBorder: "1" 
    ApplyFill: "1" 
    ApplyFont: "1" 
    ApplyNumberFormat: "1" 
    ApplyProtection: "1" 
    BorderId: "64" 
    ExtensionList: null 
    FillId: "0" 
    FontId: "83" 
    FormatId: "37992" 
    LocalName: "xf" 
    NumberFormatId: "323" 
    PivotButton: null 
    Protection: {DocumentFormat.OpenXml.Spreadsheet.Protection} 
    QuotePrefix: "1" 
+1

Hãy xem trang đó có chứa bảng có giá trị số nguyên và định dạng tương ứng: http://closedxml.codeplex.com/wikipage?title=NumberFormatId%20Lookup%20Table hoặc http://lateral8.com/articles/2010 /6/11/openxml-sdk-20-formatting-excel-values.aspx. –

+0

Bạn có muốn trợ giúp thêm về điều này hoặc các liên kết này đủ để giải quyết vấn đề của bạn không? Nếu vậy, tôi có thể đăng nó như một giải pháp :). Nếu bạn muốn biết thêm thông tin hoặc đang tìm kiếm một thứ gì đó khác, hãy cho tôi biết và tôi sẽ cố gắng giúp đỡ. –

+0

Cần thêm thông tin về điều này. Các liên kết được cung cấp không bao gồm các định dạng tôi đã liệt kê trong câu hỏi của tôi 189,212,214,305 vv. Tôi đang tìm một phạm vi cho tất cả các ngày so với số nguyên/số thập phân hoặc chuỗi. – maguy

Trả lời

23

Danh sách các định dạng ID giá trị

Dưới đây là danh sách các tùy chọn định dạng (source)

ID Format Code 
0 General 
1 0 
2 0.00 
3 #,##0 
4 #,##0.00 
9 0% 
10 0.00% 
11 0.00E+00 
12 # ?/? 
13 # ??/?? 
14 d/m/yyyy 
15 d-mmm-yy 
16 d-mmm 
17 mmm-yy 
18 h:mm tt 
19 h:mm:ss tt 
20 H:mm 
21 H:mm:ss 
22 m/d/yyyy H:mm 
37 #,##0 ;(#,##0) 
38 #,##0 ;[Red](#,##0) 
39 #,##0.00;(#,##0.00) 
40 #,##0.00;[Red](#,##0.00) 
45 mm:ss 
46 [h]:mm:ss 
47 mmss.0 
48 ##0.0E+0 
49 @ 

Hower, danh sách đó chỉ xác định một số định dạng. Theo bài đăng này: Reading dates from OpenXml Excel files, định dạng có giá trị ID nhỏ hơn 164 được tích hợp. Bạn cũng có thể tìm danh sách định dạng dài hơn ở đó.

định dạng Kiểm tra giá trị ID trong file xlsx

Đối với các định dạng với các giá trị ID lớn hơn, bạn có thể tìm định nghĩa của chúng trong tập tin riêng của mình. Để xem chúng, bạn nên mở nó bằng trình duyệt kho lưu trữ zip và tìm các tệp styles.xml trong xl thư mục. Hoặc mở tệp xlsx này bằng Open XML SDK 2.0 Productivity Tools và điều hướng đến nút /xl/styles.xml/x:StyleSheet của tệp đó.

Trong phần đó, bạn sẽ có thể xem các định dạng được xác định trong tài liệu của mình cùng với các giá trị ID được chỉ định cho chúng. Phần với các định dạng sẽ trông giống như thế này:

... 
<x:numFmts count="1"> 
    <x:numFmt numFmtId="166" formatCode="yy/mm/dd;@" /> 
</x:numFmts> 
... 

Nhìn vào các định dạng lưu ở đây, có vẻ như vlaues id có thể được cụ thể cho một xlsx tập tin, vì vậy có lẽ là giá trị ID tương tự có thể được sử dụng để xác định khác nhau định dạng trong hai tệp xlsx khác nhau. Tuy nhiên, đối với các định dạng được tích hợp sẵn, chúng được xác định trước, vì vậy sẽ giống nhau trong tất cả các tệp.

Nếu bạn cần bất kỳ trợ giúp nào trong việc tìm kiếm định dạng này trong tệp của bạn hoặc thông tin bổ sung, hãy cho tôi biết.

EDIT

Bạn cũng có thể tìm thấy một số thông tin thêm về định dạng số trong tài liệu này: http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.numberingformat.aspx.

EDIT II

Bạn có thể sử dụng mã này để có được một cuốn từ điển chứa tất cả các định dạng được định nghĩa trong xlsx file:

private Dictionary<uint, String> BuildFormatMappingsFromXlsx(String fileName) 
{ 
    Dictionary<uint, String> formatMappings = new Dictionary<uint, String>(); 

    using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true)) 
    { 
     var stylePart = document.WorkbookPart.WorkbookStylesPart; 

     var numFormatsParentNodes = stylePart.Stylesheet.ChildElements.OfType<NumberingFormats>(); 

     foreach (var numFormatParentNode in numFormatsParentNodes) 
     { 
      var formatNodes = numFormatParentNode.ChildElements.OfType<NumberingFormat>(); 
      foreach (var formatNode in formatNodes) 
      { 
       formatMappings.Add(formatNode.NumberFormatId.Value, formatNode.FormatCode); 
      } 
     } 
    } 

    return formatMappings; 
} 

Nếu bạn muốn kiểm tra nếu bất kỳ của những là một ngày, tôi giả sử một cách đơn giản sẽ xác minh xem mã định dạng (giá trị trong từ điển được tạo bởi phương pháp tôi đã đăng) có chứa mmyy chất nền.

+1

Hoàn hảo LukasZ M. Điều đó sẽ làm các trick. Thực sự đánh giá cao tất cả công việc bạn đã làm về điều này. – maguy

+0

Không sao, tôi rất vui được trợ giúp :). Cảm ơn bạn đã đánh dấu và upvoting câu trả lời của tôi :). –

+0

Cảm ơn bạn Lukasz. Nó rất hữu ích. Không, tôi có thể nhận dạng loại ngày tháng trong Excel. –