Skip to content

Commit

Permalink
resolve merge conflicts after project restucture
Browse files Browse the repository at this point in the history
Fixes #6
  • Loading branch information
doroudi committed Feb 19, 2024
2 parents d200b81 + 452e969 commit e9ece12
Show file tree
Hide file tree
Showing 28 changed files with 1,128 additions and 0 deletions.
25 changes: 25 additions & 0 deletions ExcelMapper.Test/MapperProfiles/ExportProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using ExcelMapper.Test.Models;
using NPOI.SS.UserModel;
using YummyCode.ExcelMapper.Exporter;

namespace YummyCode.ExcelMapper.Test.MapperProfiles
{
public class ExportProfile: ExportMapper<Person>
{
public ExportProfile(IWorkbook workbook): base(workbook)
{
_ = CreateMap()
.ForColumn("A", x => x.Name, opt => opt.WithHeader("Name"))
.ForColumn("B", x => x.Family, opt => opt.WithHeader("Family"))
.ForColumn("C", x => x.BirthDate, opt => opt.WithHeader("BirthDate").UseAction(ConvertToPersian))
.ForColumn("D", x => x.Address, opt => opt.WithHeader("Address"))
.ForColumn("E", x => x.Name, opt => opt.WithHeader("NAME").UseAction(x => x?.ToUpper()));
// .ForColumn("B", opt => opt.MapFrom<Employee>(x => x.Name));
}

private static string ConvertToPersian(DateTime? arg)
{
return arg?.ToShortDateString() ?? "";
}
}
}
10 changes: 10 additions & 0 deletions ExcelMapper.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
<<<<<<< HEAD
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YummyCode.ExcelMapper.Importer", "src\YummyCode.ExcelMapper.Importer\YummyCode.ExcelMapper.Importer.csproj", "{B72766E3-836D-48EA-ABF4-38C1F16F0DCE}"
=======
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YummyCode.ExcelMapper.Importer", "ExcelMapper\YummyCode.ExcelMapper.Importer.csproj", "{B72766E3-836D-48EA-ABF4-38C1F16F0DCE}"
>>>>>>> 452e969fed67e87b821b76b42a2de365434c852f
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5D816DBB-F928-4AAC-AC10-B4170D353844}"
ProjectSection(SolutionItems) = preProject
Expand All @@ -24,6 +28,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DD08BCF-3A6
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{10C4E5AE-0A60-4978-B708-3A6076ACEE10}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YummyCode.ExcelMapper.Exporter", "YummyCode.ExcelMapper.Exporter\YummyCode.ExcelMapper.Exporter.csproj", "{B051350E-13E1-4A0C-B1DE-C56DF0109A8E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YummyCode.ExcelMapper.Shared", "YummyCode.ExcelMapper.Shared\YummyCode.ExcelMapper.Shared.csproj", "{E3C9F767-3DA2-4C10-BC19-BF49E63243C5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YummyCode.ExcelMapper.Logger", "YummyCode.ExcelMapper.Logger\YummyCode.ExcelMapper.Logger.csproj", "{2CDAA3F2-2812-44C5-AD8B-27B24CC0D2F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
11 changes: 11 additions & 0 deletions ExcelMapper/Exceptions/ExcelMappingException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using YummyCode.ExcelMapper.Shared.Models;

namespace YummyCode.ExcelMapper.Exceptions
{
public class ExcelMappingException(Dictionary<string, ResultState> cols) : Exception
{
public Dictionary<string, ResultState> Cols { get; set; } = cols;
}
}
9 changes: 9 additions & 0 deletions ExcelMapper/Models/ExcelColAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace YummyCode.ExcelMapper.Models
{
public sealed class ExcelColAttribute(string col) : Attribute
{
public string Col { get; set; } = col;
}
}
16 changes: 16 additions & 0 deletions ExcelMapper/Models/PropertyMapInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace YummyCode.ExcelMapper.Models
{
public sealed class PropertyMapInfo(string name, PropertyInfo property, string columnName)
{
public string Name { get; set; } = name;
public PropertyInfo Property { get; set; } = property;
public string ColumnName { get; set; } = columnName;
public List<LambdaExpression> Actions { get; set; } = new();
public List<LambdaExpression> Validations { get; set; } = new();
public List<string> IgnoredValues { get; set; } = new List<string>();
}
}
47 changes: 47 additions & 0 deletions YummyCode.ExcelMapper.Exporter/ExcelExporter{T}.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.IO;
using NPOI.XSSF.Streaming;

namespace YummyCode.ExcelMapper.Exporter
{
public class ExcelWriter
{
public SXSSFWorkbook WorkBook { get; } = new();

#region Methods
/// <summary>
/// Add new sheet using SheetBuilder
/// </summary>
/// <param name="mapper">mapper instance of TSource</param>
/// <param name="builder">sheet builder</param>
/// <returns></returns>
public ExcelWriter AddSheet<TSource>(IExportMapper<TSource> mapper, Action<SheetBuilder<TSource>> builder) where TSource : new()
{
builder.Invoke(new SheetBuilder<TSource>(WorkBook, mapper));
return this;
}


/// <summary>
/// Save generated excel document to memory stream and return it
/// </summary>
/// <returns>Memory stream contains excel file's outputs</returns>
public MemoryStream GetFileContent()
{
var memoryData = new MemoryStream();
WorkBook.Write(memoryData);
GC.Collect();

return memoryData;
}

public void SaveToFile(string fileName)
{
using var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
WorkBook.Write(fileStream);
GC.Collect();
}

#endregion
}
}
132 changes: 132 additions & 0 deletions YummyCode.ExcelMapper.Exporter/ExportMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NPOI.SS.UserModel;
<<<<<<<< HEAD:src/YummyCode.ExcelMapper.Exporter/ExportMapper.cs
========
using YummyCode.ExcelMapper.Exporter.Models;
>>>>>>>> 452e969fed67e87b821b76b42a2de365434c852f:YummyCode.ExcelMapper.Exporter/ExportMapper.cs
using YummyCode.ExcelMapper.Shared.Models;

namespace YummyCode.ExcelMapper.Exporter
{
public abstract class ExportMapper<TSource> : IExportMapper<TSource> where TSource : new()
{
// protected IWorkbook Workbook;
private IExportMappingExpression<TSource> _mappingExpression;
private Dictionary<int, List<Delegate>> _compiledActions;
public ExportMapper(IWorkbook workbook)
{
// Workbook = workbook;
_mappingExpression = new ExportMappingExpression<TSource>();
_compiledActions = new Dictionary<int, List<Delegate>>();
}
public List<CellMappingInfo> Mappings =>
_mappingExpression.Mappings;

public IExportMappingExpression<TSource> CreateMap()
{
var expression = new ExportMappingExpression<TSource>();
_mappingExpression = expression;
_compiledActions = new Dictionary<int, List<Delegate>>();
return expression;
}

public void Map(TSource data, IRow row)
{
if (_compiledActions.Count == 0)
{
CompileMappingActions();
}

var mappingCols = _mappingExpression.Mappings;
foreach (var colMapping in mappingCols)
{
try
{
var converted = ExecuteMappingAction(data, colMapping);
SetCellValue(row, colMapping, converted);
}
//TODO Check
catch
{
throw;
}
}
}

private void CompileMappingActions()
{
foreach (var mapping in _mappingExpression.Mappings)
{
if (mapping == null) { continue; }
var mappingCompiledActions = mapping.Actions.Select(action => action.Compile()).ToList();

if (mappingCompiledActions.Any())
{
_compiledActions.Add(mapping.Column, mappingCompiledActions);
}
}
}

private static void SetCellValue(IRow row, CellMappingInfo colMapping, object converted)
{
// TODO: should check for value is correct column name in excel
if (colMapping.Column < 0) return;

var cellValue = string.Empty;
if (colMapping.ConstValue != null)
cellValue = colMapping.ConstValue;

else if (converted != null)
cellValue = converted.ToString();

else if (colMapping.DefaultValue != null)
cellValue = colMapping.DefaultValue;

var cell = row.CreateCell(colMapping.Column);
if (colMapping.Style != null)
cell.CellStyle = colMapping.Style;

cell.SetCellValue(cellValue);
}

private object ExecuteMappingAction(TSource data, CellMappingInfo mapping)
{
//data = data ?? throw new ArgumentNullException(nameof(data));
//mapping = mapping ?? throw new ArgumentNullException(nameof(mapping));
var value = data?.GetType().GetProperty(mapping.Property?.Name).GetValue(data, null);
if (!_compiledActions.ContainsKey(mapping.Column)) return value;
var converted = value;
for (var i = 0; i < _compiledActions[mapping.Column].Count; i++)
{
var action = _compiledActions[mapping.Column][i];
converted = action.DynamicInvoke(converted);
}

return converted;
}


public void MapHeader(ref IRow headerRow)
{
var mappingCols = _mappingExpression.Mappings;
foreach (var mapping in mappingCols)
{
headerRow.CreateCell(mapping.Column).SetCellValue(mapping.Header);
}
}

public IEnumerable<string> GetMappingColumns()
{
var items = _mappingExpression.Mappings;
//items.Reverse();
foreach (var item in items)
{
yield return item.Header ?? item.Property?.Name ?? "";
}
}
}
}
125 changes: 125 additions & 0 deletions YummyCode.ExcelMapper.Exporter/ExportMappingExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using YummyCode.ExcelMapper.Exporter.Models;
using YummyCode.ExcelMapper.Shared.Models;

namespace YummyCode.ExcelMapper.Exporter
{
public class ExportMappingExpression<TDestination> : IExportMappingExpression<TDestination>
{
private ICellStyle _defaultStyle;

public List<CellMappingInfo> Mappings { get; } = new List<CellMappingInfo>();

public IExportMappingExpression<TDestination> ForAllMembers
(Action<ExportConfigurationExpression<TDestination>> memberOptions)
{

throw new NotImplementedException();
}

public IExportMappingExpression<TDestination> ForAllOtherMembers(Action<ExportConfigurationExpression<TDestination>> memberOptions)
{
// TODO: implement this
throw new NotImplementedException();
}

public ExportMappingExpression<TDestination> ForColumn<TMember>
(string column,
Expression<Func<TDestination, TMember>> destinationMember,
Action<ExportMemberConfigurationExpression<TDestination, TMember>> memberOptions = null)
{
var colRef = new CellReference(column);
var config = GetCellConfig(colRef.Col, destinationMember, memberOptions); ;
Mappings.Add(config);
return this;
}


public ExportMappingExpression<TDestination> AddColumn<TMember>
(Expression<Func<TDestination, TMember>> destinationMember,
Action<ExportMemberConfigurationExpression<TDestination, TMember>> memberOptions = null)
{
var config = GetCellConfig(Mappings.Count, destinationMember, memberOptions);
Mappings.Add(config);
return this;
}

private CellMappingInfo GetCellConfig<TMember>(int column, Expression<Func<TDestination, TMember>> destinationMember, Action<ExportMemberConfigurationExpression<TDestination, TMember>> memberOptions)
{
var memberName = ((MemberExpression)destinationMember.Body).Member.Name;
var property = typeof(TDestination).GetProperty(memberName);

var expression = new ExportMemberConfigurationExpression<TDestination, TMember>();
memberOptions(expression);

if (expression.CellStyle == null && _defaultStyle != null)
{
expression.UseStyle(_defaultStyle);
}

var config = new CellMappingInfo
{
Header = expression.Header,
Column = column,
Property = property,
Actions = expression.Actions,
Style = expression.CellStyle,
ConstValue = expression.ConstValue,
DefaultValue = expression.DefaultValue?.ToString()
};
Mappings.Add(config);
return config;
}

private string GetAvailableColumn()
{
return ColumnIndexToColumnLetter(Mappings.Count + 1);
}

/// <summary>
/// Converts index to excel column name
/// for example 0=> A, 33 => AG
/// </summary>
/// <param name="colIndex">index of column in excel</param>
/// <returns>corresponding column name for colIndex</returns>
private string ColumnIndexToColumnLetter(int colIndex)
{
var div = colIndex;
var colLetter = string.Empty;
while (div > 0)
{
var mod = (div - 1) % 26;
colLetter = (char)(65 + mod) + colLetter;
div = ((div - mod) / 26);
}
return colLetter;
}

public List<LambdaExpression> GetActions(PropertyInfo property)
{
return Mappings
.FirstOrDefault(x => x.Property.Name == property.Name)?
.Actions ?? new List<LambdaExpression>();
}

public CellMappingInfo this[PropertyInfo property]
{
get
{
return Mappings.FirstOrDefault(x => x.Property.Name == property.Name);
}
}

public ExportMappingExpression<TDestination> SetDefaultStyle(ICellStyle cellStyle)
{
_defaultStyle = cellStyle;
return this;
}
}
}
Loading

0 comments on commit e9ece12

Please sign in to comment.