diff --git a/ClosedXML/Attributes/ColumnOrderAttribute.cs b/ClosedXML/Attributes/ColumnOrderAttribute.cs new file mode 100644 index 0000000..b85c541 --- /dev/null +++ b/ClosedXML/Attributes/ColumnOrderAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace ClosedXML.Attributes +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public class ColumnOrderAttribute : Attribute + { + public ColumnOrderAttribute(long order) + { + this.Order = order; + } + + public long Order { get; private set; } + } +} diff --git a/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML.csproj index 1136f31..eb62794 100644 --- a/ClosedXML/ClosedXML.csproj +++ b/ClosedXML/ClosedXML.csproj @@ -61,6 +61,7 @@ + diff --git a/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/Excel/Cells/XLCell.cs index 1709adc..1338dad 100644 --- a/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/Excel/Cells/XLCell.cs @@ -1,19 +1,22 @@ -namespace ClosedXML.Excel -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Data; - using System.Globalization; - using System.Linq; - using System.Reflection; - using System.Text; - using System.Text.RegularExpressions; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; #if NET4 using System.ComponentModel.DataAnnotations; - +#else +using System.ComponentModel; #endif +namespace ClosedXML.Excel +{ + using Attributes; + internal class XLCell : IXLCell, IXLStylized { public static readonly DateTime BaseDate = new DateTime(1899, 12, 30); @@ -326,7 +329,7 @@ { cValue = GetString(); } - catch + catch { cValue = String.Empty; } @@ -572,23 +575,14 @@ { var fieldInfo = m.GetType().GetFields(); var propertyInfo = m.GetType().GetProperties(); + + var columnOrders = fieldInfo.Select(fi => new KeyValuePair(GetFieldOrder(fi.GetCustomAttributes(true)), fi)) + .Concat(propertyInfo.Select(pi => new KeyValuePair(GetFieldOrder(pi.GetCustomAttributes(true)), pi))) + .OrderBy(pair => pair.Key); + if (!hasTitles) { - foreach (var info in fieldInfo) - { - if ((info as IEnumerable) == null) - { - var fieldName = GetFieldName(info.GetCustomAttributes(true)); - if (XLHelper.IsNullOrWhiteSpace(fieldName)) - fieldName = info.Name; - - SetValue(fieldName, fRo, co); - } - - co++; - } - - foreach (var info in propertyInfo) + foreach (var info in columnOrders.Select(o => o.Value)) { if ((info as IEnumerable) == null) { @@ -606,16 +600,17 @@ hasTitles = true; } - foreach (var info in fieldInfo) - { - SetValue(info.GetValue(m), ro, co); - co++; - } - foreach (var info in propertyInfo) + foreach (var info in columnOrders.Select(o => o.Value)) { - if ((info as IEnumerable) == null) - SetValue(info.GetValue(m, null), ro, co); + var fi = info as FieldInfo; + var pi = info as PropertyInfo; + + if (fi != null) + SetValue(fi.GetValue(m), ro, co); + else if (pi != null && info as IEnumerable == null) + SetValue(pi.GetValue(m, null), ro, co); + co++; } } @@ -1679,7 +1674,7 @@ val = dtTest.ToOADate().ToInvariantString(); } } - + } else if (Boolean.TryParse(val, out bTest)) { @@ -2491,10 +2486,17 @@ var attribute = customAttributes.FirstOrDefault(a => a is DisplayAttribute); return attribute != null ? (attribute as DisplayAttribute).Name : null; #else - return null; + var attribute = customAttributes.FirstOrDefault(a => a is DisplayNameAttribute); + return attribute != null ? (attribute as DisplayNameAttribute).DisplayName : null; #endif } + private static long GetFieldOrder(Object[] customAttributes) + { + var attribute = customAttributes.FirstOrDefault(a => a is ColumnOrderAttribute); + return attribute != null ? (attribute as ColumnOrderAttribute).Order : long.MaxValue; + } + #region Nested type: FormulaConversionType private enum FormulaConversionType @@ -2605,4 +2607,4 @@ public IXLRangeAddress FormulaReference { get; set; } } -} \ No newline at end of file +} diff --git a/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj b/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj index dc7a265..56c7353 100644 --- a/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj +++ b/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj @@ -55,6 +55,9 @@ + + Attributes\ColumnOrderAttribute.cs + Excel\AutoFilters\IXLAutoFilter.cs diff --git a/ClosedXML_Tests/Excel/Tables/TablesTests.cs b/ClosedXML_Tests/Excel/Tables/TablesTests.cs index d3c29df..d7a8bac 100644 --- a/ClosedXML_Tests/Excel/Tables/TablesTests.cs +++ b/ClosedXML_Tests/Excel/Tables/TablesTests.cs @@ -1,7 +1,9 @@ -using ClosedXML.Excel; +using ClosedXML.Attributes; +using ClosedXML.Excel; using NUnit.Framework; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Data; using System.IO; using System.Linq; @@ -14,12 +16,26 @@ [TestFixture] public class TablesTests { - public class TestObject + public class TestObjectWithoutAttributes { public String Column1 { get; set; } public String Column2 { get; set; } } + public class TestObjectWithAttributes + { + public int UnOrderedColumn { get; set; } + + [Display(Name ="SecondColumn"), ColumnOrder(1)] + public String Column1 { get; set; } + + [Display(Name = "FirstColumn"), ColumnOrder(0)] + public String Column2 { get; set; } + + [Display(Name = "SomeFieldNotProperty"), ColumnOrder(2)] + public int MyField; + } + [Test] public void CanSaveTableCreatedFromEmptyDataTable() { @@ -151,7 +167,7 @@ [Test] public void TableCreatedFromEmptyListOfObject() { - var l = new List(); + var l = new List(); var wb = new XLWorkbook(); IXLWorksheet ws = wb.AddWorksheet("Sheet1"); @@ -160,6 +176,25 @@ } [Test] + public void TableCreatedFromListOfObjectWithPropertyAttributes() + { + var l = new List() + { + new TestObjectWithAttributes() { Column1 = "a", Column2 = "b", MyField = 4, UnOrderedColumn = 999 }, + new TestObjectWithAttributes() { Column1 = "c", Column2 = "d", MyField = 5, UnOrderedColumn = 777 } + }; + + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + ws.FirstCell().InsertTable(l); + Assert.AreEqual(4, ws.Tables.First().ColumnCount()); + Assert.AreEqual("FirstColumn", ws.FirstCell().Value); + Assert.AreEqual("SecondColumn", ws.FirstCell().CellRight().Value); + Assert.AreEqual("SomeFieldNotProperty", ws.FirstCell().CellRight().CellRight().Value); + Assert.AreEqual("UnOrderedColumn", ws.FirstCell().CellRight().CellRight().CellRight().Value); + } + + [Test] public void TableInsertAboveFromData() { var wb = new XLWorkbook();