如何将日期插入 Open XML 工作表?

发布于 2024-08-31 13:32:16 字数 354 浏览 5 评论 0原文

我正在使用 Microsoft Open XML SDK 2,但在将日期插入单元格时遇到了很大的困难。通过设置 Cell.DataType = CellValues.Number,我可以毫无问题地插入数字,但是当我对日期 (Cell.DataType = CellValues.Date) 执行相同操作时,Excel 2010 年崩溃(2007 年也是如此)。

我尝试将 Cell.Text 值设置为多种日期格式以及 Excel 的日期/数字格式,但无济于事。我还尝试使用样式,删除类型属性,加上我扔在墙上的许多其他披萨......

任何人都可以给我指出一个将日期插入工作表的示例吗?

I'm using Microsoft Open XML SDK 2 and I'm having a really hard time inserting a date into a cell. I can insert numbers without a problem by setting Cell.DataType = CellValues.Number, but when I do the same with a date (Cell.DataType = CellValues.Date) Excel 2010 crashes (2007 too).

I tried setting the Cell.Text value to many date formats as well as Excel's date/numeric format to no avail. I also tried to use styles, removing the type attribute, plus many other pizzas I threw at the wall…

Can anyone point me to an example inserting a date to a worksheet?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

提赋 2024-09-07 13:32:16

我使用了 Andrew J 提供的代码,但是 DataType CellValues.Date 为我生成了一个损坏的 xlsx 文件。

