c# - ejemplos - OpenXML: escribir una fecha en la hoja de cálculo de Excel da como resultado un contenido ilegible
epplus ejemplos c# (7)
Estoy usando el siguiente código para agregar una fecha y hora a una columna en mi hoja de cálculo:
var dt = DateTime.Now;
r.AppendChild<Cell>(new Cell() { CellValue = new CellValue(dt.ToOADate().ToString()),
DataType = new EnumValue<CellValues>(CellValues.Date),
StyleIndex = 1,
CellReference = header[6] + index });
Cuando intento abrir el archivo en Excel 2010, aparece el error
Excel found unreadable content in file.xlsx
Todo está bien si comento la línea.
Me he referido a preguntas similares en StackOverFlow, pero básicamente tienen el mismo código que yo
Como ejemplo, puede crear su propio archivo de Excel con la columna de fecha. Luego, si lo abre con la Herramienta de productividad de Open XML SDK, encontrará que no se ha especificado ningún DataType
para la celda con valor de fecha. Esto significa que debe omitir DataType
al crear la celda de fecha. En este caso, también es necesario pasar dt.ToOADate().ToString()
como un valor de celda.
El siguiente código se puede usar para establecer un valor de DateTime en una hoja de cálculo:
Cell cell = GetRequiredCell(); // It returns the required Cell
DateTime dtValue = new DateTime(2012, 12, 8);
string strValue = dtValue.ToOADate().ToString().Replace(",", ".");
// decimal separator change it to "."
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.CellValue = new CellValue(strValue);
cell.StyleIndex = 1;
Intente indicar que es un tipo CellValues.String
, en lugar de un tipo CellValues.Date
.
Utilizar
DataType = new EnumValue<CellValues>(CellValues.String) // good
en lugar de
DataType = new EnumValue<CellValues>(CellValues.Date) // bad
Ahora, tendría sentido agregarlo como fecha , sin la conversión ToString (), y usar CellValues.Date
DataType, pero CellValue () solo toma una cadena como parámetro. [¿Por qué, OpenXmlSDK, ¿POR QUÉ ? Eres una envoltura Envuelve las cosas muy bien. Hazlos invisibles, y hazte la vida más fácil. :::suspiro:::]
Además, si la celda objetivo espera formatear una fecha, deberíamos indicar que es una fecha.
Pero he descubierto que mientras CellValues.String
y CellValues.Date
se formatean como se esperaba (de manera idéntica), solo CellValues.Date arroja el "contenido ilegible" en la carga.
No he tenido ninguna suerte con cualquier variación en dt.ToOADate().ToString(new CultureInfo("en-US"));
Método: termino con un número de cinco dígitos que se muestra en la hoja de cálculo como un número de cinco dígitos, cuando debería ser una fecha con formato.
CellValues.Number
el mismo mensaje de error al agregar un valor de cadena, pero al usar el CellValues.Number
datos CellValues.Number
.
Lo siguiente funcionó para nosotros:
c.CellValue = new CellValue(datetimeValue).ToOADate().ToString());
c.DataType = CellValues.Number;
c.StyleIndex = StyleDate;
Establezca DataType en CellValues.Number y luego asegúrese de formatear la celda con el índice de estilo apropiado de CellFormats. En nuestro caso, construimos una hoja de estilo dentro de la hoja de trabajo, y StyleDate es un índice en los CellFormats en la hoja de estilo.
Tarde en la fiesta, como de costumbre, pero tengo que publicar una respuesta porque TODAS las anteriores están completamente equivocadas, excepto la respuesta negativa de Oleh, que lamentablemente estaba incompleta.
Como la pregunta está relacionada con Excel, lo más fácil es crear una hoja de cálculo de Excel con los datos y el estilo que desea, luego abrirla como partes y ver el XML sin formato.
Agregar la fecha 01/01/2015 en la celda A1 da como resultado lo siguiente:
<row r="1">
<c r="A1" s="0">
<v>42005</v>
</c>
</row>
Tenga en cuenta que el atributo de tipo no está allí. Sin embargo, hay un atributo de estilo que hace referencia al siguiente estilo:
<xf numFmtId="14" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1" />
Ese es el estilo más básico que debes agregar.
Entonces codifique para generar lo anterior:
- Necesitas crear un estilo de la siguiente manera:
var CellFormats = new CellFormats();
CellFormats.Append(new CellFormat()
{
BorderId = 0,
FillId = 0,
FontId = 0,
NumberFormatId = 14,
FormatId = 0,
ApplyNumberFormat = true
});
CellFormats.Count = (uint)CellFormats.ChildElements.Count;
var StyleSheet = new Stylesheet();
StyleSheet.Append(CellFormats);
El NumberFormatId = 14
refiere al formato incorporado mm-dd-yy
, aquí hay una lista de algunos otros formatos .
Desafortunadamente, parece que agregar solo el estilo anterior no es suficiente y si lo hace, en realidad hace que Excel se bloquee. Tenga en cuenta que BorderId
, FillId
, FontId
deben corresponder a un elemento en la hoja de estilo, lo que significa que debe proporcionarlos. El método GetStyleSheet()
en la lista de códigos completa proporciona la hoja de estilo predeterminada mínima requerida para que Excel funcione sin errores.
- Y añada una celda de la siguiente manera:
SheetData.AppendChild(new Row(
new Cell()
{
// CellValue is set to OADate because that''s what Excel expects.
CellValue = new CellValue(date.ToOADate().ToString(CultureInfo.InvariantCulture)),
// Style index set to style (0 based).
StyleIndex = 0
}));
Nota: Office 2010 y 2013 pueden manejar las fechas de manera diferente, pero por defecto parece que no lo hacen.
Proporcionan soporte para las fechas en formato ISO 8601, es decir, yyyy-MM-ddTHH:mm:ss
casualidad de que este también es un formato estándar clasificable ("s"), por lo que puede hacerlo:
SheetData.AppendChild(new Row(
new Cell()
{
CellValue = new CellValue(date.ToString("s")),
// This time we do add the DataType attribute but ONLY for Office 2010+.
DataType = CellValues.Date
StyleIndex = 1
}));
El resultado:
<row>
<c s="0" t="d">
<v>2015-08-05T11:13:57</v>
</c>
</row>
Listado de Código Completo
A continuación se muestra un ejemplo del código mínimo requerido para agregar una celda con formato de fecha.
private static void TestExcel()
{
using (var Spreadsheet = SpreadsheetDocument.Create("C://Example.xlsx", SpreadsheetDocumentType.Workbook))
{
// Create workbook.
var WorkbookPart = Spreadsheet.AddWorkbookPart();
var Workbook = WorkbookPart.Workbook = new Workbook();
// Add Stylesheet.
var WorkbookStylesPart = WorkbookPart.AddNewPart<WorkbookStylesPart>();
WorkbookStylesPart.Stylesheet = GetStylesheet();
WorkbookStylesPart.Stylesheet.Save();
// Create worksheet.
var WorksheetPart = Spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
var Worksheet = WorksheetPart.Worksheet = new Worksheet();
// Add data to worksheet.
var SheetData = Worksheet.AppendChild(new SheetData());
SheetData.AppendChild(new Row(
new Cell() { CellValue = new CellValue(DateTime.Today.ToOADate().ToString(CultureInfo.InvariantCulture)), StyleIndex = 1 },
// Only works for Office 2010+.
new Cell() { CellValue = new CellValue(DateTime.Today.ToString("s")), DataType = CellValues.Date, StyleIndex = 1 }));
// Link worksheet to workbook.
var Sheets = Workbook.AppendChild(new Sheets());
Sheets.AppendChild(new Sheet()
{
Id = WorkbookPart.GetIdOfPart(WorksheetPart),
SheetId = (uint)(Sheets.Count() + 1),
Name = "Example"
});
Workbook.Save();
}
}
private static Stylesheet GetStylesheet()
{
var StyleSheet = new Stylesheet();
// Create "fonts" node.
var Fonts = new Fonts();
Fonts.Append(new Font()
{
FontName = new FontName() { Val = "Calibri" },
FontSize = new FontSize() { Val = 11 },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
});
Fonts.Count = (uint)Fonts.ChildElements.Count;
// Create "fills" node.
var Fills = new Fills();
Fills.Append(new Fill()
{
PatternFill = new PatternFill() { PatternType = PatternValues.None }
});
Fills.Append(new Fill()
{
PatternFill = new PatternFill() { PatternType = PatternValues.Gray125 }
});
Fills.Count = (uint)Fills.ChildElements.Count;
// Create "borders" node.
var Borders = new Borders();
Borders.Append(new Border()
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
Borders.Count = (uint)Borders.ChildElements.Count;
// Create "cellStyleXfs" node.
var CellStyleFormats = new CellStyleFormats();
CellStyleFormats.Append(new CellFormat()
{
NumberFormatId = 0,
FontId = 0,
FillId = 0,
BorderId = 0
});
CellStyleFormats.Count = (uint)CellStyleFormats.ChildElements.Count;
// Create "cellXfs" node.
var CellFormats = new CellFormats();
// A default style that works for everything but DateTime
CellFormats.Append(new CellFormat()
{
BorderId = 0,
FillId = 0,
FontId = 0,
NumberFormatId = 0,
FormatId = 0,
ApplyNumberFormat = true
});
// A style that works for DateTime (just the date)
CellFormats.Append(new CellFormat()
{
BorderId = 0,
FillId = 0,
FontId = 0,
NumberFormatId = 14, // or 22 to include the time
FormatId = 0,
ApplyNumberFormat = true
});
CellFormats.Count = (uint)CellFormats.ChildElements.Count;
// Create "cellStyles" node.
var CellStyles = new CellStyles();
CellStyles.Append(new CellStyle()
{
Name = "Normal",
FormatId = 0,
BuiltinId = 0
});
CellStyles.Count = (uint)CellStyles.ChildElements.Count;
// Append all nodes in order.
StyleSheet.Append(Fonts);
StyleSheet.Append(Fills);
StyleSheet.Append(Borders);
StyleSheet.Append(CellStyleFormats);
StyleSheet.Append(CellFormats);
StyleSheet.Append(CellStyles);
return StyleSheet;
}
intente dt.ToOADate().ToString().Replace (",", ".")
lugar de dt.ToOADate().ToString()
Para ver algunos ejemplos de código de trabajo, visite http://www.codeproject.com/KB/office/ExcelOpenXMLSDK.aspx
EDITAR:
por favor cambia tu código a esto:
dt.ToOADate().ToString(new CultureInfo("en-US"));
private Cell CreateCellWithValue(DateTime columnValue, uint? styleIndex, string cellReference)
{
Cell c = new Cell();
c.DataType = CellValues.Number;
c.CellValue = new CellValue(columnValue.ToOADate().ToString(new CultureInfo("en-US")));
c.CellReference = cellReference;
c.StyleIndex = styleIndex;
return c;
}