C# 使用OpenXMLSDK从xlsx读取日期
我在其中一个单元格的xlsx文件中有一个格式为“4/5/2011”(月/日/年)的日期。我正在尝试解析文件并将这些数据加载到一些类中 到目前为止,我解析单元格的部分如下所示:C# 使用OpenXMLSDK从xlsx读取日期,c#,date,datetime,openxml,openxml-sdk,C#,Date,Datetime,Openxml,Openxml Sdk,我在其中一个单元格的xlsx文件中有一个格式为“4/5/2011”(月/日/年)的日期。我正在尝试解析文件并将这些数据加载到一些类中 到目前为止,我解析单元格的部分如下所示: string cellValue = cell.InnerText; if (cell.DataType != null) { switch (cell.DataType.Value) { case CellValues.SharedString: // get st
string cellValue = cell.InnerText;
if (cell.DataType != null)
{
switch (cell.DataType.Value)
{
case CellValues.SharedString:
// get string from shared string table
cellValue = this.GetStringFromSharedStringTable(int.Parse(cellValue));
break;
}
}
我希望日期是cell.DataType。事实是,当解析日期为“4/5/2011”的单元格时,cell.DataType的值为null,单元格的值为“40638”,并且它不是共享字符串表的索引。(我以前也试过,但结果是一个例外。)
有什么想法吗?
谢谢我也遇到了同样的问题-切换到ePlus
请注意,它具有LGPL许可证。因此,如果您需要代码库不受GPL问题的影响,只需按原样使用库,您的原始代码库许可证是安全的。Open XML将日期存储为1900年1月1日起的天数。好吧,跳过不正确的1900年2月29日作为有效日期。您应该能够找到算法来帮助您计算正确的值。我相信一些开发人员使用
DateTime.FromOADate()
作为帮助
另外,默认情况下,单元格
类的数据类型
属性为Number。所以如果它是空的,它是一个数字,在我们的例子中包括日期
仅当存储的日期早于历元(本例中为1900年1月1日)时,才能转到共享字符串表。在这种情况下,Cell类的CellValue保存共享字符串表的索引。您可以使用DateTime.FromOADate(41690)添加我的2便士值。 我正在处理一个模板,所以我知道一个给定的单元格应该是一个日期时间。 因此,我在这个方法中使用了一个字符串参数excelDateTime,其中包含单元格值,它通常是一个OADate数字,如“42540.04166664” 我的问题是,最终用户在德国,因为这是一个网站,我们将Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture设置为“DE DE”。当您调用
double.TryParse
时,它使用区域性来解析数字。所以这一行:double.TryParse(“42540.0416666664”,out-oaDate)
确实有效,但它返回4254004166664
,因为在德国,点是一个组分隔符DateTime.FromOADate
然后失败,因为该数字超出范围()
这使我想到:
double.TryParse
时,我们应该使用double.TryParse(excelDateTimeAsString,NumberStyles.Any,CultureInfo.InvariantCulture,out-oaDateAsDouble))
。我使用的是CultureInfo.InvariantCulture,但应该是第1点,我不确定每个单元格有2个属性r(CellReference)和s(StyleIndex) 数字的样式索引为2,日期的样式索引为3 日期为ODate,您可以将其转换为字符串格式
value=DateTime.FromOADate(double.Parse(value)).ToSortDateString() 似乎没有为日期设置cell.DataType 方法是查看单元格是否有StyleIndex,它是文档中单元格格式数组的索引 然后使用cellFormat.NumberFormatId查看这是否是日期数据类型 下面是一些代码:
public class ExcelCellWithType
{
public string Value { get; set; }
public UInt32Value ExcelCellFormat { get; set; }
public bool IsDateTimeType { get; set; }
}
public class ExcelDocumentData
{
public ExcelXmlStatus Status { get; set; }
public IList<Sheet> Sheets { get; set; }
public IList<ExcelSheetData> SheetData { get; set; }
public ExcelDocumentData()
{
Status = new ExcelXmlStatus();
Sheets = new List<Sheet>();
SheetData = new List<ExcelSheetData>();
}
}
...
public ExcelDocumentData ReadSpreadSheetDocument(SpreadsheetDocument mySpreadsheet, ExcelDocumentData data)
{
var workbookPart = mySpreadsheet.WorkbookPart;
data.Sheets = workbookPart.Workbook.Descendants<Sheet>().ToList();
foreach (var sheet in data.Sheets)
{
var sheetData = new ExcelSheetData { SheetName = sheet.Name };
var workSheet = ((WorksheetPart)workbookPart.GetPartById(sheet.Id)).Worksheet;
sheetData.ColumnConfigurations = workSheet.Descendants<Columns>().FirstOrDefault();
var rows = workSheet.Elements<SheetData>().First().Elements<Row>().ToList();
if (rows.Count > 1)
{
foreach (var row in rows)
{
var dataRow = new List<ExcelCellWithType>();
var cellEnumerator = GetExcelCellEnumerator(row);
while (cellEnumerator.MoveNext())
{
var cell = cellEnumerator.Current;
var cellWithType = ReadExcelCell(cell, workbookPart);
dataRow.Add(cellWithType);
}
sheetData.DataRows.Add(dataRow);
}
}
data.SheetData.Add(sheetData);
}
return data;
}
...
private ExcelCellWithType ReadExcelCell(Cell cell, WorkbookPart workbookPart)
{
var cellValue = cell.CellValue;
var text = (cellValue == null) ? cell.InnerText : cellValue.Text;
if (cell.DataType?.Value == CellValues.SharedString)
{
text = workbookPart.SharedStringTablePart.SharedStringTable
.Elements<SharedStringItem>().ElementAt(
Convert.ToInt32(cell.CellValue.Text)).InnerText;
}
var cellText = (text ?? string.Empty).Trim();
var cellWithType = new ExcelCellWithType();
if (cell.StyleIndex != null)
{
var cellFormat = workbookPart.WorkbookStylesPart.Stylesheet.CellFormats.ChildElements[
int.Parse(cell.StyleIndex.InnerText)] as CellFormat;
if (cellFormat != null)
{
cellWithType.ExcelCellFormat = cellFormat.NumberFormatId;
var dateFormat = GetDateTimeFormat(cellFormat.NumberFormatId);
if (!string.IsNullOrEmpty(dateFormat))
{
cellWithType.IsDateTimeType = true;
if (!string.IsNullOrEmpty(cellText))
{
if (double.TryParse(cellText, out var cellDouble))
{
var theDate = DateTime.FromOADate(cellDouble);
cellText = theDate.ToString(dateFormat);
}
}
}
}
}
cellWithType.Value = cellText;
return cellWithType;
}
//// https://msdn.microsoft.com/en-GB/library/documentformat.openxml.spreadsheet.numberingformat(v=office.14).aspx
private readonly Dictionary<uint, string> DateFormatDictionary = new Dictionary<uint, string>()
{
[14] = "dd/MM/yyyy",
[15] = "d-MMM-yy",
[16] = "d-MMM",
[17] = "MMM-yy",
[18] = "h:mm AM/PM",
[19] = "h:mm:ss AM/PM",
[20] = "h:mm",
[21] = "h:mm:ss",
[22] = "M/d/yy h:mm",
[30] = "M/d/yy",
[34] = "yyyy-MM-dd",
[45] = "mm:ss",
[46] = "[h]:mm:ss",
[47] = "mmss.0",
[51] = "MM-dd",
[52] = "yyyy-MM-dd",
[53] = "yyyy-MM-dd",
[55] = "yyyy-MM-dd",
[56] = "yyyy-MM-dd",
[58] = "MM-dd",
[165] = "M/d/yy",
[166] = "dd MMMM yyyy",
[167] = "dd/MM/yyyy",
[168] = "dd/MM/yy",
[169] = "d.M.yy",
[170] = "yyyy-MM-dd",
[171] = "dd MMMM yyyy",
[172] = "d MMMM yyyy",
[173] = "M/d",
[174] = "M/d/yy",
[175] = "MM/dd/yy",
[176] = "d-MMM",
[177] = "d-MMM-yy",
[178] = "dd-MMM-yy",
[179] = "MMM-yy",
[180] = "MMMM-yy",
[181] = "MMMM d, yyyy",
[182] = "M/d/yy hh:mm t",
[183] = "M/d/y HH:mm",
[184] = "MMM",
[185] = "MMM-dd",
[186] = "M/d/yyyy",
[187] = "d-MMM-yyyy"
};
private string GetDateTimeFormat(UInt32Value numberFormatId)
{
return DateFormatDictionary.ContainsKey(numberFormatId) ? DateFormatDictionary[numberFormatId] : string.Empty;
}
公共类ExcelCellWithType
{
公共字符串值{get;set;}
公共UINT32值ExcelCellFormat{get;set;}
公共bool IsDateTimeType{get;set;}
}
公共类ExcelDocumentData
{
公共ExcelXmlStatus状态{get;set;}
公共IList表{get;set;}
公共IList SheetData{get;set;}
公共文档数据()
{
状态=新的ExcelXmlStatus();
图纸=新列表();
SheetData=新列表();
}
}
...
公共Excel文档数据读取电子表格文档(电子表格文档mySpreadsheet,Excel文档数据)
{
var workbookPart=mySpreadsheet.workbookPart;
data.Sheets=workbookPart.Workbook.subjects().ToList();
foreach(数据表中的var表)
{
var sheetData=new ExcelSheetData{SheetName=sheet.Name};
var工作表=((WorksheetPart)workbookPart.GetPartById(sheet.Id)).workSheet;
sheetData.ColumnConfigurations=workSheet.subjects().FirstOrDefault();
变量行=工作表.Elements().First().Elements().ToList();
如果(rows.Count>1)
{
foreach(行中的变量行)
{
var dataRow=新列表();
var cellEnumerator=GetExcelCellEnumerator(行);
while(cellEnumerator.MoveNext())
{
var cell=cellEnumerator.Current;
var cellWithType=ReadExcelCell(单元格,工作簿部件);
添加(cellWithType);
}
sheetData.DataRows.Add(dataRow);
}
}
data.SheetData.Add(SheetData);
}
返回数据;
}
...
私有ExcelCellWithType ReadExcelCell(单元格单元格,WorkbookPart WorkbookPart)
{
var cellValue=cell.cellValue;
var text=(cellValue==null)?cell.InnerText:cellValue.text;
if(cell.DataType?.Value==CellValues.SharedString)
{
text=workbookPart.SharedStringTablePart.SharedStringTable
.Elements().ElementAt(
Convert.ToInt32(cell.CellValue.Text)).InnerText;
}
var cellText=(text??string.Empty).Trim();
var cellWithType=新的ExcelCellWithType();
if(cell.StyleIndex!=null)
{
塞尔弗
public class ExcelCellWithType
{
public string Value { get; set; }
public UInt32Value ExcelCellFormat { get; set; }
public bool IsDateTimeType { get; set; }
}
public class ExcelDocumentData
{
public ExcelXmlStatus Status { get; set; }
public IList<Sheet> Sheets { get; set; }
public IList<ExcelSheetData> SheetData { get; set; }
public ExcelDocumentData()
{
Status = new ExcelXmlStatus();
Sheets = new List<Sheet>();
SheetData = new List<ExcelSheetData>();
}
}
...
public ExcelDocumentData ReadSpreadSheetDocument(SpreadsheetDocument mySpreadsheet, ExcelDocumentData data)
{
var workbookPart = mySpreadsheet.WorkbookPart;
data.Sheets = workbookPart.Workbook.Descendants<Sheet>().ToList();
foreach (var sheet in data.Sheets)
{
var sheetData = new ExcelSheetData { SheetName = sheet.Name };
var workSheet = ((WorksheetPart)workbookPart.GetPartById(sheet.Id)).Worksheet;
sheetData.ColumnConfigurations = workSheet.Descendants<Columns>().FirstOrDefault();
var rows = workSheet.Elements<SheetData>().First().Elements<Row>().ToList();
if (rows.Count > 1)
{
foreach (var row in rows)
{
var dataRow = new List<ExcelCellWithType>();
var cellEnumerator = GetExcelCellEnumerator(row);
while (cellEnumerator.MoveNext())
{
var cell = cellEnumerator.Current;
var cellWithType = ReadExcelCell(cell, workbookPart);
dataRow.Add(cellWithType);
}
sheetData.DataRows.Add(dataRow);
}
}
data.SheetData.Add(sheetData);
}
return data;
}
...
private ExcelCellWithType ReadExcelCell(Cell cell, WorkbookPart workbookPart)
{
var cellValue = cell.CellValue;
var text = (cellValue == null) ? cell.InnerText : cellValue.Text;
if (cell.DataType?.Value == CellValues.SharedString)
{
text = workbookPart.SharedStringTablePart.SharedStringTable
.Elements<SharedStringItem>().ElementAt(
Convert.ToInt32(cell.CellValue.Text)).InnerText;
}
var cellText = (text ?? string.Empty).Trim();
var cellWithType = new ExcelCellWithType();
if (cell.StyleIndex != null)
{
var cellFormat = workbookPart.WorkbookStylesPart.Stylesheet.CellFormats.ChildElements[
int.Parse(cell.StyleIndex.InnerText)] as CellFormat;
if (cellFormat != null)
{
cellWithType.ExcelCellFormat = cellFormat.NumberFormatId;
var dateFormat = GetDateTimeFormat(cellFormat.NumberFormatId);
if (!string.IsNullOrEmpty(dateFormat))
{
cellWithType.IsDateTimeType = true;
if (!string.IsNullOrEmpty(cellText))
{
if (double.TryParse(cellText, out var cellDouble))
{
var theDate = DateTime.FromOADate(cellDouble);
cellText = theDate.ToString(dateFormat);
}
}
}
}
}
cellWithType.Value = cellText;
return cellWithType;
}
//// https://msdn.microsoft.com/en-GB/library/documentformat.openxml.spreadsheet.numberingformat(v=office.14).aspx
private readonly Dictionary<uint, string> DateFormatDictionary = new Dictionary<uint, string>()
{
[14] = "dd/MM/yyyy",
[15] = "d-MMM-yy",
[16] = "d-MMM",
[17] = "MMM-yy",
[18] = "h:mm AM/PM",
[19] = "h:mm:ss AM/PM",
[20] = "h:mm",
[21] = "h:mm:ss",
[22] = "M/d/yy h:mm",
[30] = "M/d/yy",
[34] = "yyyy-MM-dd",
[45] = "mm:ss",
[46] = "[h]:mm:ss",
[47] = "mmss.0",
[51] = "MM-dd",
[52] = "yyyy-MM-dd",
[53] = "yyyy-MM-dd",
[55] = "yyyy-MM-dd",
[56] = "yyyy-MM-dd",
[58] = "MM-dd",
[165] = "M/d/yy",
[166] = "dd MMMM yyyy",
[167] = "dd/MM/yyyy",
[168] = "dd/MM/yy",
[169] = "d.M.yy",
[170] = "yyyy-MM-dd",
[171] = "dd MMMM yyyy",
[172] = "d MMMM yyyy",
[173] = "M/d",
[174] = "M/d/yy",
[175] = "MM/dd/yy",
[176] = "d-MMM",
[177] = "d-MMM-yy",
[178] = "dd-MMM-yy",
[179] = "MMM-yy",
[180] = "MMMM-yy",
[181] = "MMMM d, yyyy",
[182] = "M/d/yy hh:mm t",
[183] = "M/d/y HH:mm",
[184] = "MMM",
[185] = "MMM-dd",
[186] = "M/d/yyyy",
[187] = "d-MMM-yyyy"
};
private string GetDateTimeFormat(UInt32Value numberFormatId)
{
return DateFormatDictionary.ContainsKey(numberFormatId) ? DateFormatDictionary[numberFormatId] : string.Empty;
}
private static object Convert(this DocumentFormat.OpenXml.Spreadsheet.CellValues value, string content)
{
switch (value)
{
case DocumentFormat.OpenXml.Spreadsheet.CellValues.Boolean:
if (content.Length < 2)
{
return content?.ToUpperInvariant() == "T" || content == "1";
}
return System.Convert.ToBoolean(content);
case DocumentFormat.OpenXml.Spreadsheet.CellValues.Date:
if (double.TryParse(content, out double result))
{
return System.DateTime.FromOADate(result);
}
return null;
case DocumentFormat.OpenXml.Spreadsheet.CellValues.Number:
return System.Convert.ToDecimal(content);
case DocumentFormat.OpenXml.Spreadsheet.CellValues.Error:
case DocumentFormat.OpenXml.Spreadsheet.CellValues.String:
case DocumentFormat.OpenXml.Spreadsheet.CellValues.InlineString:
case DocumentFormat.OpenXml.Spreadsheet.CellValues.SharedString:
default:
return content;
}
}