2010-07-22 50 views
6

我無法找到這一個。C#打開Xml SDK 2.0電子表格設置單元日期時間格式

我的情況:

  • SDK 2.0
  • 沒有電子表格模板
  • 下,在VS2010#4.0

我的問題:
在Excel文件我想建立一些數據存在採用DateTime格式。由於我不想只使用字符串(絃樂日期時間無法正確排序),我想將包含DateTime的單元格設置爲我選擇的格式,就像我在Excel中所做的那樣。
據我的理解,我必須使用樣式表來達到這一點。我一直瀏覽網絡一段時間,找到一個對此問題有簡單解釋的人,但似乎很難找到。

我已經在mem中有一個電子表格,可以通過SheetData添加數據。 我唯一缺少的是單元格的格式/樣式。

這是我迄今爲止得到:

DocumentFormat.OpenXml.Packaging.SpreadsheetDocument doc = SpreadsheetDocument.Create("test.xlsx", SpreadsheetDocumentType.Workbook); 

WorkbookPart wbPart = doc.AddWorkbookPart(); 
wbPart.Workbook = new Workbook(); 

SheetData data = new SheetData(
      new Row(...etc)); 

WorksheetPart wsPart = wbPart.AddNewPart<WorksheetPart>(); 
wsPart.Worksheet = new Worksheet(data); 

Sheets sheets = doc.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets()); 

Sheet sheet = new Sheet() { Id = doc.WorkbookPart.GetIdOfPart(wsPart), SheetId = 1, Name = "TestSheet" }; 
sheets.Append(sheet); 

wbPart.Workbook.Save(); 

doc.Close(); 

在何處以及如何我可以添加簡單的補充,如日期時間樣式(例如,「DD-MM-YYYY」),也許更先進的造型以後?

我希望我是在那時我會繼續尋找足夠:) 具體...

THX!

+0

你有沒有工作,這一點建議? – 2011-01-17 14:19:30

+0

您沒有閱讀過Office Open XML規範嗎?它只有6,000頁... :-)當然,我現在正在與類似的「小」問題進行鬥爭。 – 2011-01-18 22:52:30

+1

都能跟得上我從來沒有,我們對此深感抱歉...... 我們決定使用第三方工具,使表:) – 2011-01-27 12:16:00

回答

3

作爲日期格式化數字有很多。

您需要以數字格式開頭。要麼標識與您想要的模式匹配的內置格式,要麼創建一個自定義格式。內置格式爲ECMA-376,第二版,第1部分 - 基礎和標記語言參考section 18.8.30(樣式參考和<numFmt>。如果您需要創建自定義格式,請從ID 164開始並將它們添加到。

doc.WorkbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats 

接下來,你需要有一個指向一個日期格式的單元格的格式你總是需要一個單元格的格式,沒有內置:你styles.xml文件中<numFmts>元素這是SDK訪問。單元格樣式是指numFmtId的數字格式,在<cellXfs>的內部定義在styles.xml內,可以在sdk中作爲:

doc.WorkbookPart.WorkbookStylesPart.Stylesheet.CellStyles 

單元格樣式本身沒有ID。它們由單元格樣式列表中的零索引位置引用。因此,當您創建單元格時,請將其樣式索引設置爲您想要的日期樣式。

對於該值,可以將它們存儲爲ISO 8601格式,但Excel 2010仍使用日期序列格式來存儲其日期。如果您使用除基於1900的日期序列以外的其他任何內容,則需要在工作簿屬性中指定它。

doc.WorkbookPart.Workbook.WorkbookProperties.DateCompatibility 

有用於存儲日期序列值的兩個日期的兼容性設置,也可以是基地1900或1904年基地1900就是Excel 2010中的用途和1904是與舊的Excel的Mac向後兼容性。

基於1900年的日期連續出版物中的數字是自1899年12月31日以來的日子,其中增加了一些複雜因素,您必須將1900年2月29日作爲有效日期處理,儘管技術上1900年不是閏年。

下面是我寫的,從日期序列值轉換爲DateTime的方法。你需要相反的。

/// <summary> 
/// Represents the formula used for converting date serial values stored within the workbook into DateTime instances. 
/// </summary> 
/// <remarks> 
/// Information on date serial conversion is available here: http://www.documentinteropinitiative.com/implnotes/ISO-IEC29500-2008/001.018.017.004.001.000.000.aspx 
/// </remarks> 
public enum XlsxDateCompatibility 
{ 
    /// <summary> 
    /// Standard dates are based on December 30, 1899 and are considered "Standard 1900" dates. 
    /// </summary> 
    StandardBase1900, 

    /// <summary> 
    /// Excel for Windows backwards compatible dates are based on December 31, 1899 are are considered "Backwards compatible 1900" dates. 
    /// </summary> 
    BackwardsCompatibleBase1900, 

    /// <summary> 
    /// Excel for Macintos backwards compatible dates are based on January 1, 1904 and are considered "1904" dates. 
    /// </summary> 
    BackwardsCompatibleBase1904 
} 

    private static readonly IDictionary<XlsxDateCompatibility, DateTime> _dateSerialBaseDates 
     = new Dictionary<XlsxDateCompatibility, DateTime> 
      { 
       {XlsxDateCompatibility.StandardBase1900, new DateTime(1899, 12, 30)}, 
       {XlsxDateCompatibility.BackwardsCompatibleBase1900, new DateTime(1899, 12, 31)}, 
       {XlsxDateCompatibility.BackwardsCompatibleBase1904, new DateTime(1904, 1, 1)} 
      }; 

    public static DateTime DateSerialToDateTime(double dateSerial, XlsxDateCompatibility dateCompatibility) 
    { 

     // special case for dateCompaitility 1900, Excel thinks 1900 is a leap year 
     // http://support.microsoft.com/kb/214019 
     if (dateCompatibility == XlsxDateCompatibility.BackwardsCompatibleBase1900 && dateSerial >= 61.0) 
     { 
      dateSerial -= 1; 
     } 

     DateTime baseDate;   
     if (!_dateSerialBaseDates.TryGetValue(dateCompatibility, out baseDate)) 
     { 
      baseDate = _dateSerialBaseDates[XlsxDateCompatibility.StandardBase1900]; 
     } 
     return baseDate.AddDays(dateSerial); 
    }