Esempio n. 1
0
    public static void CreateScriptableObjectFromExcelFile <T>(string excelPath, string assetPath) where T : ScriptableObject
    {
        // Dummy scriptable object
        T obj = ScriptableObject.CreateInstance <T>();

        obj.name = typeof(T).ToString();

        AssetDatabase.CreateAsset(obj, assetPath);

        Debug.Log("Parsing " + excelPath + " into " + assetPath);

        // Using reflection find all the fields in our main container class
        // These will be our sheets
        FieldInfo[] sheetFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
        if (sheetFields.Length == 0)
        {
            Debug.LogError("Could not find any fields in class " + typeof(T).ToString());
        }

        foreach (var sheetFieldInfo in sheetFields)
        {
            Debug.Log("Sheet name: " + sheetFieldInfo.ToString());

            object[] attrs = sheetFieldInfo.GetCustomAttributes(true);
            int      found = 0;
            if (attrs.Length == 0)
            {
                Debug.LogError("Could not find any attributes in class " + typeof(T).ToString());
            }
            foreach (var att in attrs)
            {
                // Depending on the attributes, we might have to use reflection to work out the column names
                // We use reflection to work out the required datatype
                ExcelSheetAttribute e = att as ExcelSheetAttribute;
                if (e != null)
                {
                    found += 1;
                    Debug.Log(sheetFieldInfo.ToString());
                    Debug.Log(sheetFieldInfo.GetType().ToString());

                    // Get the type of the list
                    Debug.Log(sheetFieldInfo.FieldType.GetGenericArguments().Length);
                    Type listType = sheetFieldInfo.FieldType.GetGenericArguments()[0];

                    Debug.Log(listType.ToString());

                    // Use reflection to call the correct generic method
                    MethodInfo method  = typeof(ExcelParser).GetMethod("CreateListFromSheet");
                    MethodInfo generic = method.MakeGenericMethod(listType);
                    sheetFieldInfo.SetValue(obj, generic.Invoke(null, new object[] { obj, excelPath, e.sheetName }));
                }
            }
            if (found == 0)
            {
                Debug.LogError("Could not find any ExcelSheet attributes in class " + typeof(T).ToString());
            }
        }

        AssetDatabase.SaveAssets();
    }
        private static void ImplementExcelSheetOptions(Worksheet sheet, ExcelSheetAttribute sheetAttribute, int currentRow, int currentColumn)
        {
            //freeze all the header cells if requested.
            if (sheetAttribute.FreezeHeaders)
            {
                sheet.FreezePanes(currentRow + 1, 0, 1, 0);
            }

            if (sheetAttribute.AutoFilter)
            {
                sheet.AutoFilter.SetRange(currentRow, sheetAttribute.StartColumn, currentColumn - 1);
            }
        }
        public ExcelSheetInfoCollection GetExcelSheetInfo(Type itemType, object data)
        {
            if (itemType.Name.StartsWith("Dictionary"))
            {
                return(null);
            }

            var sheets     = FormatterUtils.GetMemberNames(itemType);
            var properties = GetSerialisablePropertyInfo(itemType);

            var sheetCollection = new  ExcelSheetInfoCollection();

            foreach (var sheet in sheets)
            {
                var prop = properties.FirstOrDefault(p => p.Name == sheet);

                ExcelSheetAttribute attr = FormatterUtils.GetAttribute <ExcelSheetAttribute>(prop);

                if (prop == null || attr == null)
                {
                    continue;
                }

                var sheetInfo = new ExcelSheetInfo()
                {
                    SheetType           = prop.PropertyType,
                    SheetName           = sheet,
                    ExcelSheetAttribute = attr,
                    PropertyName        = prop.Name,
                    SheetObject         = FormatterUtils.GetFieldOrPropertyValue(data, prop.Name)
                };

                if (prop.PropertyType.Name.StartsWith("List") && sheetInfo.SheetObject != null)
                {
                    sheetInfo.SheetType = FormatterUtils.GetEnumerableItemType(sheetInfo.SheetObject.GetType());
                }

                sheetCollection.Add(sheetInfo);
            }

            return(sheetCollection);
        }
        private static void PopulateAttributeBased(Worksheet sheet, IEnumerable items, Type type, ExcelSheetAttribute sheetAttribute)
        {
            var columnList = type.GetProperties()
                             .Where(x => x.GetCustomAttribute <ExcelColumnAttribute>() != null)
                             .Select(x => new PropertyAttributeItem(x, x.GetCustomAttribute <ExcelColumnAttribute>()))
                             .OrderBy(x => x.Attribute.Order)
                             .ThenBy(x => x.Property.Name)
                             .ToList();

            var currentRow    = sheetAttribute.StartRow;
            var currentColumn = sheetAttribute.StartColumn;

            if (sheetAttribute.Headers)
            {
                foreach (var column in columnList)
                {
                    var cell = sheet.Cells[currentRow, currentColumn++];
                    cell.PutValue(column.Attribute.HeaderName ?? column.Property.Name);
                    SetHeaderStyle(cell);
                }

                ImplementExcelSheetOptions(sheet, sheetAttribute, currentRow, currentColumn);
                currentRow++;
                currentColumn = sheetAttribute.StartColumn;
            }

            foreach (var dataRow in items)
            {
                for (int i = 0; i < columnList.Count; i++)
                {
                    var column = columnList[i];
                    var value  = column.Property.GetValue(dataRow);
                    var cell   = sheet.Cells[currentRow, currentColumn++];

                    if (column.Attribute.Formula)
                    {
                        if (column.Property.PropertyType != typeof(string))
                        {
                            throw new ExcelColumnFormulaMismatchException(type, column.Property.Name);
                        }

                        cell.Formula = (string)value;
                        continue;
                    }

                    cell.PutValue(value);

                    //apply custom formatting.
                    if (!String.IsNullOrEmpty(column.Attribute.Format))
                    {
                        var style = cell.GetStyle();
                        style.Custom = column.Attribute.Format;
                        cell.SetStyle(style);
                    }
                }

                currentRow++;
                currentColumn = sheetAttribute.StartColumn;
            }

            //check if there are any auto-fit columns.  Mostly to keep the currentColumn reset code template.
            if (columnList.Any(x => x.Attribute.AutoFit))
            {
                foreach (var column in columnList)
                {
                    if (column.Attribute.AutoFit)
                    {
                        sheet.AutoFitColumn(currentColumn);
                    }

                    currentColumn++;
                }
                currentColumn = sheetAttribute.StartColumn;
            }
        }
        private static void PopulateSimple(Worksheet sheet, IEnumerable items, Type type, ExcelSheetAttribute sheetAttribute)
        {
            var propertyList = type.GetProperties().OrderBy(x => x.Name).ToList();

            if (propertyList.Any(x => x.GetCustomAttribute <ExcelColumnAttribute>() != null))
            {
                throw new ApplicationException("ExcelColumnAttribute should not be used when IncludeAllProperties of ExcelSheetAttribute is true.");
            }

            var currentRow    = sheetAttribute.StartRow;
            var currentColumn = sheetAttribute.StartColumn;

            if (sheetAttribute.Headers)
            {
                foreach (var property in propertyList)
                {
                    var cell = sheet.Cells[currentRow, currentColumn++];
                    cell.PutValue(property.Name);
                    SetHeaderStyle(cell);
                }

                ImplementExcelSheetOptions(sheet, sheetAttribute, currentRow, currentColumn);
                currentRow++;
                currentColumn = sheetAttribute.StartColumn;
            }

            foreach (var dataRow in items)
            {
                for (int i = 0; i < propertyList.Count; i++)
                {
                    var value = propertyList[i].GetValue(dataRow);
                    var cell  = sheet.Cells[currentRow, currentColumn++];
                    cell.PutValue(value);
                }

                currentRow++;
                currentColumn = sheetAttribute.StartColumn;
            }

            for (int i = 0; i < propertyList.Count; i++)
            {
                sheet.AutoFitColumn(currentColumn++);
            }
            currentColumn = sheetAttribute.StartColumn;
        }