Example #1
0
        /// <summary>
        ///     Generic extension method yielding objects of specified type from table.
        /// </summary>
        /// <remarks>
        ///     Exceptions are not catched. It works on all or nothing basis.
        ///     Only primitives and enums are supported as property.
        ///     Currently supports only tables with header.
        /// </remarks>
        /// <typeparam name="T">Type to map to. Type should be a class and should have parameterless constructor.</typeparam>
        /// <param name="table">Table object to fetch</param>
        /// <param name="onCaught"></param>
        /// <param name="configurationAction"></param>
        /// <returns>An enumerable of the generating type</returns>
        public static IEnumerable <T> AsEnumerable <T>(this ExcelTable table, OnCaught <T> onCaught = null, Action <IExcelConfiguration <T> > configurationAction = null) where T : class, new()
        {
            IExcelConfiguration <T> configuration = DefaultExcelConfiguration <T> .Instance;

            configurationAction?.Invoke(configuration);

            List <KeyValuePair <int, PropertyInfo> > mapping = PrepareMappings <T>(table);

            ExcelAddress bounds = table.GetDataBounds();

            // Parse table
            for (int row = bounds.Start.Row; row <= bounds.End.Row; row++)
            {
                var item = (T)Activator.CreateInstance(typeof(T));

                foreach (KeyValuePair <int, PropertyInfo> map in mapping)
                {
                    object cell = table.WorkSheet.Cells[row, map.Key + table.Address.Start.Column].Value;

                    PropertyInfo property = map.Value;

                    try
                    {
                        TrySetProperty(item, property, cell);
                    }
                    catch (Exception ex)
                    {
                        if (!configuration.SkipCastingErrors)
                        {
                            var exceptionArgs = new ExcelTableExceptionArgs
                            {
                                ColumnName   = table.Columns[map.Key].Name,
                                ExpectedType = property.PropertyType,
                                PropertyName = property.Name,
                                CellValue    = cell,
                                CellAddress  = new ExcelCellAddress(row, map.Key + table.Address.Start.Column)
                            };

                            throw new ExcelTableConvertException($"The expected type of '{exceptionArgs.PropertyName}' property is '{exceptionArgs.ExpectedType.Name}', but the cell [{exceptionArgs.CellAddress.Address}] contains an invalid value.",
                                                                 ex, exceptionArgs
                                                                 );
                        }
                    }
                }

                onCaught?.Invoke(item, row);

                // TODO:
                if (!configuration.SkipValidationErrors)
                {
                    // Validate parsed object according to data annotations
                    item.Validate(row);
                }

                yield return(item);
            }
        }
 /// <inheritdoc />
 /// <summary>
 ///     Custom constructor that takes message, inner exception and conversion arguments
 /// </summary>
 /// <param name="message">Exception message</param>
 /// <param name="inner">Actual conversion exception catched</param>
 /// <param name="args">Information related to the circumstances of the exception</param>
 public ExcelTableConvertException(string message, Exception inner, ExcelTableExceptionArgs args)
     : base(message, inner)
 {
     Args = args;
 }