Skip to content

Commit 2cb105f

Browse files
authored
Merge pull request #21 from biggray/develop
port to netstandard 2.0
2 parents 18ed6dd + 6b8e72f commit 2cb105f

10 files changed

Lines changed: 332 additions & 260 deletions

File tree

samples/FluentExcel.Samples.csproj

Lines changed: 18 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,25 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
43
<PropertyGroup>
5-
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6-
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7-
<ProjectGuid>{08DCA8C6-8AB5-4341-AB82-001EC59B9ACC}</ProjectGuid>
4+
<TargetFrameworks>net461</TargetFrameworks>
85
<OutputType>Exe</OutputType>
9-
<AppDesignerFolder>Properties</AppDesignerFolder>
10-
<RootNamespace>FluentExcel.Samples</RootNamespace>
11-
<AssemblyName>FluentExcel.Samples</AssemblyName>
12-
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
13-
<FileAlignment>512</FileAlignment>
14-
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
6+
<StartupObject>samples.Program</StartupObject>
7+
<Authors>RigoFunc (xuyingting)</Authors>
8+
<Description>The examples of the FluentExcel</Description>
9+
<Copyright>Copyright © RigoFunc (xuyingting). All rights reserved.</Copyright>
10+
<PackageProjectUrl>https://github.com/Arch/FluentExcel</PackageProjectUrl>
11+
<PackageLicenseUrl>https://github.com/Arch/FluentExcel/blob/master/LICENSE</PackageLicenseUrl>
12+
<RepositoryUrl>https://github.com/Arch/FluentExcel</RepositoryUrl>
13+
<RepositoryType>GIT</RepositoryType>
14+
<PackageTags>FluentExcel, NPOI, Fluent API, NPOI.Extension, xyting, Arch, dotnetcore</PackageTags>
1515
</PropertyGroup>
16-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
17-
<PlatformTarget>AnyCPU</PlatformTarget>
18-
<DebugSymbols>true</DebugSymbols>
19-
<DebugType>full</DebugType>
20-
<Optimize>false</Optimize>
21-
<OutputPath>bin\Debug\</OutputPath>
22-
<DefineConstants>DEBUG;TRACE</DefineConstants>
23-
<ErrorReport>prompt</ErrorReport>
24-
<WarningLevel>4</WarningLevel>
25-
</PropertyGroup>
26-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27-
<PlatformTarget>AnyCPU</PlatformTarget>
28-
<DebugType>pdbonly</DebugType>
29-
<Optimize>true</Optimize>
30-
<OutputPath>bin\Release\</OutputPath>
31-
<DefineConstants>TRACE</DefineConstants>
32-
<ErrorReport>prompt</ErrorReport>
33-
<WarningLevel>4</WarningLevel>
34-
</PropertyGroup>
35-
<ItemGroup>
36-
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
37-
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
38-
</Reference>
39-
<Reference Include="NPOI, Version=2.3.0.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
40-
<HintPath>..\packages\NPOI.2.3.0\lib\net40\NPOI.dll</HintPath>
41-
</Reference>
42-
<Reference Include="NPOI.OOXML, Version=2.3.0.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
43-
<HintPath>..\packages\NPOI.2.3.0\lib\net40\NPOI.OOXML.dll</HintPath>
44-
</Reference>
45-
<Reference Include="NPOI.OpenXml4Net, Version=2.3.0.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
46-
<HintPath>..\packages\NPOI.2.3.0\lib\net40\NPOI.OpenXml4Net.dll</HintPath>
47-
</Reference>
48-
<Reference Include="NPOI.OpenXmlFormats, Version=2.3.0.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
49-
<HintPath>..\packages\NPOI.2.3.0\lib\net40\NPOI.OpenXmlFormats.dll</HintPath>
50-
</Reference>
51-
<Reference Include="System" />
52-
<Reference Include="System.ComponentModel.DataAnnotations" />
53-
<Reference Include="System.Core" />
54-
</ItemGroup>
55-
<ItemGroup>
56-
<Compile Include="FluentConfigurationExtensions.cs" />
57-
<Compile Include="Program.cs" />
58-
<Compile Include="Properties\AssemblyInfo.cs" />
59-
<Compile Include="Report.cs" />
60-
</ItemGroup>
16+
6117
<ItemGroup>
62-
<ProjectReference Include="..\src\FluentExcel.csproj">
63-
<Project>{5addd29d-b3af-4966-b730-5e5192d0e9df}</Project>
64-
<Name>FluentExcel</Name>
65-
</ProjectReference>
18+
<ProjectReference Include="../src/FluentExcel.csproj" />
6619
</ItemGroup>
20+
6721
<ItemGroup>
68-
<None Include="packages.config" />
22+
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
6923
</ItemGroup>
70-
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
71-
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
72-
Other similar extension points exist, see Microsoft.Common.targets.
73-
<Target Name="BeforeBuild">
74-
</Target>
75-
<Target Name="AfterBuild">
76-
</Target>
77-
-->
78-
</Project>
24+
25+
</Project>

