예제 #1
0
 public static Workbook Merge(this Workbook workbook, WorkbookSheet sheet, bool softMerge = true)
 {
     return(Merge(workbook, new Workbook(string.Empty, new List <WorkbookSheet>()
     {
         sheet
     }), softMerge));
 }
예제 #2
0
        private async Task <KeyValuePair <Type, IList> > ManualMapType(Type type, WorkbookSheet sheet)
        {
            await Task.Delay(0).ConfigureAwait(false);

            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                         .Where(f => f.IsDefined(typeof(FieldMappingAttribute)));

            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                             .Where(f => f.IsDefined(typeof(FieldMappingAttribute)));


            List <object> values = new List <object>(sheet.Rows.Count - 1);

            for (int r = 1; r < sheet.Rows.Count; r++)
            {
                var    row = sheet.Rows[r];
                object obj = Activator.CreateInstance(type);
                foreach (FieldInfo field in fields)
                {
                    FieldInfo fieldInfo            = type.GetField(field.Name);
                    string    lookingForColumnName =
                        fieldInfo.GetCustomAttribute <FieldMappingAttribute>().WorkbookHeader;

                    if (sheet.TryToGetColumnIndexByName(lookingForColumnName, out int value))
                    {
                        if (!ReflectionParser.SetValue(fieldInfo, obj, row[value].Value))
                        {
                            throw new Exception($"Field '{fieldInfo.Name}' in type '{type.FullName}' doesn't match the type of data in WorkbookSheet '{sheet.Name}' in column '{value}'");
                        }
                    }
                    else
                    {
                        throw new Exception($"In workbooksheet '{sheet.Name}' there is no such a column like '{lookingForColumnName}' defined in '{type.FullName}' on field '{fieldInfo.Name}'");
                    }
                }
                foreach (PropertyInfo property in properties)
                {
                    PropertyInfo p = type.GetProperty(property.Name);
                    string       lookingForColumnName =
                        p.GetCustomAttribute <FieldMappingAttribute>().WorkbookHeader;

                    if (sheet.TryToGetColumnIndexByName(lookingForColumnName, out int value))
                    {
                        if (!ReflectionParser.SetValue(p, obj, row[value].Value))
                        {
                            throw new Exception($"Property '{p.Name}' in type '{type.FullName}' doesn't match the type of data in WorkbookSheet '{sheet.Name}' in column '{value}'");
                        }
                    }
                    else
                    {
                        throw new Exception($"In workbooksheet '{sheet.Name}' there is no such a column like '{lookingForColumnName}' defined in '{type.FullName}' on property '{p.Name}'");
                    }
                }
                values.Add(obj);
            }
            return(new KeyValuePair <Type, IList>(type, values));
        }
예제 #3
0
        private async Task <KeyValuePair <Type, IList> > AutoMapType(Type type, WorkbookSheet sheet)
        {
            await Task.Delay(0).ConfigureAwait(false);

            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                         .Where(w => sheet.WorkbookHeader.Titles.Contains(w.Name));

            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                             .Where(w => sheet.WorkbookHeader.Titles.Contains(w.Name));

            // Iterate from 1 because header is on the index 0.
            List <object> values = new List <object>(sheet.Rows.Count - 1);

            for (int r = 1; r < sheet.Rows.Count; r++)
            {
                var    row = sheet.Rows[r];
                object obj = Activator.CreateInstance(type);
                foreach (FieldInfo field in fields)
                {
                    FieldInfo fieldInfo = type.GetField(field.Name);
                    if (sheet.TryToGetColumnIndexByName(fieldInfo.Name, out int value))
                    {
                        // If we can cast type
                        if (!ReflectionParser.SetValue(fieldInfo, obj, row[value].Value))
                        {
                            throw new Exception(
                                      $"Field '{fieldInfo.Name}' in type '{type.FullName}' doesn't match the type of data in WorkbookSheet '{sheet.Name}' in column '{value}'");
                        }
                    }
                }

                foreach (PropertyInfo property in properties)
                {
                    PropertyInfo p = type.GetProperty(property.Name);
                    if (sheet.TryToGetColumnIndexByName(p.Name, out int value))
                    {
                        if (!ReflectionParser.SetValue(p, obj, row[value].Value))
                        {
                            throw new Exception(
                                      $"Property '{p.Name}' in type '{type.FullName}' doesn't match the type of data in WorkbookSheet '{sheet.Name}' in column '{value}'");
                        }
                    }
                }

                values.Add(obj);
            }

            return(new KeyValuePair <Type, IList>(type, values));
        }