DataType CellValues.Number 对我来说效果很好(不要忘记设置NumberFormatId

cell.DataType = new EnumValue<CellValues>(CellValues.Number);

我的整个代码:

DateTime valueDate = DateTime.Now;
string valueString = valueDate.ToOADate().ToString();
CellValue cellValue = new CellValue(valueString);

Cell cell = new Cell();
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.StyleIndex = yourStyle; //StyleIndex of CellFormat cfBaseDate -> See below
cell.Append(cellValue);

样式表中此单元格的 CellFormat 如下所示:

CellFormat cfBaseDate = new CellFormat() { 
 ApplyNumberFormat = true,
 NumberFormatId = 14, //14 is a localized short Date (d/m/yyyy) -> See list below
 //Some further styling parameters
}; 

如果您想以其他方式设置日期格式,这里是所有默认 Excel < 的列表code>NumberFormatId's

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  @

列表来源:https: //github.com/ClosedXML/ClosedXML/wiki/NumberFormatId-Lookup-Table

我知道这个列表来自 ClosedXML,但在 OpenXML 中也是一样的。

I used the code provided by Andrew J, but the DataType CellValues.Date produced a corrupted xlsx-file for me.

The DataType CellValues.Number worked fine for me (Don't forget to set NumberFormatId):

cell.DataType = new EnumValue<CellValues>(CellValues.Number);

My whole code:

DateTime valueDate = DateTime.Now;
string valueString = valueDate.ToOADate().ToString();
CellValue cellValue = new CellValue(valueString);

Cell cell = new Cell();
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.StyleIndex = yourStyle; //StyleIndex of CellFormat cfBaseDate -> See below
cell.Append(cellValue);

My CellFormat for this cell in the Stylesheet looks like:

CellFormat cfBaseDate = new CellFormat() { 
 ApplyNumberFormat = true,
 NumberFormatId = 14, //14 is a localized short Date (d/m/yyyy) -> See list below
 //Some further styling parameters
}; 

If you'd like to format your date another way, here is a list of all default Excel NumberFormatId's

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  @

Source of list: https://github.com/ClosedXML/ClosedXML/wiki/NumberFormatId-Lookup-Table

I know this list is from ClosedXML, but it's the same in OpenXML.

童话 2024-09-07 13:32:16

从头开始创建新的 SpreadsheetDocument 时,要使 Date 格式正常工作,必须创建最少的 Stylesheet

关键是这几行:

new CellFormat
{
    NumberFormatId = 14,
    ApplyNumberFormat = true
})

完整的 Stylesheet 类:

using (var spreadSheet = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
{
    // Workbook
    var workbookPart = spreadSheet.AddWorkbookPart();
    workbookPart.Workbook =
        new Workbook(new Sheets(new Sheet { Name = "Sheet1", SheetId = (UInt32Value) 1U, Id = "rId1" }));

    // Add minimal Stylesheet
    var stylesPart = spreadSheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
    stylesPart.Stylesheet = new Stylesheet
    {
        Fonts = new Fonts(new Font()),
        Fills = new Fills(new Fill()),
        Borders = new Borders(new Border()),
        CellStyleFormats = new CellStyleFormats(new CellFormat()),
        CellFormats =
            new CellFormats(
                new CellFormat(),
                new CellFormat
                {
                    NumberFormatId = 14,
                    ApplyNumberFormat = true
                })
    };

    // Continue creating `WorksheetPart`...

添加 Stylesheet 后,可以格式化 DateTime

if (valueType == typeof(DateTime))
{
    DateTime date = (DateTime)value;
    cell.CellValue = new CellValue(date.ToOADate().ToString(CultureInfo.InvariantCulture));

    // "StyleIndex" is "1", because "NumberFormatId=14"
    // is in the 2nd item of `CellFormats` array.
    cell.StyleIndex = 1; 
}

请注意 StyleIndex > 值取决于 CellFormats 数组或 Stylesheet 对象中 CellFormat 项的顺序。在此示例中,NumberFormatId = 14 项位于数组中的第二项。

When creating new SpreadsheetDocument from scratch, for Date formatting to work, minimal Stylesheet has to be created.

Critical are those few lines:

new CellFormat
{
    NumberFormatId = 14,
    ApplyNumberFormat = true
})

Full Stylesheet class:

using (var spreadSheet = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
{
    // Workbook
    var workbookPart = spreadSheet.AddWorkbookPart();
    workbookPart.Workbook =
        new Workbook(new Sheets(new Sheet { Name = "Sheet1", SheetId = (UInt32Value) 1U, Id = "rId1" }));

    // Add minimal Stylesheet
    var stylesPart = spreadSheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
    stylesPart.Stylesheet = new Stylesheet
    {
        Fonts = new Fonts(new Font()),
        Fills = new Fills(new Fill()),
        Borders = new Borders(new Border()),
        CellStyleFormats = new CellStyleFormats(new CellFormat()),
        CellFormats =
            new CellFormats(
                new CellFormat(),
                new CellFormat
                {
                    NumberFormatId = 14,
                    ApplyNumberFormat = true
                })
    };

    // Continue creating `WorksheetPart`...

After Stylesheet is added, DateTime can be formatted:

if (valueType == typeof(DateTime))
{
    DateTime date = (DateTime)value;
    cell.CellValue = new CellValue(date.ToOADate().ToString(CultureInfo.InvariantCulture));

    // "StyleIndex" is "1", because "NumberFormatId=14"
    // is in the 2nd item of `CellFormats` array.
    cell.StyleIndex = 1; 
}

Note that StyleIndex value depends on the order of CellFormat items in the CellFormats array or the Stylesheet object. In this example NumberFormatId = 14 item on the 2nd item in the array.

不醒的梦 2024-09-07 13:32:16

您必须使用函数 ToOADateDateTime 转换为 double 即:

DateTime dtValue = DateTime.Now;
string strValue = dtValue.ToOADate().ToString(CultureInfo.InvariantCulture);

然后将其设置为 CellValue

Cell cell;
cell.DataType = new EnumValue<CellValues>(CellValues.Date);
cell.CellValue = new CellValue(strValue);

请记住使用以下格式设置单元格格式DateTime 格式,否则您将看到 double 值,而不是日期。

You have to convert DateTime to double using function ToOADate i.e.:

DateTime dtValue = DateTime.Now;
string strValue = dtValue.ToOADate().ToString(CultureInfo.InvariantCulture);

then set it as CellValue

Cell cell;
cell.DataType = new EnumValue<CellValues>(CellValues.Date);
cell.CellValue = new CellValue(strValue);

Remember to format cell using DateTime formatting, otherwise you will see double value, not date.

笑忘罢 2024-09-07 13:32:16

在 OpenXml 中存储日期有 2 种方法;通过写入数字(使用 ToOADate)并将 DataType 设置为 Number 或写入 ISO 8601 格式的日期并将 DataType 设置为 Date。请注意,默认的DataTypeNumber,因此如果您选择第一个选项,则不必设置DataType

无论选择哪种方法,都需要设置样式,因为 Excel 会以相同的方式显示这两种方法。以下代码显示了使用 Number 格式(无论是否显式设置 DataType)并使用 ISO 8601 格式写入日期的示例。

using (SpreadsheetDocument document = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
    //fluff to generate the workbook etc
    WorkbookPart workbookPart = document.AddWorkbookPart();
    workbookPart.Workbook = new Workbook();

    var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
    worksheetPart.Worksheet = new Worksheet();

    Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());

    Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet" };
    sheets.Append(sheet);

    workbookPart.Workbook.Save();

    var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

    //add the style
    Stylesheet styleSheet = new Stylesheet();

    CellFormat cf = new CellFormat();
    cf.NumberFormatId = 14;
    cf.ApplyNumberFormat = true;

    CellFormats cfs = new CellFormats();
    cfs.Append(cf);
    styleSheet.CellFormats = cfs;

    styleSheet.Borders = new Borders();
    styleSheet.Borders.Append(new Border());
    styleSheet.Fills = new Fills();
    styleSheet.Fills.Append(new Fill());
    styleSheet.Fonts = new Fonts();
    styleSheet.Fonts.Append(new Font());

    workbookPart.AddNewPart<WorkbookStylesPart>();
    workbookPart.WorkbookStylesPart.Stylesheet = styleSheet;

    CellStyles css = new CellStyles();
    CellStyle cs = new CellStyle();
    cs.FormatId = 0;
    cs.BuiltinId = 0;
    css.Append(cs);
    css.Count = UInt32Value.FromUInt32((uint)css.ChildElements.Count);
    styleSheet.Append(css);

    Row row = new Row();

    DateTime date = new DateTime(2017, 6, 24);

    /*** Date code here ***/
    //write an OADate with type of Number
    Cell cell1 = new Cell();
    cell1.CellReference = "A1";
    cell1.CellValue = new CellValue(date.ToOADate().ToString());
    cell1.DataType = new EnumValue<CellValues>(CellValues.Number);
    cell1.StyleIndex = 0;
    row.Append(cell1);

    //write an OADate with no type (defaults to Number)
    Cell cell2 = new Cell();
    cell2.CellReference = "B1";
    cell2.CellValue = new CellValue(date.ToOADate().ToString());
    cell1.StyleIndex = 0;
    row.Append(cell2);

    //write an ISO 8601 date with type of Date
    Cell cell3 = new Cell();
    cell3.CellReference = "C1";
    cell3.CellValue = new CellValue(date.ToString("yyyy-MM-dd"));
    cell3.DataType = new EnumValue<CellValues>(CellValues.Date);
    cell1.StyleIndex = 0;
    row.Append(cell3);

    sheetData.AppendChild(row);

    worksheetPart.Worksheet.Save();
}

There are 2 ways to store dates in OpenXml; by writing a number (using ToOADate) and setting the DataType to Number or by writing an ISO 8601 formatted date and setting the DataType to Date. Note that the default DataType is Number so if you go with the first option you don't have to set the DataType.

Whichever method you choose, you'll need to set the style as Excel displays both methods identically. The following code shows an example of writing a date using the Number format (with and without explicitly setting the DataType) and using the ISO 8601 format.

using (SpreadsheetDocument document = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
    //fluff to generate the workbook etc
    WorkbookPart workbookPart = document.AddWorkbookPart();
    workbookPart.Workbook = new Workbook();

    var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
    worksheetPart.Worksheet = new Worksheet();

    Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());

    Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet" };
    sheets.Append(sheet);

    workbookPart.Workbook.Save();

    var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());

    //add the style
    Stylesheet styleSheet = new Stylesheet();

    CellFormat cf = new CellFormat();
    cf.NumberFormatId = 14;
    cf.ApplyNumberFormat = true;

    CellFormats cfs = new CellFormats();
    cfs.Append(cf);
    styleSheet.CellFormats = cfs;

    styleSheet.Borders = new Borders();
    styleSheet.Borders.Append(new Border());
    styleSheet.Fills = new Fills();
    styleSheet.Fills.Append(new Fill());
    styleSheet.Fonts = new Fonts();
    styleSheet.Fonts.Append(new Font());

    workbookPart.AddNewPart<WorkbookStylesPart>();
    workbookPart.WorkbookStylesPart.Stylesheet = styleSheet;

    CellStyles css = new CellStyles();
    CellStyle cs = new CellStyle();
    cs.FormatId = 0;
    cs.BuiltinId = 0;
    css.Append(cs);
    css.Count = UInt32Value.FromUInt32((uint)css.ChildElements.Count);
    styleSheet.Append(css);

    Row row = new Row();

    DateTime date = new DateTime(2017, 6, 24);

    /*** Date code here ***/
    //write an OADate with type of Number
    Cell cell1 = new Cell();
    cell1.CellReference = "A1";
    cell1.CellValue = new CellValue(date.ToOADate().ToString());
    cell1.DataType = new EnumValue<CellValues>(CellValues.Number);
    cell1.StyleIndex = 0;
    row.Append(cell1);

    //write an OADate with no type (defaults to Number)
    Cell cell2 = new Cell();
    cell2.CellReference = "B1";
    cell2.CellValue = new CellValue(date.ToOADate().ToString());
    cell1.StyleIndex = 0;
    row.Append(cell2);

    //write an ISO 8601 date with type of Date
    Cell cell3 = new Cell();
    cell3.CellReference = "C1";
    cell3.CellValue = new CellValue(date.ToString("yyyy-MM-dd"));
    cell3.DataType = new EnumValue<CellValues>(CellValues.Date);
    cell1.StyleIndex = 0;
    row.Append(cell3);

    sheetData.AppendChild(row);

    worksheetPart.Worksheet.Save();
}
桃气十足 2024-09-07 13:32:16

使用共享字符串:

// assuming it's the first item in the shared string table
SharedStringItem sharedStringItem = new SharedStringItem();
Text text = new Text();
text.Text = DateTime.Today.ToString("MM/dd/yyyy hh:mm");
sharedStringTable1.Append(sharedStringItem);

然后在代码中:

// assuming it's the first item in the shared string table
var cell = new Cell {CellReference = "A1", DataType = CellValues.SharedString};
var cellValue = new CellValue("0");
cell.Append(cellValue);

Use Shared String:

// assuming it's the first item in the shared string table
SharedStringItem sharedStringItem = new SharedStringItem();
Text text = new Text();
text.Text = DateTime.Today.ToString("MM/dd/yyyy hh:mm");
sharedStringTable1.Append(sharedStringItem);

Then later in code:

// assuming it's the first item in the shared string table
var cell = new Cell {CellReference = "A1", DataType = CellValues.SharedString};
var cellValue = new CellValue("0");
cell.Append(cellValue);
别挽留 2024-09-07 13:32:16

以下内容对我们有用:

c.CellValue = new CellValue(datetimeValue).ToOADate().ToString());
c.DataType = CellValues.Number;
c.StyleIndex = StyleDate;