samples/Properties/AssemblyInfo.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/Excel.cs

Lines changed: 150 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,127 @@ public static class Excel
3232
/// <param name="sheetIndex">Which sheet to read.</param>
3333
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
3434
public static IEnumerable<T> Load<T>(string excelFile, int startRow = 1, int sheetIndex = 0) where T : class, new()
35+
=> Load<T>(excelFile, Setting, startRow, sheetIndex);
36+
37+
/// <summary>
38+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
39+
/// </summary>
40+
/// <typeparam name="T">The type of the model.</typeparam>
41+
/// <param name="excelFile">The excel file.</param>
42+
/// <param name="excelSetting">The excel setting to use to load data.</param>
43+
/// <param name="startRow">The row to start read.</param>
44+
/// <param name="sheetIndex">Which sheet to read.</param>
45+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
46+
public static IEnumerable<T> Load<T>(string excelFile, ExcelSetting excelSetting, int startRow = 1, int sheetIndex = 0) where T : class, new()
3547
{
36-
if (!File.Exists(excelFile))
37-
{
38-
throw new FileNotFoundException();
39-
}
48+
if (!File.Exists(excelFile)) throw new FileNotFoundException();
49+
50+
return Load<T>(File.OpenRead(excelFile), excelSetting, startRow, sheetIndex);
51+
}
52+
53+
/// <summary>
54+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
55+
/// </summary>
56+
/// <typeparam name="T">The type of the model.</typeparam>
57+
/// <param name="excelFile">The excel file.</param>
58+
/// <param name="sheetName">Which sheet to read.</param>
59+
/// <param name="startRow">The row to start read.</param>
60+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
61+
public static IEnumerable<T> Load<T>(string excelFile, string sheetName, int startRow = 1) where T : class, new()
62+
=> Load<T>(excelFile, Setting, sheetName, startRow);
63+
64+
/// <summary>
65+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
66+
/// </summary>
67+
/// <typeparam name="T">The type of the model.</typeparam>
68+
/// <param name="excelFile">The excel file.</param>
69+
/// <param name="excelSetting">The excel setting to use to load data.</param>
70+
/// <param name="sheetName">Which sheet to read.</param>
71+
/// <param name="startRow">The row to start read.</param>
72+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
73+
public static IEnumerable<T> Load<T>(string excelFile, ExcelSetting excelSetting, string sheetName, int startRow = 1) where T : class, new()
74+
{
75+
if (!File.Exists(excelFile)) throw new FileNotFoundException();
4076

41-
var workbook = InitializeWorkbook(excelFile);
77+
return Load<T>(File.OpenRead(excelFile), excelSetting, sheetName, startRow);
78+
}
79+
80+
/// <summary>
81+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
82+
/// </summary>
83+
/// <typeparam name="T">The type of the model.</typeparam>
84+
/// <param name="excelStream">The excel stream.</param>
85+
/// <param name="startRow">The row to start read.</param>
86+
/// <param name="sheetIndex">Which sheet to read.</param>
87+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
88+
public static IEnumerable<T> Load<T>(Stream excelStream, int startRow = 1, int sheetIndex = 0) where T : class, new()
89+
=> Load<T>(excelStream, Setting, startRow, sheetIndex);
4290

43-
// currently, only handle sheet one (or call side using foreach to support multiple sheet)
91+
/// <summary>
92+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
93+
/// </summary>
94+
/// <typeparam name="T">The type of the model.</typeparam>
95+
/// <param name="excelStream">The excel stream.</param>
96+
/// <param name="excelSetting">The excel setting to use to load data.</param>
97+
/// <param name="startRow">The row to start read.</param>
98+
/// <param name="sheetIndex">Which sheet to read.</param>
99+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
100+
public static IEnumerable<T> Load<T>(Stream excelStream, ExcelSetting excelSetting, int startRow = 1, int sheetIndex = 0) where T : class, new()
101+
{
102+
var workbook = InitializeWorkbook(excelStream);
103+
104+
// currently, only handle one sheet (or call side using foreach to support multiple sheet)
44105
var sheet = workbook.GetSheetAt(sheetIndex);
106+
if (null == sheet) throw new ArgumentException($"Excel sheet with specified index [{sheetIndex}] not found", nameof(sheetIndex));
107+
108+
return Load<T>(sheet, _formulaEvaluator, excelSetting, startRow);
109+
}
110+
111+
/// <summary>
112+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
113+
/// </summary>
114+
/// <typeparam name="T">The type of the model.</typeparam>
115+
/// <param name="excelStream">The excel stream.</param>
116+
/// <param name="sheetName">Which sheet to read.</param>
117+
/// <param name="startRow">The row to start read.</param>
118+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
119+
public static IEnumerable<T> Load<T>(Stream excelStream, string sheetName, int startRow = 1) where T : class, new()
120+
=> Load<T>(excelStream, Setting, sheetName, startRow);
121+
122+
/// <summary>
123+
/// Loading <see cref="IEnumerable{T}"/> from specified excel file. ///
124+
/// </summary>
125+
/// <typeparam name="T">The type of the model.</typeparam>
126+
/// <param name="excelStream">The excel stream.</param>
127+
/// <param name="excelSetting">The excel setting to use to load data.</param>
128+
/// <param name="sheetName">Which sheet to read.</param>
129+
/// <param name="startRow">The row to start read.</param>
130+
/// <returns>The <see cref="IEnumerable{T}"/> loading from excel.</returns>
131+
public static IEnumerable<T> Load<T>(Stream excelStream, ExcelSetting excelSetting, string sheetName, int startRow = 1) where T : class, new()
132+
{
133+
if (string.IsNullOrWhiteSpace(sheetName)) throw new ArgumentException($"sheet name cannot be null or whitespace", nameof(sheetName));
134+
135+
var workbook = InitializeWorkbook(excelStream);
136+
137+
// currently, only handle one sheet (or call side using foreach to support multiple sheet)
138+
var sheet = workbook.GetSheet(sheetName);
139+
if (null == sheet) throw new ArgumentException($"Excel sheet with specified name [{sheetName}] not found", nameof(sheetName));
140+
141+
return Load<T>(sheet, _formulaEvaluator, excelSetting, startRow);
142+
}
143+
144+
public static IEnumerable<T> Load<T>(ISheet sheet, IFormulaEvaluator formulaEvaluator, int startRow = 1) where T : class, new()
145+
=> Load<T>(sheet, formulaEvaluator, Excel.Setting, startRow);
146+
public static IEnumerable<T> Load<T>(ISheet sheet, IFormulaEvaluator formulaEvaluator, ExcelSetting excelSetting, int startRow = 1) where T : class, new()
147+
{
148+
if (null == sheet) throw new ArgumentNullException(nameof(sheet));
45149

46150
// get the writable properties
47151
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty);
48152

