将数字格式化为日期涉及很多内容。
您需要从数字格式开始。识别与您想要的模式匹配的内置格式或创建自定义格式。内置格式在ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference section 18.8.30(样式和<numFmt>
.文件中的<numFmts>
元素styles.xml
。在 SDK 中可以通过以下方式访问:
doc.WorkbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats
接下来,您需要有一个引用日期格式的单元格格式。你总是需要一个单元格格式,没有内置的。单元格样式是指数字格式,numFmtId
并在styles.xml
内部定义<cellXfs>
。这可以在 sdk 中通过以下方式访问:
doc.WorkbookPart.WorkbookStylesPart.Stylesheet.CellStyles
单元格样式本身没有 ID。它们由单元格样式列表中的零索引位置引用。因此,当您创建单元格时,请将它们的样式索引设置为您想要的日期样式。
对于该值,您可以将它们存储为ISO 8601格式,但 Excel 2010 仍使用日期序列格式来存储其日期。如果您使用的不是基于 1900 的日期序列,则需要在工作簿属性中指定它。
doc.WorkbookPart.Workbook.WorkbookProperties.DateCompatibility
存储日期序列值有两种日期兼容性设置,它们可以是基数 1900 或基数 1904。Excel 2010 使用 1900,而 1904 用于向后兼容旧的 Excel for 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);
}