将 DataType 设置为 CellValues.Number,然后确保使用 CellFormats 中适当的样式索引来格式化单元格。在我们的例子中,我们在工作表中构建一个样式表,StyleDate 是样式表中 CellFormat 的索引。

The following worked for us:

c.CellValue = new CellValue(datetimeValue).ToOADate().ToString());
c.DataType = CellValues.Number;
c.StyleIndex = StyleDate;

Set the DataType to CellValues.Number and then be sure to format the cell with the appropriate style index from the CellFormats. In our case we build a stylesheet within the worksheet, and StyleDate is an index into the CellFormats in the stylesheet.

离线来电— 2024-09-07 13:32:16

a) 与 Excel 2007、Excel 2007 Viewer 等兼容。
b) 1.1.1900 之前的日期时间写为字符串。

DateTime dat = (DateTime)dr[dc.ColumnName];

//Not working with Excel 2007
//cell.DataType = CellValues.Date;
//cell.CellValue = new CellValue(dat.ToString("s"));

double diff = (dat - new DateTime(1899, 12, 30)).TotalSeconds / 86400.0;
if (diff > 1)
{
    cell.DataType = CellValues.Number;
    cell.CellValue = new CellValue(diff.ToString().Replace(",", "."));

    if (dat.TimeOfDay == new TimeSpan(0))
    {                                
        cell.StyleIndex = 2;   //Custom Style NumberFormatId = 14 ( d/m/yyyy)
    }
    else
    {
        cell.StyleIndex = 1;   //Custom Style NumberFormatId = 22 (m/d/yyyy H:mm)
    }
}
else
{
    cell.DataType = CellValues.String;
    cell.CellValue = new CellValue(dat.ToString());
}

a) Get compatibility with Excel 2007, Excel 2007 Viewer etc.
b) DateTime before 1.1.1900 write as string.

DateTime dat = (DateTime)dr[dc.ColumnName];

//Not working with Excel 2007
//cell.DataType = CellValues.Date;
//cell.CellValue = new CellValue(dat.ToString("s"));

double diff = (dat - new DateTime(1899, 12, 30)).TotalSeconds / 86400.0;
if (diff > 1)
{
    cell.DataType = CellValues.Number;
    cell.CellValue = new CellValue(diff.ToString().Replace(",", "."));

    if (dat.TimeOfDay == new TimeSpan(0))
    {                                
        cell.StyleIndex = 2;   //Custom Style NumberFormatId = 14 ( d/m/yyyy)
    }
    else
    {
        cell.StyleIndex = 1;   //Custom Style NumberFormatId = 22 (m/d/yyyy H:mm)
    }
}
else
{
    cell.DataType = CellValues.String;
    cell.CellValue = new CellValue(dat.ToString());
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文