49153
bool fluentConfigEnabled = false;
50154
// get the fluent config
51-
if (Setting.FluentConfigs.TryGetValue(typeof(T), out var fluentConfig))
155+
if (excelSetting.FluentConfigs.TryGetValue(typeof(T), out var fluentConfig))
52156
{
53157
fluentConfigEnabled = true;
54158
}
@@ -136,12 +240,28 @@ public static class Excel
136240
}
137241
}
138242

139-
var value = row.GetCellValue(index, _formulaEvaluator);
243+
var value = row.GetCellValue(index, formulaEvaluator);
244+
245+
// give a chance to the cell value validator
246+
if (null != config?.CellValueValidator)
247+
{
248+
var validationResult = config.CellValueValidator(row.RowNum - 1, config.Index, value);
249+
if (false == validationResult)
250+
{
251+
if (fluentConfig.SkipInvalidRows)
252+
{
253+
itemIsValid = false;
254+
break;
255+
}
256+
257+
throw new ArgumentException($"Validation of cell value at row {row.RowNum}, column {config.Title}({config.Index + 1}) failed! Value: [{value}]");
258+
}
259+
}
140260

141261
// give a chance to the value converter.
142-
if (config?.ValueConverter != null)
262+
if (config?.CellValueConverter != null)
143263
{
144-
value = config.ValueConverter(value);
264+
value = config.CellValueConverter(row.RowNum - 1, config.Index, value);
145265
}
146266

147267
if (value == null)
@@ -173,6 +293,22 @@ public static class Excel
173293

174294
if (itemIsValid)
175295
{
296+
// give a chance to the row data validator
297+
if (null != fluentConfig?.RowDataValidator)
298+
{
299+
var validationResult = fluentConfig.RowDataValidator(row.RowNum - 1, item);
300+
if (false == validationResult)
301+
{
302+
if (fluentConfig.SkipInvalidRows)
303+
{
304+
itemIsValid = false;
305+
continue;
306+
}
307+
308+
throw new ArgumentException($"Validation of row data at row {row.RowNum} failed!");
309+
}
310+
}
311+
176312
list.Add(item);
177313
}
178314
}
@@ -242,11 +378,12 @@ internal static object GetDefault(this Type type)
242378
}
243379

244380
private static IWorkbook InitializeWorkbook(string excelFile)
381+
=> InitializeWorkbook(File.OpenRead(excelFile));
382+
private static IWorkbook InitializeWorkbook(Stream excelStream)
245383
{
246-
var extension = Path.GetExtension(excelFile);
247-
var workbook = WorkbookFactory.Create(new FileStream(excelFile, FileMode.Open, FileAccess.Read));
384+
var workbook = WorkbookFactory.Create(excelStream);
248385
_formulaEvaluator = workbook.GetCreationHelper().CreateFormulaEvaluator();
249386
return workbook;
250387
}
251388
}
252-
}
389+
}

src/ExcelSetting.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class ExcelSetting
3030
/// <summary>
3131
/// Gets or sets a value indicating whether to use *.xlsx file extension.
3232
/// </summary>
33-
public bool UserXlsx { get; set; } = true;
33+
public bool UseXlsx { get; set; } = true;
3434

3535
/// <summary>
3636
/// Gets or sets the title cell style applier.

0 commit comments

Comments
 (0)