Skip to content

Commit a5574ee

Browse files
authored
LoadFromCollection - support for Dictionary properties (#1176)
* #969, #1058 - implemented EPPlusDictionaryColumnAttribute for LoadFromCollection with attributes * #969, #1058 - added support for Dictionary property in LoadFromCollection * #1058, #969 - LoadFromCollection, support for Dictionary property * #1058, #969 - added testclass * #1058, #969 - added unit test for reading column headers/keys from attribute
1 parent 945b83e commit a5574ee

File tree

8 files changed

+566
-140
lines changed

8 files changed

+566
-140
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*************************************************************************************************
2+
Required Notice: Copyright (C) EPPlus Software AB.
3+
This software is licensed under PolyForm Noncommercial License 1.0.0
4+
and may only be used for noncommercial purposes
5+
https://polyformproject.org/licenses/noncommercial/1.0.0/
6+
7+
A commercial license to use this software can be purchased at https://epplussoftware.com
8+
*************************************************************************************************
9+
Date Author Change
10+
*************************************************************************************************
11+
7/11/2023 EPPlus Software AB EPPlus 7
12+
*************************************************************************************************/
13+
using System;
14+
using System.Collections.Generic;
15+
using System.Linq;
16+
using System.Text;
17+
18+
namespace OfficeOpenXml.Attributes
19+
{
20+
/// <summary>
21+
/// This attributes can only be used on properties that are of the type IDictionary&lt;string, string&gt;.
22+
/// Columns will be added based on the items in <see cref="EPPlusDictionaryColumnAttribute.ColumnHeaders"/>
23+
/// </summary>
24+
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field)]
25+
internal class EPPlusDictionaryColumnAttribute : Attribute
26+
{
27+
/// <summary>
28+
/// Order of the columns value, default value is 0
29+
/// </summary>
30+
public int Order
31+
{
32+
get;
33+
set;
34+
}
35+
36+
/// <summary>
37+
/// The values of this array will be used to generate columns (one column for each item).
38+
/// </summary>
39+
public string[] ColumnHeaders { get; set; }
40+
41+
/// <summary>
42+
/// Should be unique within all attributes. Will be used to retrieve the keys of the Dictionary
43+
/// that also will be used to create the columns for this property.
44+
/// </summary>
45+
public string KeyId { get; set; }
46+
}
47+
}

src/EPPlus/FormulaParsing/Excel/Functions/Engineering/ConvertFunction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace OfficeOpenXml.FormulaParsing.Excel.Functions.Engineering
2121
[FunctionMetadata(
2222
Category = ExcelFunctionCategory.Engineering,
2323
EPPlusVersion = "5.1",
24-
Description = "Calculates the modified Bessel function Yn(x)")]
24+
Description = "Converts a number from one measurement system to another")]
2525
public class ConvertFunction : ExcelFunction
2626
{
2727
public override int ArgumentMinLength => 3;

src/EPPlus/LoadFunctions/ColumnInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public ColumnInfo()
3030

3131
public int SortOrder { get; set; }
3232

33+
public bool IsDictionaryProperty { get; set; }
34+
35+
public string DictinaryKey { get; set; }
36+
3337
public List<int> SortOrderLevels { get; set; }
3438
public int Index { get; set; }
3539

src/EPPlus/LoadFunctions/LoadFromCollection.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public LoadFromCollection(ExcelRangeBase range, IEnumerable<T> items, LoadFromCo
5555
LoadFromCollectionColumns<T> cols;
5656
if (parameters.Members == null)
5757
{
58-
cols = new LoadFromCollectionColumns<T>(parameters.BindingFlags, SortOrderProperties);
58+
cols = new LoadFromCollectionColumns<T>(parameters, SortOrderProperties);
5959
var columns = cols.Setup();
6060
_columns = columns.ToArray();
6161
SetHiddenColumns();
@@ -66,7 +66,7 @@ public LoadFromCollection(ExcelRangeBase range, IEnumerable<T> items, LoadFromCo
6666
{
6767
throw (new ArgumentException("Parameter Members must have at least one property. Length is zero"));
6868
}
69-
cols = new LoadFromCollectionColumns<T>(parameters.BindingFlags, SortOrderProperties, parameters.Members);
69+
cols = new LoadFromCollectionColumns<T>(parameters, SortOrderProperties);
7070
var columns = cols.Setup();
7171
_columns = columns.ToArray();
7272
// the ValidateType method will throw an InvalidCastException
@@ -228,6 +228,18 @@ private void SetValuesAndFormulas(object[,] values, Dictionary<int, FormulaCell>
228228
{
229229
v = ((MethodInfo)member).Invoke(obj, null);
230230
}
231+
if (colInfo.IsDictionaryProperty)
232+
{
233+
var dict = v as Dictionary<string, object>;
234+
if(dict != null && dict.ContainsKey(colInfo.DictinaryKey))
235+
{
236+
v = dict[colInfo.DictinaryKey];
237+
}
238+
else
239+
{
240+
v = null;
241+
}
242+
}
231243

232244
#if (!NET35)
233245
if (v != null)
@@ -273,8 +285,9 @@ private object GetValueByPath(object obj, string path)
273285
{
274286
var members = path.Split('.');
275287
object o = obj;
276-
foreach(var member in members)
288+
for(var ix = 0; ix < members.Length; ix++)
277289
{
290+
var member = members[ix];
278291
if (o == null) return null;
279292
var memberInfos = o.GetType().GetMember(member);
280293
if(memberInfos == null || memberInfos.Length == 0)
@@ -298,6 +311,19 @@ private object GetValueByPath(object obj, string path)
298311
{
299312
throw new NotSupportedException("Invalid member: '" + memberInfo.Name + "', not supported member type '" + memberInfo.GetType().FullName + "'");
300313
}
314+
if(o is Dictionary<string, object> dict && ix < members.Length + 1)
315+
{
316+
var key = members[ix + 1];
317+
if(dict.ContainsKey(key))
318+
{
319+
o = dict[key];
320+
}
321+
else
322+
{
323+
o = null;
324+
}
325+
break;
326+
}
301327
}
302328
return o;
303329
}

0 commit comments

Comments
 (0)