Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an OpenXml (C#) date/time format for "m/d/yyyy h:mm tt" [AM/PM]?

Looking at the list here, you can see:

  • 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
  • 39 - #,##0.00;(#,##0.00)
  • 40 - #,##0.00;Red
  • 45 - mm:ss
  • 46 - [h]:mm:ss
  • 47 - mmss.0
  • 48 - ##0.0E+0
  • 49 - @

You can see most cases seem to be covered, 22 gets very close, but what I really need is m/d/yyyy h:mm tt - does anyone know of a way to set that in OpenXml? Thank you.

like image 877
naspinski Avatar asked Oct 21 '25 16:10

naspinski


1 Answers

There isn't a built in format to achieve what you're after within OpenXml but you can easily add your own format. The format string you need is m/d/yyyy\ h:mm\ AM/PM.

In order to apply a format you need to create a NumberingFormats object, add a NumberingFormat to it and assign it to the NumberingFormats property on a Stylesheet. The following method will create a Stylesheet with the m/d/yyyy\ h:mm\ AM/PM format:

private static Stylesheet CreateStyles()
{
    Stylesheet styleSheet = new Stylesheet();

    NumberingFormats nfs = new NumberingFormats();

    NumberingFormat nf;
    nf = new NumberingFormat();
    nf.NumberFormatId = 165;
    nf.FormatCode = "m/d/yyyy\\ h:mm\\ AM/PM";
    nfs.Append(nf);

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

    CellFormats cfs = new CellFormats();
    cfs.Append(cf);
    styleSheet.CellFormats = cfs;
    styleSheet.NumberingFormats = nfs;
    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());

    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);
    return styleSheet;
}

The following code will create a new file from scratch with 2 dates (in A1 and B1) using the format added above:

public static void CreateFile(string filename)
{
    using (SpreadsheetDocument spreadsheetDocument = 
        SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
    {
        // Add a WorkbookPart to the document.
        WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
        workbookpart.Workbook = new Workbook();
        workbookpart.AddNewPart<WorkbookStylesPart>();

        // Add a WorksheetPart to the WorkbookPart.
        WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
        worksheetPart.Worksheet = new Worksheet(new SheetData());

        // Add Sheets to the Workbook.
        Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());

        // Append a new worksheet and associate it with the workbook.
        Sheet sheet = new Sheet()
        {
            Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
            SheetId = 1,
            Name = "Sheet 1"
        };
        sheets.Append(sheet);
        Worksheet worksheet = new Worksheet();
        SheetData sheetData = new SheetData();

        Stylesheet styleSheet = CreateStyles();
        Row row = CreateRow();

        sheetData.Append(row);
        worksheet.Append(sheetData);
        worksheetPart.Worksheet = worksheet;
        workbookpart.WorkbookStylesPart.Stylesheet = styleSheet;

        // Close the document.
        spreadsheetDocument.Close();
    }
}

private static Row CreateRow()
{
    Row row = new Row();

    DateTime now = DateTime.UtcNow;
    //add a date cell using the number data type
    Cell cell = new Cell();
    cell.StyleIndex = 0;
    cell.DataType = CellValues.Number;
    string columnValue = now.ToOADate().ToString();
    cell.CellValue = new CellValue(columnValue);
    row.Append(cell);

    //add a date cell using the date data type
    Cell cell2 = new Cell();
    cell2.StyleIndex = 0;
    cell2.DataType = CellValues.Date;
    columnValue = now.ToString("o");
    cell2.CellValue = new CellValue(columnValue);
    row.Append(cell2);
    return row;
}

Original answer (based on the 24hr time with the AM/PM specifier)

Unfortunately I don't think this is possible.

You can define custom formats but section 18.8.31 numFmts of the spec states:

If the format contains AM or PM, the hour is based on the 12-hour clock, where "AM" or "A" indicates times from midnight until noon and "PM" or "P" indicates times from noon until midnight. Otherwise, the hour is based on the 24-hour clock.

So, mixing the 24hr format with an AM/PM suffix isn't possible.

like image 96
petelids Avatar answered Oct 23 '25 05:10

petelids



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!