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();