数値を日付としてフォーマットすることには多くのことが関係しています。
数値形式から始める必要があります。必要なパターンに一致する組み込みフォーマットを特定するか、カスタムフォーマットを作成します。組み込みフォーマットは、ECMA-376、第2版、パート1-基本およびマークアップ言語リファレンス セクション18.8.30(スタイルおよびのリファレンスです<numFmt>
。カスタムフォーマットを作成する必要がある場合は、ID164から始めてに追加してください。ファイル内の<numFmts>
要素styles.xml
。これは、SDKで次のようにアクセスできます。
doc.WorkbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats
次に、日付形式を参照するセル形式が必要です。常にセル形式が必要です。組み込みの形式はありません。セルスタイルは、によって数値形式を参照し、内部numFmtId
で定義されます。これは、SDKで次のようにアクセスできます。styles.xml
<cellXfs>
doc.WorkbookPart.WorkbookStylesPart.Stylesheet.CellStyles
セルスタイル自体にはIDがありません。それらは、セルスタイルリスト内のゼロインデックス位置によって参照されます。したがって、セルを作成するときは、セルのスタイルインデックスを日付に必要なスタイルに設定します。
値については、 ISO 8601形式で保存できますが、Excel2010では日付シリアル形式を使用して日付を保存します。1900ベースの日付シリアル以外のものを使用する場合は、ブックのプロパティで指定する必要があります。
doc.WorkbookPart.Workbook.WorkbookProperties.DateCompatibility
日付のシリアル値を格納するための2つの日付互換性設定があります。ベース1900またはベース1904です。1900はExcel2010が使用するもので、1904は古いExcelforMacとの下位互換性のためです。
1900年ベースの日付シリアルでは、数値は1899年12月31日以降の日数であり、1900年は技術的にうるう年ではありませんが、1900年2月29日を有効な日付として扱う必要があるという複雑さが加わります。
以下は、日付シリアル値から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);
}