Domanda

Sto usando Microsoft Open XML SDK 2 e sto avendo un momento davvero difficile l'inserimento di una data in una cella. Posso inserire numeri senza un problema impostando Cell.DataType = CellValues.Number, ma quando lo faccio lo stesso con una data (Cell.DataType = CellValues.Date) Excel 2010 si blocca (2007 troppo).

Ho provato a fissare il valore Cell.Text a molti formati di data e il formato della data di Excel / numerico inutilmente. Ho provato anche a stili di utilizzo, eliminando l'attributo type, oltre a molte altre pizze ho buttato contro il muro ...

qualcuno mi può punto ad un esempio l'inserimento di una data per un foglio di lavoro?

È stato utile?

Soluzione

È necessario convertire DateTime a double utilizzando la funzione ToOADate cioè:.

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

quindi impostarlo come CellValue

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

Ricordate di cella formato utilizzando DateTime formattazione, altrimenti si vedrà il valore double, non la data.

Altri suggerimenti

Ho usato il codice fornito da Andrew J, ma la DataType CellValues.Date prodotto un xlsx-file danneggiato per me.

Il DataType CellValues.Number funzionato bene per me (non dimenticate di NumberFormatId set) :

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

Tutto il mio codice:

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);

Il mio CellFormat per questa cella negli sguardi del foglio di stile come:

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

Se vuoi formattare la data in un altro modo, ecco un elenco di tutti i predefinito Excel del NumberFormatId

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  @

Fonte di lista: https://github.com/ClosedXML/ClosedXML / wiki / NumberFormatId-Lookup-Table

So che questo elenco è da ClosedXML, ma è lo stesso in OpenXML.

Durante la creazione di nuova SpreadsheetDocument da zero, per Date formattazione al lavoro, il minimo Stylesheet deve essere creato.

critiche sono quelle poche righe:

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

class Stylesheet completa:

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`...

Dopo aver aggiunto Stylesheet, DateTime può essere formattato:

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; 
}

Si noti che il valore StyleIndex dipende dall'ordine degli elementi CellFormat nell'array CellFormats o l'oggetto Stylesheet. In questo esempio oggetto NumberFormatId = 14 al 2 ° elemento della matrice.

Ci sono 2 modi per memorizzare le date in OpenXml; scrivendo un numero (utilizzando ToOADate) e impostando la DataType a Number o scrivendo un ISO 8601 la data e l'impostazione del DataType a Date formattato. Si noti che il valore predefinito è DataType Number quindi se si va con la prima opzione non è necessario impostare il DataType.

Qualunque sia il metodo scelto, dovrete impostare lo stile come Excel visualizza entrambi i metodi in modo identico. Quanto segue mostra un esempio di codice crei una data utilizzando il formato Number (con e senza impostare esplicitamente la DataType) e utilizzando il formato 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();
}

Usa Stringa condivisa:

// 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);

Poi, più avanti nel codice:

// 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);

Di seguito ha lavorato per noi:

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

Impostare il tipo di dati per CellValues.Number e quindi assicuratevi di formattare la cella con l'indice stile appropriato dalle CellFormats. Nel nostro caso si costruisce un foglio di stile all'interno del foglio di lavoro, e StyleDate è un indice nelle CellFormats nel foglio di stile.

a) Get compatibilità con Excel 2007, Excel 2007 Viewer etc. b) DateTime prima 1900/01/01 scrittura come stringa.

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());
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top