예제 #4
0
        /// <summary>
        /// Map all the types decorated by <see cref="ClassMappingAttribute"/> from given workbooks files.
        /// </summary>
        /// <param name="workbookPaths">VALIDATED excel workbook paths.</param>
        /// <returns>IEnumerable dictionary with all the types and values.</returns>
        public async Task <WorkbookClassMapperResult> MapTypes(string[] workbookPaths)
        {
            Workbook[] workbooks = new Workbook[workbookPaths.Length];

            for (int i = 0; i < workbookPaths.Length; i++)
            {
                workbooks[i] = await Workbook.CreateFromExcel(workbookPaths[i], workbookPaths[i]).ConfigureAwait(false);
            }

            var decoratedClasses = AppDomain.CurrentDomain.GetAssemblies()
                                   .SelectMany(a => a.GetTypes())
                                   .Where(t => t.IsDefined(typeof(ClassMappingAttribute)))
                                   .Select(t =>
            {
                var attribute = t.GetCustomAttribute <ClassMappingAttribute>();
                return(new TypeData(t, attribute.Automapping, attribute.WorkbookPath, attribute.SheetName));
            });

            Dictionary <Type, IList> resultInput = new Dictionary <Type, IList>(decoratedClasses.Count());

            foreach (TypeData typeData in decoratedClasses)
            {
                if (workbooks.All(t => t.WorkbookName != typeData.WorkbookName))
                {
                    throw new Exception($"Workbook '{typeData.WorkbookName}' for given type '{typeData.Type.FullName}' not found.");
                }
                // Get workbook if match name with workbook name from ClassMappingAttribute.
                Workbook workbook = workbooks.FirstOrDefault(t => t.WorkbookName == typeData.WorkbookName);


                // If ClassMappingAttribute contains sheet name than try to get it from the workbook else take first.
                WorkbookSheet sheet = string.IsNullOrEmpty(typeData.SheetName)
            ? workbook.Sheets[0] : workbook.GetSheetByName(typeData.SheetName);

                if (sheet.Columns.Count == 0 || sheet.Rows.Count == 0)
                {
                    throw new Exception($"Sheet '{sheet.Name}' in workbook '{workbook.WorkbookName}' is empty");
                }

                var singleTypeResult = await MapType(typeData.Type, sheet, typeData.Automapping).ConfigureAwait(false);

                resultInput.Add(singleTypeResult.Key, singleTypeResult.Value);
            }

            return(new WorkbookClassMapperResult(resultInput));
        }
예제 #5
0
        public async Task <KeyValuePair <Type, IList> > MapType(TypeWithAttribute <ClassMappingAttribute> typeToMap)
        {
            Workbook workbook = await Workbook.CreateFromExcel(
                Path.GetFileNameWithoutExtension(typeToMap.Attribute.WorkbookPath),
                typeToMap.Attribute.WorkbookPath).ConfigureAwait(false);

            // Try to merge sheets inside this workbook.
            // If one balance workbook is splited into separated sheets that share the same structure.
            workbook.Merge();
            // If ClassMappingAttribute contains sheet name than try to get it from the workbook else take first.
            WorkbookSheet sheet = string.IsNullOrEmpty(typeToMap.Attribute.SheetName)
          ? workbook.Sheets[0] : workbook.GetSheetByName(typeToMap.Attribute.SheetName);

            if (sheet.Columns.Count == 0 || sheet.Rows.Count == 0)
            {
                throw new Exception($"Sheet '{sheet.Name}' in workbook '{workbook.WorkbookName}' is empty");
            }

            return(await MapType(typeToMap.Type, sheet, typeToMap.Attribute.Automapping).ConfigureAwait(false));
        }
예제 #6
0
        public bool Merge(WorkbookSheet other)
        {
            if (!WorkbookHeader.Merge(other.WorkbookHeader))
            {
                return(false);
            }

            WorkbookColumn[] backupColumns = new WorkbookColumn[Columns.Count];
            Columns.CopyTo(backupColumns);
            for (int i = 0; i < Columns.Count; i++)
            {
                var column = Columns[i];
                if (!column.Merge(other.Columns[i]))
                {
                    Columns = backupColumns.ToList();
                    return(false);
                }

                Columns[i] = column;
            }

            Rows.AddRange(other.Rows);
            return(true);
        }
예제 #7
0
        public bool Merge()
        {
            if (Sheets.Count < 2)
            {
                return(true);
            }


            WorkbookSheet sheet = Sheets[0];

            for (int i = 1; i < Sheets.Count; i++)
            {
                if (!sheet.Merge(Sheets[i]))
                {
                    return(false);
                }
            }

            Sheets = new List <WorkbookSheet>()
            {
                sheet
            };
            return(true);
        }
예제 #8
0
 private async Task <KeyValuePair <Type, IList> > MapType(Type type, WorkbookSheet sheet, bool automapping)
 {
     return(automapping ? await AutoMapType(type, sheet) : await ManualMapType(type, sheet));
 }