What indicates an Office Open XML Cell contains a Date/Time value?

前端 未结 6 2017
-上瘾入骨i
-上瘾入骨i 2020-11-27 13:26

I\'m reading an .xlsx file using the Office Open XML SDK and am confused about reading Date/Time values. One of my spreadsheets has this markup (generated by Excel 2010)

6条回答
  •  执念已碎
    2020-11-27 14:04

    Thought I'd add my solution that I've put together to determine if the double value FromOADate is really a date or not. Reason being is I have a zip code in my excel file as well. The numberingFormat will be null if it's text.

    Alternatively you could use the numberingFormatId and check against a list of Ids that Excel uses for dates.

    In my case I've explicitly determined the formatting of all fields for the client.

        /// 
        /// Creates the datatable and parses the file into a datatable
        /// 
        /// the file upload's filename
        private void ReadAsDataTable(string fileName)
        {
            try
            {
                DataTable dt = new DataTable();
                using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(string.Format("{0}/{1}", UploadPath, fileName), false))
                {
                    WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
                    IEnumerable sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild().Elements();
                    string relationshipId = sheets.First().Id.Value;
                    WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
                    Worksheet workSheet = worksheetPart.Worksheet;
                    SheetData sheetData = workSheet.GetFirstChild();
                    IEnumerable rows = sheetData.Descendants();
    
                    var cellFormats = workbookPart.WorkbookStylesPart.Stylesheet.CellFormats;
                    var numberingFormats = workbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats;
    
                    // columns omitted for brevity
    
                    // skip first row as this row is column header names
                    foreach (Row row in rows.Skip(1))
                    {
                        DataRow dataRow = dt.NewRow();
    
                        for (int i = 0; i < row.Descendants().Count(); i++)
                        {
                            bool isDate = false;
                            var styleIndex = (int)row.Descendants().ElementAt(i).StyleIndex.Value;
                            var cellFormat = (CellFormat)cellFormats.ElementAt(styleIndex);
    
                            if (cellFormat.NumberFormatId != null)
                            {
                                var numberFormatId = cellFormat.NumberFormatId.Value;
                                var numberingFormat = numberingFormats.Cast()
                                    .SingleOrDefault(f => f.NumberFormatId.Value == numberFormatId);
    
                                // Here's yer string! Example: $#,##0.00_);[Red]($#,##0.00)
                                if (numberingFormat != null && numberingFormat.FormatCode.Value.Contains("mm/dd/yy"))
                                {
                                    string formatString = numberingFormat.FormatCode.Value;
                                    isDate = true;
                                }
                            }
    
                            // replace '-' with empty string
                            string value = GetCellValue(spreadSheetDocument, row.Descendants().ElementAt(i), isDate);
                            dataRow[i] = value.Equals("-") ? string.Empty : value;
                        }
    
                        dt.Rows.Add(dataRow);
                    }
                }
    
                this.InsertMembers(dt);
                dt.Clear();
            }
            catch (Exception ex)
            {
                LogHelper.Error(typeof(MemberUploadApiController), ex.Message, ex);
            }
        }
    
        /// 
        /// Reads the cell's value
        /// 
        /// current document
        /// the cell to read
        /// cell's value
        private string GetCellValue(SpreadsheetDocument document, Cell cell, bool isDate)
        {
            string value = string.Empty;
    
            try
            {
                SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
                value = cell.CellValue.InnerXml;
    
                if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
                {
                    return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
                }
                else
                {
                    // check if this is a date or zip.
                    // integers will be passed into this else statement as well. 
                    if (isDate)
                    {
                        value = DateTime.FromOADate(double.Parse(value)).ToString();
                    }
    
                    return value;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(typeof(MemberUploadApiController), ex.Message, ex);
            }
    
            return value;
        }
    

提交回复
热议问题