31 private MemoryStream stream;
33 private List<string> dateStyles;
34 private List<string> timeStyles;
35 private Dictionary<string, Style> resolvedStyles;
72 public void Init(MemoryStream stream,
Workbook workbook, IOptions readerOptions)
75 this.Workbook = workbook;
77 if (dateStyles ==
null || timeStyles ==
null || this.resolvedStyles ==
null)
80 ProcessStyles(styleReaderContainer);
82 if (this.passwordReader ==
null)
85 this.passwordReader.
Init(PasswordType.WorksheetProtection,
this.readerOptions);
97 WorksheetDefinition worksheetDefinition =
Workbook.AuxiliaryData.GetData<WorksheetDefinition>(PlugInUUID.WorkbookReader, PlugInUUID.WorksheetDefinitionEntity,
CurrentWorksheetID);
100 Hidden = worksheetDefinition.Hidden
104 XmlDocument document =
new XmlDocument() { XmlResolver =
null };
105 using (XmlReader reader = XmlReader.Create(stream,
new XmlReaderSettings() { XmlResolver =
null }))
107 document.Load(reader);
108 GetRows(document, worksheet);
109 GetSheetView(document, worksheet);
110 GetMergedCells(document, worksheet);
111 GetSheetFormats(document, worksheet);
112 GetAutoFilters(document, worksheet);
113 GetColumns(document, worksheet);
114 GetSheetProtection(document, worksheet);
115 SetWorkbookRelation(worksheet);
122 catch (NotSupportedContentException)
128 throw new IOException(
"The XML entry could not be read from the input stream. Please see the inner exception:", ex);
136 private void SetWorkbookRelation(Worksheet worksheet)
139 int selectedWorksheetId =
Workbook.AuxiliaryData.GetData<
int>(PlugInUUID.WorkbookReader, PlugInUUID.SelectedWorksheetEntity);
142 Workbook.SetSelectedWorksheet(worksheet);
150 private void ProcessStyles(StyleReaderContainer styleReaderContainer)
152 this.dateStyles =
new List<string>();
153 this.timeStyles =
new List<string>();
154 this.resolvedStyles =
new Dictionary<string, Style>();
155 for (
int i = 0; i < styleReaderContainer.StyleCount; i++)
159 string index = ParserUtils.ToString(i);
160 Style style = styleReaderContainer.GetStyle(i, out isDate, out isTime);
163 this.dateStyles.Add(index);
167 this.timeStyles.Add(index);
169 this.resolvedStyles.Add(index, style);
178 private void GetRows(XmlDocument document, Worksheet worksheet)
180 XmlNodeList rows = document.GetElementsByTagName(
"row");
181 foreach (XmlNode row
in rows)
183 string rowAttribute = ReaderUtils.GetAttribute(row,
"r");
184 if (rowAttribute !=
null)
186 int rowNumber = ParserUtils.ParseInt(rowAttribute) - 1;
187 string hiddenAttribute = ReaderUtils.GetAttribute(row,
"hidden");
188 if (hiddenAttribute !=
null)
190 int value = ParserUtils.ParseBinaryBool(hiddenAttribute);
193 worksheet.AddHiddenRow(rowNumber);
196 string heightAttribute = ReaderUtils.GetAttribute(row,
"ht");
197 if (heightAttribute !=
null)
199 worksheet.RowHeights.Add(rowNumber, GetValidatedHeight(ParserUtils.ParseFloat(heightAttribute)));
202 if (row.HasChildNodes)
204 foreach (XmlNode rowChild
in row.ChildNodes)
206 ReadCell(rowChild, worksheet);
217 private static void GetSheetView(XmlDocument xmlDocument, Worksheet worksheet)
219 XmlNodeList sheetViewsNodes = xmlDocument.GetElementsByTagName(
"sheetViews");
220 if (sheetViewsNodes !=
null && sheetViewsNodes.Count > 0)
222 XmlNodeList sheetViewNodes = sheetViewsNodes[0].ChildNodes;
225 foreach (XmlNode sheetView
in sheetViewNodes)
227 attribute = ReaderUtils.GetAttribute(sheetView,
"view",
string.Empty);
228 worksheet.ViewType = Worksheet.GetSheetViewTypeEnum(attribute);
229 attribute = ReaderUtils.GetAttribute(sheetView,
"zoomScale");
230 if (attribute !=
null)
232 worksheet.ZoomFactor = ParserUtils.ParseInt(attribute);
234 attribute = ReaderUtils.GetAttribute(sheetView,
"zoomScaleNormal");
235 if (attribute !=
null)
237 int scale = ParserUtils.ParseInt(attribute);
238 worksheet.ZoomFactors[Worksheet.SheetViewType.Normal] = scale;
240 attribute = ReaderUtils.GetAttribute(sheetView,
"zoomScalePageLayoutView");
241 if (attribute !=
null)
243 int scale = ParserUtils.ParseInt(attribute);
244 worksheet.ZoomFactors[Worksheet.SheetViewType.PageLayout] = scale;
246 attribute = ReaderUtils.GetAttribute(sheetView,
"zoomScaleSheetLayoutView");
247 if (attribute !=
null)
249 int scale = ParserUtils.ParseInt(attribute);
250 worksheet.ZoomFactors[Worksheet.SheetViewType.PageBreakPreview] = scale;
252 attribute = ReaderUtils.GetAttribute(sheetView,
"showGridLines");
253 if (attribute !=
null)
255 worksheet.ShowGridLines = ParserUtils.ParseBinaryBool(attribute) == 1;
257 attribute = ReaderUtils.GetAttribute(sheetView,
"showRowColHeaders");
258 if (attribute !=
null)
260 worksheet.ShowRowColumnHeaders = ParserUtils.ParseBinaryBool(attribute) == 1;
262 attribute = ReaderUtils.GetAttribute(sheetView,
"showRuler");
263 if (attribute !=
null)
265 worksheet.ShowRuler = ParserUtils.ParseBinaryBool(attribute) == 1;
267 if (sheetView.LocalName.Equals(
"sheetView", StringComparison.OrdinalIgnoreCase))
269 XmlNodeList selectionNodes = sheetView.ChildNodes;
270 if (selectionNodes !=
null && selectionNodes.Count > 0)
272 foreach (XmlNode selectionNode
in selectionNodes)
274 attribute = ReaderUtils.GetAttribute(selectionNode,
"sqref");
275 if (attribute !=
null)
277 if (attribute.Contains(
" "))
280 string[] ranges = attribute.Split(
' ');
281 foreach (
string range
in ranges)
283 CollectSelectedCells(range, worksheet);
288 CollectSelectedCells(attribute, worksheet);
294 XmlNode paneNode = ReaderUtils.GetChildNode(sheetView,
"pane");
295 if (paneNode !=
null)
297 SetPaneSplit(paneNode, worksheet);
309 private static void CollectSelectedCells(
string attribute, Worksheet worksheet)
311 if (attribute.Contains(
":"))
314 worksheet.AddSelectedCells(
new Range(attribute));
319 worksheet.AddSelectedCells(
new Range(attribute +
":" + attribute));
328 private static void SetPaneSplit(XmlNode paneNode, Worksheet worksheet)
330 string attribute = ReaderUtils.GetAttribute(paneNode,
"state");
331 bool useNumbers =
false;
332 bool frozenState =
false;
333 bool ySplitDefined =
false;
334 bool xSplitDefined =
false;
335 int? paneSplitRowIndex =
null;
336 int? paneSplitColumnIndex =
null;
337 float? paneSplitHeight =
null;
338 float? paneSplitWidth =
null;
339 Address topLeftCell =
new Address(0, 0);
340 Worksheet.WorksheetPane? activePane =
null;
341 if (attribute !=
null)
343 if (ParserUtils.ToLower(attribute) ==
"frozen" || ParserUtils.ToLower(attribute) ==
"frozensplit")
347 useNumbers = frozenState;
349 attribute = ReaderUtils.GetAttribute(paneNode,
"ySplit");
350 if (attribute !=
null)
352 ySplitDefined =
true;
355 paneSplitRowIndex = ParserUtils.ParseInt(attribute);
359 paneSplitHeight = DataUtils.GetPaneSplitHeight(ParserUtils.ParseFloat(attribute));
362 attribute = ReaderUtils.GetAttribute(paneNode,
"xSplit");
363 if (attribute !=
null)
365 xSplitDefined =
true;
368 paneSplitColumnIndex = ParserUtils.ParseInt(attribute);
372 paneSplitWidth = DataUtils.GetPaneSplitWidth(ParserUtils.ParseFloat(attribute));
375 attribute = ReaderUtils.GetAttribute(paneNode,
"topLeftCell");
376 if (attribute !=
null)
378 topLeftCell =
new Address(attribute);
380 attribute = ReaderUtils.GetAttribute(paneNode,
"activePane",
string.Empty);
381 activePane = Worksheet.GetWorksheetPaneEnum(attribute);
384 if (ySplitDefined && !xSplitDefined)
386 worksheet.SetHorizontalSplit(paneSplitRowIndex.Value, frozenState, topLeftCell, activePane);
388 if (!ySplitDefined && xSplitDefined)
390 worksheet.SetVerticalSplit(paneSplitColumnIndex.Value, frozenState, topLeftCell, activePane);
392 else if (ySplitDefined && xSplitDefined)
394 worksheet.SetSplit(paneSplitColumnIndex.Value, paneSplitRowIndex.Value, frozenState, topLeftCell, activePane);
399 if (ySplitDefined && !xSplitDefined)
401 worksheet.SetHorizontalSplit(paneSplitHeight.Value, topLeftCell, activePane);
403 if (!ySplitDefined && xSplitDefined)
405 worksheet.SetVerticalSplit(paneSplitWidth.Value, topLeftCell, activePane);
407 else if (ySplitDefined && xSplitDefined)
409 worksheet.SetSplit(paneSplitWidth, paneSplitHeight, topLeftCell, activePane);
419 private void GetSheetProtection(XmlDocument xmlDocument, Worksheet worksheet)
421 XmlNodeList sheetProtectionNodes = xmlDocument.GetElementsByTagName(
"sheetProtection");
422 if (sheetProtectionNodes !=
null && sheetProtectionNodes.Count > 0)
424 int hasProtection = 0;
425 XmlNode sheetProtectionNode = sheetProtectionNodes[0];
426 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.AutoFilter, worksheet);
427 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.DeleteColumns, worksheet);
428 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.DeleteRows, worksheet);
429 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.FormatCells, worksheet);
430 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.FormatColumns, worksheet);
431 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.FormatRows, worksheet);
432 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.InsertColumns, worksheet);
433 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.InsertHyperlinks, worksheet);
434 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.InsertRows, worksheet);
435 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.Objects, worksheet);
436 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.PivotTables, worksheet);
437 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.Scenarios, worksheet);
438 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.SelectLockedCells, worksheet);
439 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.SelectUnlockedCells, worksheet);
440 hasProtection += ManageSheetProtection(sheetProtectionNode, Worksheet.SheetProtectionValue.Sort, worksheet);
441 if (hasProtection > 0)
443 worksheet.UseSheetProtection =
true;
445 this.passwordReader.ReadXmlAttributes(sheetProtectionNode);
446 if (this.passwordReader.PasswordIsSet())
448 if (this.passwordReader is LegacyPasswordReader && (this.passwordReader as LegacyPasswordReader).ContemporaryAlgorithmDetected && (readerOptions ==
null || !readerOptions.IgnoreNotSupportedPasswordAlgorithms))
450 throw new NotSupportedContentException(
"A not supported, contemporary password algorithm for the worksheet protection was detected. Check possible packages to add support to NanoXLSX, or ignore this error by a reader option");
452 worksheet.SheetProtectionPassword.CopyFrom(this.passwordReader);
463 private static int ManageSheetProtection(XmlNode node, Worksheet.SheetProtectionValue sheetProtectionValue, Worksheet worksheet)
465 int hasProtection = 0;
466 string attributeName = Worksheet.GetSheetProtectionName(sheetProtectionValue);
467 string attribute = ReaderUtils.GetAttribute(node, attributeName);
468 if (attribute !=
null)
471 worksheet.SheetProtectionValues.Add(sheetProtectionValue);
473 return hasProtection;
481 private static void GetMergedCells(XmlDocument xmlDocument, Worksheet worksheet)
483 XmlNodeList mergedCellsNodes = xmlDocument.GetElementsByTagName(
"mergeCells");
484 if (mergedCellsNodes !=
null && mergedCellsNodes.Count > 0)
486 XmlNodeList mergedCellNodes = mergedCellsNodes[0].ChildNodes;
487 if (mergedCellNodes !=
null && mergedCellNodes.Count > 0)
489 foreach (XmlNode mergedCells
in mergedCellNodes)
491 string attribute = ReaderUtils.GetAttribute(mergedCells,
"ref");
492 if (attribute !=
null)
494 worksheet.MergeCells(
new Range(attribute));
506 private static void GetSheetFormats(XmlDocument xmlDocument, Worksheet worksheet)
508 XmlNodeList formatNodes = xmlDocument.GetElementsByTagName(
"sheetFormatPr");
509 if (formatNodes !=
null && formatNodes.Count > 0)
511 string attribute = ReaderUtils.GetAttribute(formatNodes[0],
"defaultColWidth");
512 if (attribute !=
null)
514 worksheet.DefaultColumnWidth = ParserUtils.ParseFloat(attribute);
516 attribute = ReaderUtils.GetAttribute(formatNodes[0],
"defaultRowHeight");
517 if (attribute !=
null)
519 worksheet.DefaultRowHeight = ParserUtils.ParseFloat(attribute);
529 private static void GetAutoFilters(XmlDocument xmlDocument, Worksheet worksheet)
531 XmlNodeList autoFilterNodes = xmlDocument.GetElementsByTagName(
"autoFilter");
532 if (autoFilterNodes !=
null && autoFilterNodes.Count > 0)
534 string autoFilterRef = ReaderUtils.GetAttribute(autoFilterNodes[0],
"ref");
535 if (autoFilterRef !=
null)
537 Range range =
new Range(autoFilterRef);
538 worksheet.SetAutoFilter(range.StartAddress.Column, range.EndAddress.Column);
548 private void GetColumns(XmlDocument xmlDocument, Worksheet worksheet)
550 XmlNodeList columnNodes = xmlDocument.GetElementsByTagName(
"col");
551 foreach (XmlNode columnNode
in columnNodes)
555 List<int> indices =
new List<int>();
556 string attribute = ReaderUtils.GetAttribute(columnNode,
"min");
557 if (attribute !=
null)
559 min = ParserUtils.ParseInt(attribute);
561 indices.Add(min.Value);
563 attribute = ReaderUtils.GetAttribute(columnNode,
"max");
564 if (attribute !=
null)
566 max = ParserUtils.ParseInt(attribute);
568 if (min !=
null && max.Value != min.Value)
570 for (
int i = min.Value; i <= max.Value; i++)
575 attribute = ReaderUtils.GetAttribute(columnNode,
"width");
576 float width = Worksheet.DefaultWorksheetColumnWidth;
577 if (attribute !=
null)
579 width = ParserUtils.ParseFloat(attribute);
581 attribute = ReaderUtils.GetAttribute(columnNode,
"hidden");
583 if (attribute !=
null)
585 int value = ParserUtils.ParseBinaryBool(attribute);
591 attribute = ReaderUtils.GetAttribute(columnNode,
"style");
592 Style defaultStyle =
null;
593 if (attribute !=
null && resolvedStyles.TryGetValue(attribute, out var attributeValue))
595 defaultStyle = attributeValue;
597 foreach (
int index
in indices)
599 string columnAddress = Cell.ResolveColumnAddress(index - 1);
600 if (defaultStyle !=
null)
602 worksheet.SetColumnDefaultStyle(columnAddress, defaultStyle);
605 if (width != Worksheet.DefaultWorksheetColumnWidth)
607 worksheet.SetColumnWidth(columnAddress, GetValidatedWidth(width));
611 worksheet.AddHiddenColumn(columnAddress);
622 private void ReadCell(XmlNode rowChild, Worksheet worksheet)
625 string styleNumber =
"";
626 string address =
"A1";
628 if (rowChild.LocalName.Equals(
"c", StringComparison.OrdinalIgnoreCase))
630 address = ReaderUtils.GetAttribute(rowChild,
"r");
631 type = ReaderUtils.GetAttribute(rowChild,
"t");
632 styleNumber = ReaderUtils.GetAttribute(rowChild,
"s");
633 if (rowChild.HasChildNodes)
635 foreach (XmlNode valueNode
in rowChild.ChildNodes)
637 if (valueNode.LocalName.Equals(
"v", StringComparison.OrdinalIgnoreCase))
639 value = valueNode.InnerText;
641 if (valueNode.LocalName.Equals(
"f", StringComparison.OrdinalIgnoreCase))
643 value = valueNode.InnerText;
645 if (valueNode.LocalName.Equals(
"is", StringComparison.OrdinalIgnoreCase))
647 value = valueNode.InnerText;
652 string key = ParserUtils.ToUpper(address);
653 Cell cell = ResolveCellData(value, type, styleNumber, address);
654 worksheet.AddCell(cell, address);
655 if (styleNumber !=
null)
658 this.resolvedStyles.TryGetValue(styleNumber, out style);
661 worksheet.Cells[address].SetStyle(style);
674 private Cell ResolveCellData(
string raw,
string type,
string styleNumber,
string address)
676 Cell.CellType importedType = Cell.CellType.Default;
680 rawValue = TryParseBool(raw);
681 if (rawValue !=
null)
683 importedType = Cell.CellType.Bool;
687 rawValue = GetNumericValue(raw);
688 if (rawValue !=
null)
690 importedType = Cell.CellType.Number;
694 else if (type ==
"s")
696 importedType = Cell.CellType.String;
697 rawValue = ResolveSharedString(raw);
699 else if (type ==
"str")
701 importedType = Cell.CellType.Formula;
704 else if (type ==
"inlineStr")
706 importedType = Cell.CellType.String;
709 else if (dateStyles.Contains(styleNumber) && (type ==
null || type ==
"" || type ==
"n"))
711 rawValue = GetDateTimeValue(raw, Cell.CellType.Date, out importedType);
713 else if (timeStyles.Contains(styleNumber) && (type ==
null || type ==
"" || type ==
"n"))
715 rawValue = GetDateTimeValue(raw, Cell.CellType.Time, out importedType);
719 importedType = Cell.CellType.Number;
720 rawValue = GetNumericValue(raw);
722 if (rawValue ==
null && raw ==
"")
724 importedType = Cell.CellType.Empty;
727 else if (rawValue ==
null && raw.Length > 0)
729 importedType = Cell.CellType.String;
732 Address cellAddress =
new Address(address);
733 if (readerOptions !=
null)
735 if (readerOptions.EnforcedColumnTypes.Count > 0)
737 rawValue = GetEnforcedColumnValue(rawValue, importedType, cellAddress);
739 rawValue = GetGloballyEnforcedValue(rawValue, cellAddress);
740 rawValue = GetGloballyEnforcedFlagValues(rawValue, cellAddress);
741 importedType = ResolveType(rawValue, importedType);
742 if (importedType == Cell.CellType.Date && rawValue is DateTime && (DateTime)rawValue < DataUtils.FirstAllowedExcelDate)
745 rawValue = ((DateTime)rawValue).AddDays(1);
748 return CreateCell(rawValue, importedType, cellAddress, styleNumber);
757 private static Cell.CellType ResolveType(
object value, Cell.CellType defaultType)
759 if (defaultType == Cell.CellType.Formula)
765 return Cell.CellType.Empty;
779 return Cell.CellType.Number;
781 return Cell.CellType.Date;
783 return Cell.CellType.Time;
785 return Cell.CellType.Bool;
787 return Cell.CellType.String;
797 private object GetGloballyEnforcedFlagValues(
object data, Address address)
799 if (address.Row < readerOptions.EnforcingStartRowNumber)
803 if (readerOptions.EnforceDateTimesAsNumbers)
805 if (data is DateTime)
807 data = DataUtils.GetOADateTime((DateTime)data,
true);
809 else if (data is TimeSpan)
811 data = DataUtils.GetOATime((TimeSpan)data);
814 if (readerOptions.EnforceEmptyValuesAsString && data ==
null)
827 private object GetGloballyEnforcedValue(
object data, Address address)
829 if (address.Row < readerOptions.EnforcingStartRowNumber)
833 if (readerOptions.GlobalEnforcingType == ReaderOptions.GlobalType.AllNumbersToDouble)
835 object tempDouble = ConvertToDouble(data);
836 if (tempDouble !=
null)
841 else if (readerOptions.GlobalEnforcingType == ReaderOptions.GlobalType.AllNumbersToDecimal)
843 object tempDecimal = ConvertToDecimal(data);
844 if (tempDecimal !=
null)
849 else if (readerOptions.GlobalEnforcingType == ReaderOptions.GlobalType.AllNumbersToInt)
851 object tempInt = ConvertToInt(data);
857 else if (readerOptions.GlobalEnforcingType == ReaderOptions.GlobalType.EverythingToString)
859 return ConvertToString(data);
871 private object GetEnforcedColumnValue(
object data, Cell.CellType importedTyp, Address address)
873 if (address.Row < readerOptions.EnforcingStartRowNumber)
877 if (!readerOptions.EnforcedColumnTypes.TryGetValue(address.Column, out var columnType))
881 if (importedTyp == Cell.CellType.Formula)
887 case ReaderOptions.ColumnType.Numeric:
888 return GetNumericValue(data, importedTyp);
889 case ReaderOptions.ColumnType.Decimal:
890 return ConvertToDecimal(data);
891 case ReaderOptions.ColumnType.Double:
892 return ConvertToDouble(data);
893 case ReaderOptions.ColumnType.Date:
894 return ConvertToDate(data);
895 case ReaderOptions.ColumnType.Time:
896 return ConvertToTime(data);
897 case ReaderOptions.ColumnType.Bool:
898 return ConvertToBool(data);
900 return ConvertToString(data);
909 private object ConvertToBool(
object data)
924 object tempObject = ConvertToDouble(data);
925 if (tempObject is
double)
927 double tempDouble = (double)tempObject;
928 if (
double.Equals(tempDouble, 0d))
932 else if (
double.Equals(tempDouble, 1d))
940 string tempString = (string)data;
941 bool? tempBool = TryParseBool(tempString);
942 if (tempBool !=
null)
944 return tempBool.Value;
956 private static bool? TryParseBool(
string raw)
969 if (
bool.TryParse(raw, out value))
985 private object ConvertToDouble(
object data)
987 object value = ConvertToDecimal(data);
988 if (value is decimal)
990 return Decimal.ToDouble((decimal)value);
992 else if (value is
float)
994 return Convert.ToDouble((
float)value);
1004 private object ConvertToDecimal(
object data)
1006 IConvertible converter;
1020 converter = data as IConvertible;
1021 double tempDouble = converter.ToDouble(DataUtils.InvariantCulture);
1022 if (tempDouble > (
double)decimal.MaxValue || tempDouble < (
double)decimal.MinValue)
1028 return converter.ToDecimal(DataUtils.InvariantCulture);
1037 return decimal.Zero;
1040 return new decimal(DataUtils.GetOADateTime((DateTime)data));
1042 return new decimal(DataUtils.GetOATime((TimeSpan)data));
1045 string tempString = (string)data;
1046 if (ParserUtils.TryParseDecimal(tempString, out dValue))
1050 DateTime? tempDate = TryParseDate(tempString);
1051 if (tempDate !=
null)
1053 return new decimal(DataUtils.GetOADateTime(tempDate.Value));
1055 TimeSpan? tempTime = TryParseTime(tempString);
1056 if (tempTime !=
null)
1058 return new decimal(DataUtils.GetOATime(tempTime.Value));
1070 private static object ConvertToInt(
object data)
1080 tempDouble = DataUtils.GetOADateTime((DateTime)data,
true);
1081 return ConvertDoubleToInt(tempDouble);
1083 tempDouble = DataUtils.GetOATime((TimeSpan)data);
1084 return ConvertDoubleToInt(tempDouble);
1087 int? tempInt = TryConvertDoubleToInt(data);
1088 if (tempInt !=
null)
1094 return (
bool)data ? 1 : 0;
1097 if (ParserUtils.TryParseInt((
string)data, out tempInt2))
1111 private object ConvertToDate(
object data)
1118 DateTime root = DataUtils.FirstAllowedExcelDate;
1119 TimeSpan time = (TimeSpan)data;
1120 root = root.AddDays(-1);
1121 root = root.AddHours(time.Hours);
1122 root = root.AddMinutes(time.Minutes);
1123 root = root.AddSeconds(time.Seconds);
1135 return ConvertDateFromDouble(data);
1137 DateTime? date2 = TryParseDate((
string)data);
1142 return ConvertDateFromDouble(data);
1152 private DateTime? TryParseDate(
string raw)
1156 if (readerOptions ==
null ||
string.IsNullOrEmpty(readerOptions.DateTimeFormat) || readerOptions.TemporalCultureInfo ==
null)
1158 isDateTime = DateTime.TryParse(raw, ReaderOptions.DefaultCultureInfo, DateTimeStyles.None, out dateTime);
1162 isDateTime = DateTime.TryParseExact(raw, readerOptions.DateTimeFormat, readerOptions.TemporalCultureInfo, DateTimeStyles.None, out dateTime);
1164 if (isDateTime && dateTime >= DataUtils.FirstAllowedExcelDate && dateTime <= DataUtils.LastAllowedExcelDate)
1176 private object ConvertToTime(
object data)
1181 return ConvertTimeFromDouble(data);
1194 return ConvertTimeFromDouble(data);
1196 TimeSpan? time = TryParseTime((
string)data);
1201 return ConvertTimeFromDouble(data);
1211 private TimeSpan? TryParseTime(
string raw)
1215 if (readerOptions ==
null ||
string.IsNullOrEmpty(readerOptions.TimeSpanFormat) || readerOptions.TemporalCultureInfo ==
null)
1217 isTimeSpan = TimeSpan.TryParse(raw, ReaderOptions.DefaultCultureInfo, out timeSpan);
1221 isTimeSpan = TimeSpan.TryParseExact(raw, readerOptions.TimeSpanFormat, readerOptions.TemporalCultureInfo, out timeSpan);
1223 if (isTimeSpan && timeSpan.Days >= 0 && timeSpan.Days < DataUtils.MaxOADateValue)
1238 private static object GetDateTimeValue(
string raw, Cell.CellType valueType, out Cell.CellType resolvedType)
1241 if (!ParserUtils.TryParseDouble(raw, out dValue))
1243 resolvedType = Cell.CellType.String;
1246 if ((valueType == Cell.CellType.Date && (dValue < DataUtils.MinOADateValue || dValue > DataUtils.MaxOADateValue)) || (valueType == Cell.CellType.Time && (dValue < 0.0 || dValue > DataUtils.MaxOADateValue)))
1249 resolvedType = Cell.CellType.Number;
1250 return GetNumericValue(raw);
1252 DateTime tempDate = DataUtils.GetDateFromOA(dValue);
1255 tempDate = tempDate.AddDays(1);
1257 if (valueType == Cell.CellType.Date)
1259 resolvedType = Cell.CellType.Date;
1264 resolvedType = Cell.CellType.Time;
1265 return new TimeSpan((
int)dValue, tempDate.Hour, tempDate.Minute, tempDate.Second);
1274 private object ConvertDateFromDouble(
object data)
1276 object oaDate = ConvertToDouble(data);
1277 if (oaDate is
double && (
double)oaDate < DataUtils.MaxOADateValue)
1279 DateTime date = DataUtils.GetDateFromOA((
double)oaDate);
1280 if (date >= DataUtils.FirstAllowedExcelDate && date <= DataUtils.LastAllowedExcelDate)
1293 private object ConvertTimeFromDouble(
object data)
1295 object oaDate = ConvertToDouble(data);
1296 if (oaDate is
double)
1298 double d = (double)oaDate;
1299 if (d >= DataUtils.MinOADateValue && d <= DataUtils.MaxOADateValue)
1301 DateTime date = DataUtils.GetDateFromOA(d);
1302 return new TimeSpan((
int)d, date.Hour, date.Minute, date.Second);
1313 private static int? TryConvertDoubleToInt(
object data)
1315 IConvertible converter = data as IConvertible;
1316 double dValue = converter.ToDouble(ReaderOptions.DefaultCultureInfo);
1317 if (dValue >
int.MinValue && dValue <
int.MaxValue)
1319 return converter.ToInt32(ReaderOptions.DefaultCultureInfo);
1329 private static int ConvertDoubleToInt(
object data)
1331 IConvertible converter = data as IConvertible;
1332 return converter.ToInt32(ReaderOptions.DefaultCultureInfo);
1340 private string ConvertToString(
object data)
1345 return ((
int)data).ToString(ReaderOptions.DefaultCultureInfo);
1347 return ((uint)data).ToString(ReaderOptions.DefaultCultureInfo);
1349 return ((
long)data).ToString(ReaderOptions.DefaultCultureInfo);
1351 return ((ulong)data).ToString(ReaderOptions.DefaultCultureInfo);
1353 return ((
float)data).ToString(ReaderOptions.DefaultCultureInfo);
1355 return ((
double)data).ToString(ReaderOptions.DefaultCultureInfo);
1357 return ((
bool)data).ToString(ReaderOptions.DefaultCultureInfo);
1359 return ((DateTime)data).ToString(readerOptions.DateTimeFormat, ParserUtils.InvariantCulture);
1361 return ((TimeSpan)data).ToString(readerOptions.TimeSpanFormat, ParserUtils.InvariantCulture);
1367 return data.ToString();
1377 private object GetNumericValue(
object raw, Cell.CellType importedType)
1384 switch (importedType)
1386 case Cell.CellType.String:
1387 string tempString = raw.ToString();
1388 tempObject = GetNumericValue(tempString);
1389 if (tempObject !=
null)
1393 DateTime? tempDate = TryParseDate(tempString);
1394 if (tempDate !=
null)
1396 return DataUtils.GetOADateTime(tempDate.Value);
1398 TimeSpan? tempTime = TryParseTime(tempString);
1399 if (tempTime !=
null)
1401 return DataUtils.GetOATime(tempTime.Value);
1403 tempObject = ConvertToBool(raw);
1404 if (tempObject is
bool)
1406 return (
bool)tempObject ? 1 : 0;
1409 case Cell.CellType.Number:
1411 case Cell.CellType.Date:
1412 return DataUtils.GetOADateTime((DateTime)raw);
1413 case Cell.CellType.Time:
1414 return DataUtils.GetOATime((TimeSpan)raw);
1415 case Cell.CellType.Bool:
1431 private static object GetNumericValue(
string raw)
1433 bool hasDecimalPoint = raw.Contains(
".");
1436 if (!hasDecimalPoint)
1441 bool canBeUint = ParserUtils.TryParseUint(raw, out uiValue);
1442 bool canBeInt = ParserUtils.TryParseInt(raw, out iValue);
1443 if (canBeUint && !canBeInt)
1453 bool canBeUlong = ParserUtils.TryParseUlong(raw, out ulValue);
1454 bool canBeLong = ParserUtils.TryParseLong(raw, out lValue);
1455 if (canBeUlong && !canBeLong)
1470 if (ParserUtils.TryParseDecimal(raw, out dcValue))
1473 float testFloat = decimal.ToSingle(dcValue);
1474 decimal backToDecimal = (decimal)testFloat;
1477 if (dcValue == backToDecimal)
1484 return decimal.ToDouble(dcValue);
1488 else if (ParserUtils.TryParseFloat(raw, out fValue) && fValue >=
float.MinValue && fValue <=
float.MaxValue && !
float.IsInfinity(fValue))
1492 if (ParserUtils.TryParseDouble(raw, out dValue))
1505 private float GetValidatedWidth(
float rawValue)
1507 if (rawValue < Worksheet.MinColumnWidth)
1509 if (readerOptions.EnforceStrictValidation)
1511 throw new WorksheetException($
"The worksheet contains an invalid column width (too small: {rawValue}) value. This error is ignored when disabling the reader option 'EnforceStrictValidation'");
1515 return Worksheet.MinColumnWidth;
1518 else if (rawValue > Worksheet.MaxColumnWidth)
1520 if (readerOptions.EnforceStrictValidation)
1522 throw new WorksheetException($
"The worksheet contains an invalid column width (too large: {rawValue}) value. This error is ignored when disabling the reader option 'EnforceStrictValidation'");
1526 return Worksheet.MaxColumnWidth;
1541 private float GetValidatedHeight(
float rawValue)
1543 if (rawValue < Worksheet.MinRowHeight)
1545 if (readerOptions.EnforceStrictValidation)
1547 throw new WorksheetException($
"The worksheet contains an invalid row height (too small: {rawValue}) value. Consider using the ImportOption 'EnforceValidRowDimensions' to ignore this error.");
1551 return Worksheet.MinRowHeight;
1554 else if (rawValue > Worksheet.MaxRowHeight)
1556 if (readerOptions.EnforceStrictValidation)
1558 throw new WorksheetException($
"The worksheet contains an invalid row height (too large: {rawValue}) value. Consider using the ImportOption 'EnforceValidRowDimensions' to ignore this error.");
1562 return Worksheet.MaxRowHeight;
1576 private string ResolveSharedString(
string raw)
1579 if (ParserUtils.TryParseInt(raw, out stringId))
1581 string resolvedString =
SharedStrings.ElementAtOrDefault(stringId);
1582 if (resolvedString ==
null)
1588 return resolvedString;
1602 private Cell CreateCell(
object value, Cell.CellType type, Address address,
string styleNumber =
null)
1604 Cell cell =
new Cell(value, type, address);
1605 if (styleNumber !=
null && resolvedStyles.TryGetValue(styleNumber, out var styleValue))
1607 cell.SetStyle(styleValue);