Question

J'utilise Microsoft Open XML SDK 2 et je vais avoir une période très difficile d'insérer une date dans une cellule. Je peux insérer des numéros sans problème en définissant Cell.DataType = CellValues.Number, mais quand je fais la même chose avec une date (Cell.DataType = CellValues.Date) se bloque Excel 2010 (2007 aussi).

J'ai essayé de définir la valeur de Cell.Text à de nombreux formats de date, ainsi que la date d'Excel / format numérique sans succès. J'ai aussi essayé de styles d'utilisation, en supprimant l'attribut type, ainsi que beaucoup d'autres pizzas j'ai jeté au mur ...

point Quelqu'un peut-il me un exemple d'insérer une date dans une feuille de calcul?

Était-ce utile?

La solution

Vous devez convertir DateTime à double en utilisant la fonction ToOADate i.e.:.

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

puis définissez comme CellValue

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

Souvenez-vous de la cellule de format à l'aide DateTime le formatage, sinon vous verrez valeur double, ne date pas.

Autres conseils

J'ai utilisé le code fourni par Andrew J, mais le DataType de CellValues.Date produit un xlsx fichier corrompu pour moi.

Le DataType de CellValues.Number a bien fonctionné pour moi (Ne pas oublier de NumberFormatId ensemble) :

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

Mon code complet:

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

Mon CellFormat pour cette cellule dans les regards Stylesheet comme:

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

Si vous souhaitez formater votre date d'une autre manière, voici une liste de tous par défaut Excel NumberFormatId de

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 de la liste: https://github.com/ClosedXML/ClosedXML / wiki / NumberFormatId-Lookup Table

Je sais que cette liste est de ClosedXML, mais il est le même dans OpenXML.

Lors de la création SpreadsheetDocument à partir de zéro, pour Date mise en forme au travail, Stylesheet minimum doit être créé.

critiques sont ces quelques lignes:

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

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

Après Stylesheet est ajouté, DateTime peut être formaté:

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

Notez que la valeur StyleIndex dépend de l'ordre des éléments de CellFormat dans le tableau de CellFormats ou l'objet Stylesheet. Dans cet exemple, l'article de NumberFormatId = 14 sur le 2ème élément du tableau.

Il y a 2 façons de stocker les dates dans OpenXml; en attribuant un numéro (en utilisant ToOADate) et le réglage de la DataType à Number ou en écrivant un ISO 8601 formaté la date et le réglage de la DataType à Date. Notez que le DataType par défaut est Number donc si vous allez avec la première option, vous ne devez pas régler le DataType.

Quelle que soit la méthode choisie, vous devrez définir le style comme Excel affiche les deux méthodes identiques. Le code suivant montre un exemple d'écrire une date en utilisant le format Number (avec et sans mettre explicitement le DataType) et en utilisant le format 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();
}

Utiliser la chaîne partagée:

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

Puis, plus tard dans le 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);

La suivante a fonctionné pour nous:

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

Définissez le DataType à CellValues.Number puis assurez-vous de formater la cellule avec l'indice de style approprié des CellFormats. Dans notre cas, nous construisons une feuille de style au sein de la feuille de calcul, et StyleDate est un indice dans les CellFormats dans la feuille de style.

a) Obtenez la compatibilité avec Excel 2007, Excel 2007 Viewer, etc. b) DateTime avant 01/01/1900 écriture sous forme de chaîne.

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());
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top