/// <summary> /// Write one entity to range /// </summary> /// <typeparam name="T">Type of entity</typeparam> /// <param name="cfg">Configuration that defines fields of entity</param> /// <param name="ent">Entity objet to be written</param> public void WriteEntity <T>(EntityConfigElement cfg, T ent) where T : class { Type t = typeof(T); foreach (FieldConfigElement field in cfg.Fields) { var pT = t.GetProperty(field.Name); if (pT != null) { // Handle this property object cellVal = pT.GetValue(ent); this[field.Range] = cellVal; } } // Handle sub collections here foreach (CollectionConfigElement colCfg in cfg.Collections) { var pColT = t.GetProperty(colCfg.Name); if (pColT != null) { var list = pColT.GetValue(ent) as IList; if (list == null) { throw new InvalidOperationException( String.Format( "To support write embeded collection, property {0} must be type that implements IList interface and must not be null!", colCfg.Name)); } var listType = list.GetType(); if (!listType.IsGenericType) { throw new InvalidOperationException( String.Format("Type of property {0} must be a generic collection!", colCfg.Name)); } // Get the item type if (listType.GenericTypeArguments.Count() != 1) { throw new InvalidOperationException( String.Format( "Type of property {0} must be a generic collection with only one type parameter!", colCfg.Name)); } var itemType = listType.GenericTypeArguments[0]; var writterType = typeof(ExcelEntityWriter <>); Type[] typeArgs = { itemType }; var wType = writterType.MakeGenericType(typeArgs); var writter = Activator.CreateInstance(wType, _doc, colCfg, this); var writeFunc = wType.GetMethod("Write"); foreach (var item in list) { writeFunc.Invoke(writter, new object[] { item }); } } } }
/// <summary> /// Write one object to excel at current location and move to next location for next object /// </summary> /// <param name="obj"></param> public void Write(T obj) { // Calculate the entity range if (_entityRange == null) { // No entity range calculated, this is the first entity if (_collectionRange == null) { // First time, calculate collection range if (_parentRange != null) { _collectionRange = _parentRange.GetSubRange(_colCfg.Range); } else { _collectionRange = _doc.GetRange(_colCfg.Range); } if (_collectionRange == null) { throw new InvalidDataException(String.Format("Cannot find valid range for collection of {0}!", typeof(T).FullName)); } } EntityConfigElement entCfg = _colCfg.ItemTemplate.Entity; String entRef = _collectionRange.Sheet.ExpandToSheetBound(entCfg.Range); String entRange = ExcelOpenXMLHelper.CalculateEntityRange(_collectionRange, entRef, 0, _colCfg.Orientation.Equals("vertical", StringComparison.OrdinalIgnoreCase)); if (entRange == null) { throw new NoMoreEntityException(typeof(T)); } _entityRange = _collectionRange.GetSubRange(entRange); if (_entityRange == null) { throw new NoMoreEntityException(typeof(T)); } } // Write object to range _entityRange.WriteEntity(_colCfg.ItemTemplate.Entity, obj); // Move range to next if (_colCfg.Orientation.Equals("vertical", StringComparison.OrdinalIgnoreCase)) { // Move vertically int h = _entityRange.Height; _entityRange.Move(0, h); } else { // Move horizontally int w = _entityRange.Width; _entityRange.Move(w, 0); } }
/// <summary> /// Read entity at specific index /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> protected T ReadCurrent() { // Get range of collection if (_collectionRange == null) { if (_parentRange != null) { _collectionRange = _parentRange.GetSubRange(_colCfg.Range); } else { _collectionRange = _doc.GetRange(_colCfg.Range); } if (_collectionRange == null) { throw new InvalidDataException(String.Format("Cannot find valid range for collection of {0}!", typeof(T).FullName)); } // For dynamic collection, it's possible to use a defined name to mark the end of co } // Calculate range of current entity if (_entityRange == null) { EntityConfigElement entCfg = _colCfg.ItemTemplate.Entity; String entRef = _collectionRange.Sheet.ExpandToSheetBound(entCfg.Range); String entRange = ExcelOpenXMLHelper.CalculateEntityRange(_collectionRange, entRef, _currentIdx, _colCfg.Orientation.Equals("vertical", StringComparison.OrdinalIgnoreCase), _endBefore); if (entRange == null) { throw new NoMoreEntityException(typeof(T)); } _entityRange = _collectionRange.GetSubRange(entRange); if (_entityRange == null) { throw new NoMoreEntityException(typeof(T)); } } // Read data for entity var ent = _entityRange.ReadEntity <T>(_colCfg.ItemTemplate.Entity); if (ent == null) { throw new NoMoreEntityException(typeof(T)); } return(ent); }
/// <summary> /// Read one entity from range /// </summary> /// <typeparam name="T">Type of entity</typeparam> /// <param name="cfg">Configuration that defines fields of entity</param> /// <returns></returns> public T ReadEntity <T>(EntityConfigElement cfg) where T : class, new() { var ent = new T(); Type t = typeof(T); bool entExist = false; foreach (FieldConfigElement field in cfg.Fields) { var pT = t.GetProperty(field.Name); if (pT != null) { // Handle this property object cellVal = null; bool cellExist = true; try { cellVal = this[field.Range]; } catch (CellNotExistException) { // Cell not exist cellExist = false; } if (cellExist && cellVal != null) { try { pT.SetValue(ent, ConvertExcelValue(cellVal, pT.PropertyType)); entExist = true; } catch (Exception err) { throw new InvalidDataException(String.Format("Cannot set property {0} to {1}! Err:{2}", field.Name, cellVal, err.Message)); } } } } // Handle sub collections here foreach (CollectionConfigElement colCfg in cfg.Collections) { var pColT = t.GetProperty(colCfg.Name); if (pColT != null) { var list = pColT.GetValue(ent) as IList; if (list == null) { throw new InvalidOperationException( String.Format( "To support load embeded collection, property {0} must be type that implements IList interface and must not be null!", colCfg.Name)); } var listType = list.GetType(); if (!listType.IsGenericType) { throw new InvalidOperationException( String.Format("Type of property {0} must be a generic collection!", colCfg.Name)); } // Get the item type if (listType.GenericTypeArguments.Count() != 1) { throw new InvalidOperationException( String.Format( "Type of property {0} must be a generic collection with only one type parameter!", colCfg.Name)); } var itemType = listType.GenericTypeArguments[0]; // Instantiate enumerable for item type var enumType = typeof(ExcelEntityEnumerable <>); Type[] typeArgs = { itemType }; var eType = enumType.MakeGenericType(typeArgs); // Embeded collection may has its ranged defined as relative reference, so we should pass the range of main entity // as a parent container. var enumerable = Activator.CreateInstance(eType, _doc, colCfg, this) as IEnumerable; if (enumerable == null) { throw new InvalidOperationException( String.Format("Cannot create ExcelEntityEnumerable<{0}>!", itemType.Name)); } foreach (var item in enumerable) { list.Add(item); } } } return((cfg.AllowNull || entExist) ? ent : null); }