donnytian / npoi.mapper Goto Github PK
View Code? Open in Web Editor NEWUse this tool to import or export data with Excel file. The tool is a convention based mapper between strong typed object and Excel data via NPOI.
License: MIT License
Use this tool to import or export data with Excel file. The tool is a convention based mapper between strong typed object and Excel data via NPOI.
License: MIT License
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Npoi.Mapper;
using Npoi.Mapper.Attributes;
namespace WS.NPOI
{
class Program
{
static void Main(string[] args)
{
string path = @"F:\test.xlsx";
var list = new Helper().ToMapper(path);
}
}
public class Helper
{
public List ToMapper(string filePath)
{
Mapper mapper = new Mapper(filePath);
mapper.HeaderRowIndex = 0;
mapper.HasHeader = true;
var item = new BClass();
mapper = mapper.Map(
col => { return true; },
(col, target) =>
{
// 请问怎么对 target.Items 深层的嵌套?
((AClass)target).Items.Add(item);
return true;
});
var list = mapper.Take< AClass >(0).Select(s => s.Value).ToList();
return list;
}
}
public class AClass
{
public AClass()
{
Items = new List();
}
[Column("columnName1")]
public int MyColumnName { get; set; }
public List< BClass > Items { get; set; }
}
public class BClass
{
[Column("columnName21")]
public string MyColumnName1 { get; set; }
[Column("columnName22")]
public string MyColumnName2 { get; set; }
}
}
Hello, does the library support the table style? Such as background color or font color or font type and so on
Before using the mapper, I apply a .trim() to the headers to remove empty spaces. But the problem comes when trying to match with the rows that don't have the column name with the .trim() method used on them. Do you know if there is a method or a place where I can apply the trim to the column names of the rows?
Hi,
My demo excel has two headers, the first header for Chinese Name and the second one is the actual column name of the table.
I have tried to set HeaderRowIndex to 1 or 2, but the mapping result is not expected, which the value of the properties is the default value. But if I just keep single hearer, it works fine.
Below are my code and excel:
`
var mapper = new Mapper(fullPath);
mapper.HeaderRowIndex = 1;
var objs = mapper.Take<ProductDTO>().ToList();
Mapper class Should implements IDispose , and set _workbook = null in Dispose method;
Otherwise it will cause memory leak.
Get attribute value as friendly display name if property has DisplayName
attribute.
Or you design a custom attribute enhancement class that provides a custom friendly display name, column display order, and so on.
Or does Npoi.Mapper
already have a similar function? Do you have a better idea?
public class CatalogCareViewModel
{
/// <summary>
/// ISO/国际标准
/// </summary>
public virtual string ISO { get; set; }
/// <summary>
/// German/德语
/// </summary>
[DisplayName("German")]
public virtual string DE { get; set; }
/// <summary>
/// English/英语
/// </summary>
[DisplayName("English")]
public virtual string EN { get; set; }
/// <summary>
/// French/法语
/// </summary>
[DisplayName("French")]
public virtual string FR { get; set; }
/// <summary>
/// Russion/俄语
/// </summary>
[DisplayName("Russion")]
public virtual string RU { get; set; }
/// <summary>
/// Italian/意大利语
/// </summary>
[DisplayName("Italian")]
public virtual string IT { get; set; }
/// <summary>
/// Dutch/荷兰语
/// </summary>
[DisplayName("Dutch")]
public virtual string NL { get; set; }
/// <summary>
/// Norwegian/挪威
/// </summary>
[DisplayName("Norwegian")]
public virtual string NO { get; set; }
}
ISO | German | English | French | Russion | Italian | Dutch | Norwegian |
---|---|---|---|---|---|---|---|
value1 | value2 | value3 | value4 | value5 | value6 | value7 | value8 |
value1 | value2 | value3 | value4 | value5 | value6 | value7 | value8 |
value1 | value2 | value3 | value4 | value5 | value6 | value7 | value8 |
Was trying to insert a DateTime using Put, but It always returned me the numeric value of the Date.
I even reproduced it on the tests.
I'm trying to import a Excel sheet which contains several columns which can have date values as double. Here is my approach:
var mapper = new Mapper(filePath);
mapper.TrackObjects = false;
mapper.Map<Model>(0, o => o.Property1);
mapper.Map<Model>(1, o => o.Property2);
...
mapper.Map(column =>
{
if (column.Attribute.Index == 10 && column.CurrentValue is double value)
{
column.CurrentValue = DateTime.FromOADate(value);
}
return true;
});
var result = mapper.Take<Model>().ToList();
When debugging, the debugger dont even stop in the mapper.Map(column => ...)
method.
All I got as a result is a list of errors for the specific columns:
"Object reference not set to an instance of an object."
How do I have configure the mapper to convert the double to date?
Any help is welcomed!
In MapHelper.cs, there is a static list to contains cached custom styles. In an multi-thread scenario, styles will be messed by different workbooks.
We should cache these styles as instance property.
Without setting a format on DateTime properties, excel seems to format them as integers. For example,
10/26/2016 prints as 42669.
I see that I can easily format a DateTime property if I know it in advance, like this:
mapper.Format<MyObject>("yyyy-MM-dd", x => x.MyDateField)
I tried to make it generic, so I don't need a custom method for every one of my types:
foreach (var property in typeof(T).GetProperties())
{
if (property.PropertyType == typeof(DateTime) ||
property.PropertyType == typeof(DateTime?))
{
mapper.Format<T>("yyyy-MM-dd", x => property.GetValue(x));
}
}
But this fails with "Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.UnaryExpression'."
Would you help me figure this out, or consider building in a default format for DateTime that isn't an integer?
When import from file for nullable value types like DateTime? and int?, if the value from Excel file cannot be converted to the target type, no error reported, just set null to the object.
The expected result is to report errors or use setting to control whether or not report error for specific column/ property.
用户故意上传了个文件格式合法,但列格式不合法的文件。
此时,我希望给用户一个友好的提示(列格式有误),而不是让用户顺利上传成功。
例如:
public class MyEntity
{
public string Name { get; set; }
public string Address { get; set; }
}
Excel
Comany|State|City
通过你的类库,能上传成功,但获取的实体类列表都是空值。
我希望有列名校验之类的功能。不知道你的Mapper.Map
扩展方法能否做到。
或者你有更好的建议??
FEATURE REQUEST
Is there a support to map string to enum values, based on the defined DescriptionAttribute or DisplayAttribute (would choose probably this) on then enum values?
Common scenario is to use abbreviations with enums as well. Also the enum's property is used inside the code (like gold/silver/bronze client) and in excel we might consider to use some abbreviations (G/S/B) which when importing from excel should be converted to the proper enum value.
base on my test
null
if your .Task<Import>
, the Import
contains DateTimeOffset?
DateTime?
is OkI think the DateTimeOffset should be support base on Current TimeZone of the thread
var reader = new Mapper(@"D:\111111.xlsx");
var set = reader.Take<dynamic>().Dump().Select(x => x.Value).ToList();
var writer = new Mapper();
writer.Put(set, "Sheet1");
writer.Save(@"D:\222222.xlsx");
D:\111111.xlsx只有标题行,没有数据
D:\222222.xlsx完全空白,标题行都没有了
Appears to be an issue in Mapper.cs -> Put( ...
SetCell not always called if using resolver.
From this:-
if (column.Resolver != null)
{
column.Resolver.TryPutCell(column, out value, o);
}
else
{
SetCell(cell, value, column, setStyle: overwrite);
}
To this:-
if (column.Resolver != null)
{
column.Resolver.TryPutCell(column, out value, o);
}
SetCell(cell, value, column, setStyle: overwrite);
Regards,
Gary
FEATURE REQUEST
In some cases (localization) the Y/N value do change (A/N or T/F or I/N).
Is there an extended Nullable mapping support which could handle locale string value to Nullable conversion?
使用Npoi IWorkbook的方式导出的excel在两者中打开都正常,使用3.3.0版本的Npoi.Mapper导出,在Microsoft Office中打开会提示如图
无论点击是或者否都不能正常打开。
` //var stream = new MemoryStream();
//var mapper = new Mapper();
//mapper.Format("yyyy-MM-dd", ps=> ps.DeliverPeriod)
// .Format("yyyy-MM-dd", ps=>ps.ApplyTime)
// // 将各个属性映射为中文列名
// .Map("序号", o=>o.SeqNO)
// .Map("合同编号", o=>o.ContractNO)
// .Map("产品编号", o=>o.ProductNO)
// .Map("客户", o=>o.CustomerName)
// .Map("营销代表", o=>o.MarketerName)
// .Map("交货日期", o=>o.DeliverPeriod)
// .Map("物料代码", o=>o.Code)
// .Map("产品型号", o=>o.ProductModelName)
// .Map("规格参数", o=>o.Spec)
// .Map("数量", o=>o.Qty)
// .Map("创建时间", o=>o.ApplyTime)
// .Map("备注", o=>o.Remarks)
// .Map("是否禁用", o=>o.Disabled);
//// 将数据保存到stream中
//mapper.Save(stream, objs, "生产计划评审");
//// 获取stream的buffer
//var buffer = stream.GetBuffer();
//stream.Dispose();
//return buffer;`
其中objs为List的数据
能否在没有自定义映射规则的情况下,将"列标题映射的默认命名约定"作用于Excel导出。
举例:
我没有调用Map<TModel>(parameters...)
,但我希望导出后,
DisplayNameProperty
属性在Excel表格中显示的列名是Display Name
,而不是DisplayNameProperty
。
而ColumnNameAttributeProperty属性
在Excel表格中的列名是正确显示的——By Name
。
换句话说,在导出功能中,ColumnAttribute
起作用了,但DisplayAttribute
没起作用。
实体类SampleClass
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Npoi.Mapper.Attributes;
namespace Sample
{
public class SampleClass
{
public string StringProperty { get; set; }
[Column("By Name")]
public string ColumnNameAttributeProperty { get; set; }
[Column(11)]
public string ColumnIndexAttributeProperty { get; set; }
[Ignore]
public string IgnoredAttributeProperty { get; set; }
[Display(Name = "Display Name")]
public string DisplayNameProperty { get; set; }
[Column(CustomFormat = "0%")]
public double CustomFormatProperty { get; set; }
}
}
Hi there!
Is there a way to ignore the base classes? I have already tried:
mapper.Ignore and mapper.Ignore but it is still saving it to the excel file.
Any clues on how to overcome this?
Not sure what I'm doing wrong... trying to set up a mapping to my Customer class which has some nested properties to BillingAddress, ServiceAddress, BillingContact, etc. - my excel file is 17,000 lines, with some whitespace rows in certain regions.
System.IndexOutOfRangeException: Index was outside the bounds of the array.
StackTrace:
at Npoi.Mapper.MapHelper.GetPropertyInfoByExpression[T](Expression`1 propertySelector)
at Npoi.Mapper.MapExtensions.Map[T](Mapper mapper, String columnName, Expression`1 propertySelector, Func`3 tryTake, Func`3 tryPut)
The above error is thrown, seemingly, when I try to use the mapper .. here's my code:
Npoi.Mapper.Mapper m_mapper = new Npoi.Mapper.Mapper("exportContacts.xlsx");
m_mapper.Map<Customer>("_kftAccountID", o => o.CustomerId)
.Map<Customer>("accountType", o => o.AccountType)
.Map<Customer>("addrBilling", o => o.BillingAddress.AddressLine1)
.Map<Customer>("addrBillingCity", o => o.BillingAddress.City)
.Map<Customer>("addrBillingCounty", o => o.BillingAddress.County)
.Map<Customer>("addrBillingState", o => o.BillingAddress.State)
.Map<Customer>("addrBillingZip", o => o.BillingAddress.ZipCode)
.Map<Customer>("addrService", o => o.ServiceAddress.AddressLine1)
.Map<Customer>("addrServiceCity", o => o.ServiceAddress.City)
.Map<Customer>("addrServiceCounty", o => o.ServiceAddress.County)
.Map<Customer>("addrServiceState", o => o.ServiceAddress.State)
.Map<Customer>("addrServiceZip", o => o.ServiceAddress.ZipCode)
.Map<Customer>("addrServiceAreaSubdivision", o => o.ServiceAreaSubdivision)
.Map<Customer>("contactBillingCompName", o => o.BillingContact.CompanyName)
.Map<Customer>("contactBillingEmail", o => o.BillingContact.Email)
.Map<Customer>("contactBillingNameFirst", o => o.BillingContact.FirstName)
.Map<Customer>("contactBillingNameLast", o => o.BillingContact.LastName)
.Map<Customer>("contactBillingNamePrefix", o => o.BillingContact.Prefix)
.Map<Customer>("contactBillingPhoneFax", o => o.BillingContact.FaxNumber)
.Map<Customer>("contactBillingPhoneHome", o => o.BillingContact.PhoneHome)
.Map<Customer>("contactBillingPhoneMobile", o => o.BillingContact.PhoneMobile)
.Map<Customer>("contactBillingProfessionalTitle", o => o.BillingContact.ProfessionalTitle)
.Map<Customer>("contactBillingSecondaryName", o => o.BillingContact.SecondaryName)
.Map<Customer>("contactBillingSecondaryType", o => o.BillingContact.SecondaryType)
.Map<Customer>("contactBillingWebSite", o => o.BillingContact.WebSite)
.Map<Customer>("contactServiceName", o => o.ServiceContact.CompanyName)
.Map<Customer>("contactServiceEmail", o => o.ServiceContact.Email)
.Map<Customer>("contactServiceNameFirst", o => o.ServiceContact.FirstName)
.Map<Customer>("contactServiceNamePrefix", o => o.ServiceContact.Prefix)
.Map<Customer>("contactServicePhoneFax", o => o.ServiceContact.FaxNumber)
.Map<Customer>("contactServicePhoneHome", o => o.ServiceContact.PhoneHome)
.Map<Customer>("contactServicePhoneMobile", o => o.ServiceContact.PhoneMobile)
.Map<Customer>("contactServicePropertyManager", o => o.ServiceContact.PropertyManager)
.Map<Customer>("contactServiceType", o => o.ServiceContact.Type)
.Map<Customer>("contactServiceWebSite", o => o.ServiceContact.WebSite);
Hi,
there is a message about missing method if you try to export to XLS/S with NPOI version 2.2.1 (newest) installed.
Workaround: use NPOI version 2.1.3.1.
Regards
throw System.ArgumentException: Sheet index (0) is out of range (no sheets)
.
/// <summary>
/// Put objects in the sheet with specified zero-based index.
/// </summary>
/// <typeparam name="T">Target object type</typeparam>
/// <param name="objects">The objects to save.</param>
/// <param name="sheetIndex">The sheet index, default is 0.</param>
/// <param name="overwrite"><c>true</c> to overwrite existing rows; otherwise append.</param>
public void Put<T>(IEnumerable<T> objects, int sheetIndex = 0, bool overwrite = true)
{
if (Workbook == null) Workbook = new XSSFWorkbook();
var sheet = Workbook.GetSheetAt(sheetIndex);
Put(sheet, objects, overwrite);
}
The second line in the method needs to judge the NumberOfSheets
property first.
When it‘s value is greater than 0
, the GetSheetAt
method is called, otherwise, the CreateSheet
method is called.
You mentioned in Issue #4 the new mapper.UseFormat() method. It works great on non-nullable types and on nullable types if the data in the first row after the header is not null. I tested with DateTime and DateTime?.
However, it does not apply the format if the data in the first row is null. In the case of DateTime? this results in integers being used in Excel instead of dates. Would support for this be feasible?
Also, thank you for implementing my previously-requested feature so quickly and I feel bad asking for more!
I think having to create a custom mapper to parse System.Guid values from a spreadsheet is something the mapper should have built in
If this is not going to be supported, can an example be added to the README .. as I had a hard time making a custom mapper for doing this
.NET sample object:
public class MySampleTupleObject
{
public string Id { get; set; }
public System.Guid ProcessId { get; set; }
}
IgnoreErrorsFor
and Ignore
method are not working for dynamic
type.
When producing the object from a sheet only settable properties are used and, in particular, Readonly properties should be ignored. Presently, the mere presence of such properties causing a crash. Conversely, when writing a sheet Writeonly properties should be ignored. Consequently, two distinct BindingFlag seems necessary.
Please look at the code:
Mapper mapper = new Mapper();
mapper.Ignore<TModel>(t => t.Id).Put(list);
var headerCellStyle = mapper.Workbook.CreateCellStyle();
//Ignore style detail setting code...
mapper.ForHeader(cell =>
{
cell.Sheet.AutoSizeColumn(cell.ColumnIndex);
cell.CellStyle = headerCellStyle;
});
NullReferenceException
at the mapper.Workbook.CreateCellStyle()
lineMapper mapper = new Mapper();
mapper.Ignore<TModel>(t => t.Id);
var headerCellStyle = mapper.Workbook.CreateCellStyle();
//Ignore style detail setting code...
mapper.ForHeader(cell =>
{
cell.Sheet.AutoSizeColumn(cell.ColumnIndex);
cell.CellStyle = headerCellStyle;
});
mapper.Put(list);
IWorkbook workbook = new HSSFWorkbook();
Mapper mapper = new Mapper(workbook);
mapper.Ignore<TModel>(t => t.Id);
var headerCellStyle = mapper.Workbook.GetDefaultHeaderCellStyle();
//Ignore style detail setting code...
mapper.ForHeader(cell =>
{
cell.Sheet.AutoSizeColumn(cell.ColumnIndex);
cell.CellStyle = headerCellStyle;
});
mapper.Put(list);
I have to create an object for the Workbook
property to work properly, but this is not what I want.
I looked at the code of the Mapper
class, I think a IWorkbook
object should be created inside the default constructor.
As follows:
/// <summary>
/// Initialize a new instance of <see cref="Mapper"/> class.
/// </summary>
public Mapper()
{
Workbook = new HSSFWorkbook();
}
After that, the Workbook
attribute non-null judgment code in your other methods can be deleted.
If you agree to do this, pay attention to your Save
method
Mapper Map<T>(string columnName, string toName)
如果有这样的重载方法可能会更加方便 ,此方法参数lambda表达式最后的返回值是propInfo,那么 通过 T 和 toName 也是一样可以取到的。谢谢!
First off, awesome tool! As an enhancement, would it be possible to overload the Ignore method to pass properties by property name (as a string), or list of names. Passing in property selector is handy, but it'd be nice to pass in strings.
I know this isn't a code writing service, but, would you mind showing a sample custom resolver that converts a DateTime
excel column and maps it into a SampleObj.MyDateTimeOffsetProperty
- where the property is of type DateTimeOffset
?
如题,WPF客户端项目中,还有很多.NET4.0的项目
There´s a column named "N.I.F.".
I set the mapper like:
_mapper = new Mapper(filePath) { IgnoredNameChars = new[] { '.' } };
The column is totally ignored when:
_mapper.Take<dynamic>()
Though it works if I change the column name to "NIF"
I want to get the title can not be estimated,
Although I found the value I needed on dynamic, I would like to get the title how to get it?
Thanks
挺不错的,但不支持.net framework 4.0
ForHeader
委托应该在填充完数据后执行,而不是填充数据前.
这是有原因的。
如果仅仅只是设置头部样式,你的写法毫无问题。
但如果调用者想要为单元格设置自适应列宽,那么这样写就肯定有问题的。
因为NPOI
提供的Sheet.AutoSizeColumn
自适应列宽方法,是基于当前列最宽的那一个单元格的宽度设置整列的宽度。
所以如果调用者在ForHeader
委托里调用Sheet.AutoSizeColumn
自适应列宽方法,是不会提作用的。
调用者只能在调用了你的Put
方法之后,自己另外写for
调用Sheet.AutoSizeColumn
方法。
而如果你把ForHeader
委托的执行放在填充数据之后,那么调用者无须另写for
代码。
所以请考虑将以下代码段移到Put
方法底部。
// Injects custom action for headers.
if (overwrite && HasHeader && _headerAction != null)
{
firstRow?.Cells.ForEach(c => _headerAction(c));
}
移到这个填充数据的代码段之后
foreach (var o in objectArray)
{
var row = sheet.GetRow(rowIndex);
if (overwrite && row != null)
{
sheet.RemoveRow(row);
row = sheet.CreateRow(rowIndex);
}
row = row ?? sheet.CreateRow(rowIndex);
foreach (var column in columns)
{
var pi = column.Attribute.Property;
var value = pi?.GetValue(o);
var cell = row.GetCell(column.Attribute.Index, MissingCellPolicy.CREATE_NULL_AS_BLANK);
column.CurrentValue = value;
if (column.Attribute.TryPut == null || column.Attribute.TryPut(column, o))
{
SetCell(cell, column.CurrentValue, column, setStyle: overwrite);
}
}
rowIndex++;
}
谢谢
看了下源码,数据类型是根据列头以外的第一行数据取,假如第一行是字符串,则这一列的所有数据都会转字符串,假如是数值,这一列就全是double。
但是有一种情况是,这一列既第一行是数值,其他行有字符串,然后字符串转数值会转换失败(比如中文不能转换成数字)。
代码在类 MapHelper.InferColumnDataType
请问能不能 mapper.Take 的时候,所有列设置为字符串类型
Calling Mapper.Save and passing in a stream seems to close the stream. For files this is ok but if this is content we want to stream from a web server this causes errors when trying to write the data to the response. Would it be possible to create an overload which takes a "closeStream" boolean parameter? This would allow the existing stream to be seeked to zero and sent over the wire from asp.net core.
The firstRow
variable does not get the object returned by the PopulateFirstRow
method
private void Put<T>(ISheet sheet, IEnumerable<T> objects, bool overwrite)
{
var sheetName = sheet.SheetName;
var firstRow = sheet.GetRow(sheet.FirstRowNum);
var objectArray = objects as T[] ?? objects.ToArray();
var type = MapHelper.GetConcreteType(objectArray);
var columns = GetTrackedColumns(sheetName, type) ??
GetColumns(firstRow ?? PopulateFirstRow(sheet, null, type), type);
if (firstRow == null)
{
PopulateFirstRow(sheet, columns, type);
}
// Injects custom action for headers.
if (overwrite && HasHeader && _headerAction != null)
{
firstRow?.Cells.ForEach(c => _headerAction(c));
}
var rowIndex = overwrite
? HasHeader ? sheet.FirstRowNum + 1 : sheet.FirstRowNum
: sheet.GetRow(sheet.LastRowNum) != null ? sheet.LastRowNum + 1 : sheet.LastRowNum;
MapHelper.EnsureDefaultFormats(columns, TypeFormats);
foreach (var o in objectArray)
{
var row = sheet.GetRow(rowIndex);
if (overwrite && row != null)
{
sheet.RemoveRow(row);
row = sheet.CreateRow(rowIndex);
}
row = row ?? sheet.CreateRow(rowIndex);
foreach (var column in columns)
{
var pi = column.Attribute.Property;
var value = pi?.GetValue(o);
var cell = row.GetCell(column.Attribute.Index, MissingCellPolicy.CREATE_NULL_AS_BLANK);
column.CurrentValue = value;
if (column.Attribute.TryPut == null || column.Attribute.TryPut(column, o))
{
SetCell(cell, column.CurrentValue, column, setStyle: overwrite);
}
}
rowIndex++;
}
// Remove not used rows if any.
while (overwrite && rowIndex <= sheet.LastRowNum)
{
var row = sheet.GetRow(rowIndex);
if (row != null) sheet.RemoveRow(row);
rowIndex++;
}
}
error:
if (firstRow == null)
{
PopulateFirstRow(sheet, columns, type);
}
right:
if (firstRow == null)
{
firstRow = PopulateFirstRow(sheet, columns, type);
}
sorry for my broken english
column header name is: NF
cell format is text
cell value is 2017
public class Entity
{
...
public string NF { get; set; }
...
}
var set = mapper.Take<Entity>();
var isnull = set.All(x => x.NF == null);
isnull is true
but this works well
Mapper.Take<dynamic>()
<NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion>
this line should be remove because it add unnecessary/obsolete dependancy (current netstandard.library version is 1.6.1 ) , it should be remove even you target netstandard
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
those line should be remove too, the default value is true, and Properties/AssemblyInfo.cs
will be automatic generate ( in obj folder ) , (it will be compile if you remove Properties/AssemblyInfo.cs
)
When I save the file everything work well, but when i want to read it I see:
System.MissingMethodException : No parameterless constructor defined for this object.
Stack Trace:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean wrapExceptions, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean skipCheckThis, Boolean fillCache)
at Npoi.Mapper.Mapper.Take[T](ISheet sheet, Int32 maxErrorRows, Func`1 objectInitializer)+MoveNext()
at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
var mapper = SummaryMapping.Mapper(PathHelper.directory + "/statement.xlsx");
var test = mapper.Take<SummaryExelPersistence>("sheet0").Count();
What can cause the issue?
Proposed changes to .Map
Although the set-up is a bit different, I think some ideas from AutoMapper could be borrowed...
Currently the .Map function is a bit confusing to use.
First of all it will only be executed for properties where map via annotation failed (somehow feels as if it'd be conflicting with those annotations). And second: the given interface is hard to use (needs a lot of extra code).
Would consider (at least excel to object) following changes:
No1
have a ShouldMap function to replace the current .Map - first callback function (should map column)
should return
No2
the Map function should change as follows (to work similarly as in case of AutoMapper):
...and should allow to do any kind of data manipulation from the excel value, before assigning it to the destination property (even value type changes by parsing and so)
Currently we need to match column names as find property names before we can do any extra changes... This would be maybe the first thing i'd consider to change (to pass the matched propertyname to the call)!
No3
AfterMap / BeforeMap could also help to do extra manipulation
I want to add a cell style
to the header.
Therefore I had first to Put
data, Ignore
some fields, and then get Workbook
, and then foreach
and set the first row of the cell style
.
Can you provide this functionality?
I believe there are many developers with this kind of demand.
Thank you so much.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.