/// <summary> /// Populate missing or incomplete properties from model metadata. /// </summary> /// <param name="fieldInfo">The <c>ExcelColumnInfoCollection</c> to populate.</param> /// <param name="itemType">The type of item whose metadata this is being populated from.</param> /// <param name="data">The collection of values being serialised. (Not used, provided for use by derived /// types.)</param> protected virtual void PopulateFieldInfoFromMetadata(ExcelColumnInfoCollection fieldInfo, Type itemType, IEnumerable<object> data) { // Populate missing attribute information from metadata. var metadata = ModelMetadataProviders.Current.GetMetadataForType(null, itemType); if (metadata != null && metadata.Properties != null) { foreach (var modelProp in metadata.Properties) { var propertyName = modelProp.PropertyName; if (!fieldInfo.Contains(propertyName)) continue; var field = fieldInfo[propertyName]; var attribute = field.ExcelAttribute; if (!field.IsExcelHeaderDefined) field.Header = modelProp.DisplayName ?? propertyName; if (attribute != null && attribute.UseDisplayFormatString) field.FormatString = modelProp.DisplayFormatString; } } }
public SqadXlsxSheetBuilder(string sheetName, bool isReferenceSheet = false) { _isReferenceSheet = isReferenceSheet; _sheetTables = new List <DataTable>(); _currentTable = new DataTable(sheetName); _sheetTables.Add(_currentTable); SheetColumns = new ExcelColumnInfoCollection(); }
public void AppendColumnHeaderRow(ExcelColumnInfoCollection columns) { foreach (var col in columns) { string headerName = col.IsExcelHeaderDefined ? col.Header : col.PropertyName; var dc = new DataColumn(headerName, typeof(ExcelCell)); if (col.IsHidden) { dc.ColumnMapping = MappingType.Hidden; } _currentTable.Columns.Add(dc); } }
protected SqadXlsxSheetBuilderBase(string sheetName, bool isReferenceSheet = false, bool isPreservationSheet = false, bool isHidden = false, bool shouldAutoFit = true) { IsReferenceSheet = isReferenceSheet; IsPreservationSheet = isPreservationSheet; IsHidden = isHidden; _shouldAutoFit = shouldAutoFit; SheetTables = new List <DataTable>(); CurrentTable = new DataTable(sheetName); SheetTables.Add(CurrentTable); SheetColumns = new ExcelColumnInfoCollection(); }
/// <summary> /// Populate missing or incomplete properties from model metadata. /// </summary> /// <param name="fieldInfo">The <c>ExcelColumnInfoCollection</c> to populate.</param> /// <param name="itemType">The type of item whose metadata this is being populated from.</param> /// <param name="data">The collection of values being serialised. (Not used, provided for use by derived /// types.)</param> protected virtual void PopulateFieldInfoFromMetadata(ExcelColumnInfoCollection fieldInfo, Type itemType, object data) { // Populate missing attribute information from metadata. var metadata = _modelMetaDataProvider.GetMetadataForType(itemType); if (metadata != null && metadata.Properties != null) { foreach (var modelProp in metadata.Properties) { var propertyName = modelProp.PropertyName; if (!fieldInfo.Contains(propertyName)) { continue; } var field = fieldInfo[propertyName]; field.PropertyType = modelProp.ModelType; if (field.PropertyType.IsGenericType && field.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { field.PropertyType = field.PropertyType.GetGenericArguments()[0]; } var attribute = field.ExcelColumnAttribute; if (!field.IsExcelHeaderDefined) { field.Header = modelProp.DisplayName ?? propertyName; } if (attribute != null && attribute.UseDisplayFormatString) { field.FormatString = modelProp.DisplayFormatString; } } } }
/// <summary> /// Get the <c>ExcelColumnInfo</c> for all members of a class. /// </summary> /// <param name="itemType">Type of item being serialised.</param> /// <param name="data">The collection of values being serialised. (Not used, provided for use by derived /// types.)</param> public virtual ExcelColumnInfoCollection GetExcelColumnInfo(Type itemType, IEnumerable<object> data) { var fields = GetSerialisableMemberNames(itemType, data); var properties = GetSerialisablePropertyInfo(itemType, data); var fieldInfo = new ExcelColumnInfoCollection(); // Instantiate field names and fieldInfo lists with serialisable members. foreach (var field in fields) { var propName = field; var prop = properties.FirstOrDefault(p => p.Name == propName); if (prop == null) continue; fieldInfo.Add(new ExcelColumnInfo(field, util.GetAttribute<ExcelColumnAttribute>(prop))); } PopulateFieldInfoFromMetadata(fieldInfo, itemType, data); return fieldInfo; }
/// <summary> /// Get the <c>ExcelColumnInfo</c> for all members of a class. /// </summary> /// <param name="itemType">Type of item being serialised.</param> /// <param name="data">The collection of values being serialised. (Not used, provided for use by derived /// types.)</param> public virtual ExcelColumnInfoCollection GetExcelColumnInfo(Type itemType, object data, string namePrefix = "", bool isComplexColumn = false) { var fieldInfo = new ExcelColumnInfoCollection(); if (itemType.Name.StartsWith("Dictionary")) { var prefix = namePrefix + "_Dict_"; fieldInfo.Add(new ExcelColumnInfo(prefix, null, new ExcelColumnAttribute(), null)); return(fieldInfo); } var fields = GetSerialisableMemberNames(itemType, data); var properties = GetSerialisablePropertyInfo(itemType, data); // Instantiate field names and fieldInfo lists with serialisable members. foreach (var field in fields) { var prop = properties.FirstOrDefault(p => p.Name == field); if (prop == null) { continue; } Type propertyType = prop.PropertyType; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { propertyType = propertyType.GetGenericArguments()[0]; } ExcelColumnAttribute attribute = FormatterUtils.GetAttribute <ExcelColumnAttribute>(prop); if (attribute != null) { string prefix = string.IsNullOrEmpty(namePrefix) == false ? $"{namePrefix}:{prop.Name}" : prop.Name; if (propertyType.Name.StartsWith("List")) { Type typeOfList = FormatterUtils.GetEnumerableItemType(propertyType); //if (FormatterUtils.IsSimpleType(typeOfList)) //{ // fieldInfo.Add(new ExcelColumnInfo(prefix, typeOfList, attribute, null)); //} //else if (typeOfList.FullName.EndsWith("CustomFieldModel") || typeOfList.Name.StartsWith("OverrideProperty")) { prefix += "_CustomField_"; fieldInfo.Add(new ExcelColumnInfo(prefix, null, attribute, null)); } else { prefix += "_List_"; fieldInfo.Add(new ExcelColumnInfo(prefix, null, attribute, null)); //ExcelColumnInfoCollection columnCollection = GetExcelColumnInfo(typeOfList, null, prefix, true); //foreach (var subcolumn in columnCollection) // fieldInfo.Add(subcolumn); } } else if (propertyType.Name.EndsWith("CustomFieldModel") || propertyType.Name.StartsWith("OverrideProperty")) { prefix += "_CustomField_Single_"; fieldInfo.Add(new ExcelColumnInfo(prefix, null, attribute, null)); } else if (propertyType.Name.StartsWith("Dictionary")) { prefix += "_Dict_"; fieldInfo.Add(new ExcelColumnInfo(prefix, null, attribute, null)); } else if (!FormatterUtils.IsSimpleType(propertyType)) { ExcelColumnInfoCollection columnCollection = GetExcelColumnInfo(propertyType, null, prefix, true); foreach (var subcolumn in columnCollection) { fieldInfo.Add(subcolumn); } } else { string propertyName = isComplexColumn ? $"{namePrefix}:{field}" : field; string displayName = propertyName; if (attribute.DoNotUsePropertyName) { attribute.Header = namePrefix; } bool columnAlreadyadded = fieldInfo.Any(a => a.PropertyName == propertyName); if (!columnAlreadyadded) { if (FormatterUtils.IsExcelSupportedType(propertyType)) { fieldInfo.Add(new ExcelColumnInfo(propertyName, propertyType, attribute, null)); } else { fieldInfo.Add(new ExcelColumnInfo(propertyName, typeof(string), attribute, null)); } } } } } PopulateFieldInfoFromMetadata(fieldInfo, itemType, data); return(fieldInfo); }
public void Serialize(Type itemType, object value, IXlsxDocumentBuilder document, string sheetName = null, string columnPrefix = null, XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder sheetBuilderOverride = null) { ExcelColumnInfoCollection columnInfo = _columnResolver.GetExcelColumnInfo(itemType, value, sheetName); XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder sheetBuilder = null; if (sheetName == null) { var sheetAttribute = itemType.GetCustomAttributes(true).SingleOrDefault(s => s is ExcelSheetAttribute); sheetName = sheetAttribute != null ? (sheetAttribute as ExcelSheetAttribute).SheetName : itemType.Name; } if (columnInfo.Any()) { if (sheetBuilderOverride == null) { sheetBuilder = document.GetSheetByName(sheetName) as XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder; } else { sheetBuilder = sheetBuilderOverride; } if (sheetBuilder == null) { sheetBuilder = new XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder(sheetName); //Move this to attribute hidden property //if (new List<string>() { "Formulas", "LeftTableColumn", "Cells" }.Contains(sheetName)) //{ // sheetBuilder.IsHidden = true; //} document.AppendSheet(sheetBuilder); } //Convert Dictionary Column foreach (var col in columnInfo) { if (col.PropertyName.EndsWith("_Dict_")) { string columnName = col.PropertyName.Replace("_Dict_", ""); object colValueDict = null; if (sheetName == col.PropertyName.Replace("_Dict_", "")) { colValueDict = value; } else { colValueDict = GetFieldOrPropertyValue(value, col.PropertyName.Replace("_Dict_", "")); } if (columnName.Contains(":") && (colValueDict == null || (colValueDict != null && string.IsNullOrEmpty(colValueDict.ToString())))) { colValueDict = GetFieldPathValue(value, columnName); } if (colValueDict == null || string.IsNullOrEmpty(colValueDict.ToString())) { continue; } object dictionaryKeys = colValueDict.GetType().GetProperty("Keys").GetValue(colValueDict); int count = 0; foreach (var key in (System.Collections.IEnumerable)dictionaryKeys) { ExcelColumnInfo temlKeyColumn = col.Clone() as ExcelColumnInfo; temlKeyColumn.PropertyName = temlKeyColumn.PropertyName.Replace("_Dict_", $":Key:{count}"); sheetBuilder.AppendColumnHeaderRowItem(temlKeyColumn); var currentItem = colValueDict.GetType().GetProperty("Item").GetValue(colValueDict, new object[] { key }); if (FormatterUtils.IsSimpleType(currentItem.GetType())) { ExcelColumnInfo temlValueColumn = col.Clone() as ExcelColumnInfo; temlValueColumn.PropertyName = temlValueColumn.PropertyName.Replace("_Dict_", $":Value:{count}"); sheetBuilder.AppendColumnHeaderRowItem(temlValueColumn); } else { string path = col.PropertyName.Replace("_Dict_", $":Value:{count}"); this.Serialize(currentItem.GetType(), value, document, sheetName, path, sheetBuilderOverride); } count++; } } else if (col.PropertyName.EndsWith("_List_")) { string columnName = col.PropertyName.Replace("_List_", ""); List <object> colListValue = GetFieldOrPropertyValue(value, col.PropertyName.Replace("_List_", "")) as List <object>; if (columnName.Contains(":") && (colListValue == null || (colListValue != null && string.IsNullOrEmpty(colListValue.ToString())))) { colListValue = GetFieldPathValue(value, columnName) as List <object>; } if (colListValue == null) { continue; } int dictColumnCount = colListValue.Count(); for (int i = 0; i < dictColumnCount; i++) { string listColumnPrefix = col.PropertyName.Replace("_List_", $":{i}"); if (FormatterUtils.IsSimpleType(colListValue[i].GetType())) { ExcelColumnInfo colToAppend = (ExcelColumnInfo)col.Clone(); colToAppend.PropertyName = listColumnPrefix; sheetBuilder.AppendColumnHeaderRowItem(colToAppend); } else { this.Serialize(colListValue[i].GetType(), colListValue[i], document, null, listColumnPrefix, sheetBuilder); } } } else if (col.PropertyName.EndsWith("_CustomField_") || col.PropertyName.EndsWith("_CustomField_Single_")) { string columnName = col.PropertyName.Replace("_CustomField_", "").Replace("Single_", ""); List <object> colCustomFields = GetFieldOrPropertyValue(value, columnName) as List <object>; if (columnName.Contains(":") && (colCustomFields == null || (colCustomFields != null && string.IsNullOrEmpty(colCustomFields.ToString())))) { colCustomFields = GetFieldPathValue(value, columnName) as List <object>; } if (colCustomFields == null) { continue; } foreach (var customField in colCustomFields) { int customFieldId = ((dynamic)customField).ID; bool isActual = ((dynamic)customField).Actual; ExcelColumnInfo temlKeyColumn = col.Clone() as ExcelColumnInfo; string propetyActual = isActual ? ":Actual" : string.Empty; string customFieldDef = _staticValuesResolver.GetCustomFieldName(customFieldId); if (col.PropertyName.EndsWith("_CustomField_Single_")) { customFieldDef = string.Empty; temlKeyColumn.PropertyName = temlKeyColumn.PropertyName.Replace("_CustomField_Single_", $"{propetyActual}"); temlKeyColumn.ExcelColumnAttribute.Header = temlKeyColumn.Header = temlKeyColumn.PropertyName; } else { temlKeyColumn.PropertyName = temlKeyColumn.PropertyName.Replace("_CustomField_", $"{propetyActual}:{customFieldId}"); temlKeyColumn.ExcelColumnAttribute.Header = temlKeyColumn.Header = temlKeyColumn.PropertyName + ":" + customFieldDef; } sheetBuilder.AppendColumnHeaderRowItem(temlKeyColumn); } } else { if (columnPrefix != null) { ExcelColumnInfo temlKeyColumn = col.Clone() as ExcelColumnInfo; temlKeyColumn.PropertyName = $"{columnPrefix}:{temlKeyColumn.PropertyName}"; sheetBuilder.AppendColumnHeaderRowItem(temlKeyColumn); } else { sheetBuilder.AppendColumnHeaderRowItem(col); } } } } //if its recursive do not populate rows and return to parent if (columnPrefix != null) { return; } if (sheetName != null && sheetBuilder == null) { sheetBuilder = (XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder)document.GetSheetByName(sheetName); } //adding rows data if (value != null) { var columns = columnInfo.Keys.ToList(); if (value is IEnumerable <object> && (value as IEnumerable <object>).Count() > 0) { foreach (var dataObj in value as IEnumerable <object> ) { PopulateRows(columns, dataObj, sheetBuilder, columnInfo, document); var deepSheetsInfo = _sheetResolver.GetExcelSheetInfo(itemType, dataObj); PopulateInnerObjectSheets(deepSheetsInfo, document, itemType); } } else if (!(value is IEnumerable <object>)) { PopulateRows(columns, value, sheetBuilder, columnInfo, document); var sheetsInfo = _sheetResolver.GetExcelSheetInfo(itemType, value); PopulateInnerObjectSheets(sheetsInfo, document, itemType); } } if (sheetBuilder != null) { sheetBuilder.ShouldAddHeaderRow = true; } }
private void PopulateRows(List <string> columns, object value, XlsxExportImport.Base.Builders.SqadXlsxSheetBuilder sheetBuilder, ExcelColumnInfoCollection columnInfo = null, IXlsxDocumentBuilder document = null, List <ExcelCell> rowOverride = null) { if (sheetBuilder == null) { return; } List <ExcelCell> row = new List <ExcelCell>(); if (rowOverride != null) { row = rowOverride; } for (int i = 0; i <= columns.Count - 1; i++) { string columnName = columns[i]; if (columnName.EndsWith("_Dict_")) { columnName = columnName.Replace("_Dict_", ""); object dictionaryObj = null; if (sheetBuilder.GetCurrentTableName == columnName) { dictionaryObj = value; } else if (columnName.Contains(":")) { dictionaryObj = GetFieldPathValue(value, columnName); } else { dictionaryObj = (Dictionary <int, double>)GetFieldOrPropertyValue(value, columnName); } if (dictionaryObj == null || string.IsNullOrEmpty(dictionaryObj.ToString())) { continue; } object dictionaryKeys = dictionaryObj.GetType().GetProperty("Keys").GetValue(dictionaryObj); int colCount = 0; foreach (var key in (System.Collections.IEnumerable)dictionaryKeys) { ExcelCell keyCell = new ExcelCell(); keyCell.CellHeader = columnName + $":Key:{colCount}"; keyCell.CellValue = key; ExcelColumnInfo info = null; if (columnInfo != null) { info = columnInfo[i]; CreateReferenceCell(info, columnName, document, ref keyCell); } row.Add(keyCell); var currentItem = dictionaryObj.GetType().GetProperty("Item").GetValue(dictionaryObj, new object[] { key }); if (FormatterUtils.IsSimpleType(currentItem.GetType())) { ExcelCell valueCell = new ExcelCell(); valueCell.CellHeader = columnName + $":Value:{colCount}"; valueCell.CellValue = currentItem; row.Add(valueCell); } else { string path = columnName + $":Value:{colCount}"; ExcelColumnInfoCollection listInnerObjectColumnInfo = _columnResolver.GetExcelColumnInfo(currentItem.GetType(), currentItem, path, true); PopulateRows(listInnerObjectColumnInfo.Keys.ToList(), currentItem, sheetBuilder, listInnerObjectColumnInfo, document, row); } colCount++; } } else if (columnName.EndsWith("_List_")) { columnName = columnName.Replace("_List_", ""); List <object> listValue = new List <object>(); if (columnName.Contains(":")) { var valueObject = GetFieldPathValue(value, columnName); if (valueObject != null && string.IsNullOrEmpty(valueObject.ToString()) == false) { listValue = (List <object>)valueObject; } } else { listValue = (List <object>)GetFieldOrPropertyValue(value, columnName); } int colCount = 0; foreach (var kv in listValue) { string listColumnPrefix = columnName + $":{colCount}"; if (FormatterUtils.IsSimpleType(kv.GetType())) { ExcelCell listValueCell = new ExcelCell(); listValueCell.CellHeader = listColumnPrefix; listValueCell.CellValue = kv; row.Add(listValueCell); } else { ExcelColumnInfoCollection listInnerObjectColumnInfo = _columnResolver.GetExcelColumnInfo(kv.GetType(), kv, listColumnPrefix, true); PopulateRows(listInnerObjectColumnInfo.Keys.ToList(), kv, sheetBuilder, listInnerObjectColumnInfo, document, row); } colCount++; } } else if (columnName.EndsWith("_CustomField_") || columnName.EndsWith("_CustomField_Single_")) { bool isSingleValue = columnName.Contains("Single_"); columnName = columnName.Replace("_CustomField_", "").Replace("Single_", ""); List <object> customFields = null; if (columnName.Contains(":")) { var valueObject = GetFieldPathValue(value, columnName); if (valueObject != null && string.IsNullOrEmpty(valueObject.ToString()) == false) { customFields = (List <object>)valueObject; } } else { customFields = (List <object>)GetFieldOrPropertyValue(value, columnName); } if (customFields == null) { continue; } //need to get all custom columns List <ExcelColumnInfo> allCustomColumns = null; if (isSingleValue) { allCustomColumns = sheetBuilder.SheetColumns.Where(w => w.PropertyName == columnName).ToList(); } else { allCustomColumns = sheetBuilder.SheetColumns.Where(w => w.PropertyName.StartsWith(columnName)).ToList(); } var objID = GetFieldOrPropertyValue(value, "ID"); foreach (var customColumn in allCustomColumns) { object objectCustomField = customFields.Where(w => customColumn.PropertyName.EndsWith($":{((dynamic)w).ID}")).Where(w => customColumn.PropertyName.Contains("Actual") ? ((dynamic)w).Actual == true : ((dynamic)w).Actual == false).FirstOrDefault(); ExcelCell customValueHeaderCell = new ExcelCell(); if (objectCustomField == null && !isSingleValue) { customValueHeaderCell.IsLocked = true; customValueHeaderCell.CellHeader = customColumn.Header; customValueHeaderCell.CellValue = "n/a"; } else { dynamic customFieldItem = (dynamic)objectCustomField; string isActualText = string.Empty; string columnNameCombined = string.Empty; if (isSingleValue) { isActualText = columnName.Contains("Actual") ? ":Actual" : string.Empty; columnNameCombined = $"{columnName}{isActualText}"; customFieldItem = (dynamic)customFields.First(); } else { isActualText = customFieldItem.Actual ? ":Actual" : string.Empty; columnNameCombined = $"{columnName}{isActualText}:{customFieldItem.ID}"; } customValueHeaderCell.CellHeader = customColumn.Header; if (customFieldItem is CustomFieldModel) { if (!String.IsNullOrEmpty((customFieldItem as CustomFieldModel).Key)) { ExcelCell keyPreservationCell = new ExcelCell(); keyPreservationCell.CellHeader = $"{columnNameCombined}:Key:{objID}"; keyPreservationCell.CellValue = customFieldItem.Key?.ToString(); CreatePreserveCell(keyPreservationCell, document); } } ExcelCell valuePreservationCell = new ExcelCell(); valuePreservationCell.CellHeader = $"{columnNameCombined}:Value:{objID}"; if (customFieldItem != null) { valuePreservationCell.CellValue = customFieldItem.Value; customValueHeaderCell.CellValue = customFieldItem.Value; if (customFieldItem.Override != null) { customValueHeaderCell.CellValue = customFieldItem.Override; } } if (valuePreservationCell.CellValue != null && valuePreservationCell.CellValue.GetType() == typeof(DateTime)) { valuePreservationCell.CellValue = valuePreservationCell.CellValue.ToString(); } if (customValueHeaderCell.CellValue != null && customValueHeaderCell.CellValue.GetType() == typeof(DateTime)) { customValueHeaderCell.CellValue = customValueHeaderCell.CellValue.ToString(); } CreatePreserveCell(valuePreservationCell, document); ExcelCell overridePreservationCell = new ExcelCell(); overridePreservationCell.CellHeader = $"{columnNameCombined}:Override:{objID}"; overridePreservationCell.CellValue = customFieldItem.Override?.ToString(); CreatePreserveCell(overridePreservationCell, document); ExcelCell textPreservationCell = new ExcelCell(); textPreservationCell.CellHeader = $"{columnNameCombined}:Text:{objID}"; textPreservationCell.CellValue = customFieldItem.Text; CreatePreserveCell(textPreservationCell, document); ExcelCell hiddenTextPreservationCell = new ExcelCell(); hiddenTextPreservationCell.CellHeader = $"{columnNameCombined}:HiddenText:{objID}"; hiddenTextPreservationCell.CellValue = $"\"{customFieldItem.HiddenText}\""; CreatePreserveCell(hiddenTextPreservationCell, document); try { if (customFieldItem is CustomFieldModel && (customFieldItem as CustomFieldModel).ValueMix != null) { foreach (var valueM in (customFieldItem as CustomFieldModel).ValueMix) { string valueMKey = valueM.Key; decimal valueMValue = valueM.Value; ExcelCell mixedPropertyPreservationCell = new ExcelCell(); mixedPropertyPreservationCell.CellHeader = $"{columnNameCombined}:ValueMix:{valueM.Key}:{objID}"; mixedPropertyPreservationCell.CellValue = $"\"{valueM.Value.ToString()}\""; CreatePreserveCell(mixedPropertyPreservationCell, document); } } } catch (Exception ex) { string s = ex.Message; } ExcelCell commonPropertyPreservationCell = new ExcelCell(); commonPropertyPreservationCell.CellHeader = $"{columnNameCombined}:Common:{objID}"; commonPropertyPreservationCell.CellValue = $"\"{customFieldItem.Common}\""; CreatePreserveCell(commonPropertyPreservationCell, document); } row.Add(customValueHeaderCell); } } else { ExcelCell cell = new ExcelCell(); cell.CellHeader = columnName; var cellValue = GetFieldOrPropertyValue(value, columnName); if (columnName.Contains(":") && (cellValue == null || (cellValue != null && string.IsNullOrEmpty(cellValue.ToString())))) { cellValue = GetFieldPathValue(value, columnName); } ExcelColumnInfo info = null; if (columnInfo != null) { info = columnInfo[i]; CreateReferenceCell(info, columnName, document, ref cell); } if (cellValue != null) { cell.CellValue = FormatCellValue(cellValue, info); } if (info != null) { if (info.IsExcelHeaderDefined) { cell.CellHeader = info.Header; } } row.Add(cell); } } if (row.Count() > 0 && rowOverride == null) { sheetBuilder.AppendRow(row.ToList()); } }