================================================
FILE: docs/docfx.json
================================================
{
"metadata": [
{
"src": [
{
"src": "../src",
"files": [
"**/*.csproj"
]
}
],
"dest": "api"
}
],
"build": {
"content": [
{
"files": [
"**/*.{md,yml}"
],
"exclude": [
"_site/**"
]
}
],
"resource": [
{
"files": [
"**/images/**"
]
}
],
"output": "_site",
"template": [
"default",
"modern"
],
"globalMetadata": {
"_appName": "WeihanLi.Npoi",
"_appTitle": "WeihanLi.Npoi",
"_enableSearch": true,
"pdf": true
}
}
}
================================================
FILE: docs/toc.yml
================================================
- name: Home
href: index.md
- name: API Documentation
href: api/
- name: Release Notes
href: ReleaseNotes.md
- name: Articles
href: articles/
homepage: articles/intro.md
- name: Github
href: https://github.com/WeihanLi/WeihanLi.Npoi
================================================
FILE: global.json
================================================
{
"sdk": {
"rollForward": "major",
"version": "10.0.100"
},
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
================================================
FILE: nuget.config
================================================
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report-github.md
================================================
``` ini
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-WDPKYY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
```
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------------------------- |---------- |------------:|------------:|-----------:|------------:|------------:|------------:|------------:|-----------:|----------:|----------:|
| **ExportToCsvBytesTest** | **10000** | **22.77 ms** | **0.5667 ms** | **0.1472 ms** | **22.54 ms** | **22.95 ms** | **22.77 ms** | **2281.2500** | **937.5000** | **281.2500** | **12.12 MB** |
| NpoiExportToXlsBytesTest | 10000 | 219.87 ms | 3.8409 ms | 0.9975 ms | 218.92 ms | 221.40 ms | 219.60 ms | 6000.0000 | 2000.0000 | 1000.0000 | 43.99 MB |
| NpoiExportToXlsxBytesTest | 10000 | 470.79 ms | 9.3139 ms | 2.4188 ms | 467.01 ms | 473.70 ms | 471.26 ms | 20000.0000 | 6000.0000 | 2000.0000 | 104.31 MB |
| EpplusExportToBytesTest | 10000 | 203.82 ms | 5.0193 ms | 1.3035 ms | 203.13 ms | 206.15 ms | 203.25 ms | 11000.0000 | 4000.0000 | 1000.0000 | 56.66 MB |
| StructExportToCsvBytesTest | 10000 | 21.46 ms | 0.7542 ms | 0.1959 ms | 21.30 ms | 21.73 ms | 21.34 ms | 2281.2500 | 937.5000 | 281.2500 | 12.12 MB |
| NpoiStructExportToXlsBytesTest | 10000 | 212.54 ms | 12.7005 ms | 3.2983 ms | 209.21 ms | 216.65 ms | 211.42 ms | 7000.0000 | 3000.0000 | 1000.0000 | 44.37 MB |
| NpoiStructExportToXlsxBytesTest | 10000 | 495.55 ms | 45.1010 ms | 11.7126 ms | 482.73 ms | 514.33 ms | 492.62 ms | 20000.0000 | 7000.0000 | 2000.0000 | 104.69 MB |
| EpplusStructExportToBytesTest | 10000 | 208.60 ms | 5.3520 ms | 1.3899 ms | 206.94 ms | 210.32 ms | 208.32 ms | 11000.0000 | 4000.0000 | 1000.0000 | 56.66 MB |
| **ExportToCsvBytesTest** | **30000** | **72.16 ms** | **3.2924 ms** | **0.8550 ms** | **71.34 ms** | **73.59 ms** | **71.86 ms** | **6000.0000** | **1571.4286** | **571.4286** | **36.47 MB** |
| NpoiExportToXlsBytesTest | 30000 | 839.63 ms | 22.8596 ms | 5.9366 ms | 835.13 ms | 849.85 ms | 837.76 ms | 20000.0000 | 8000.0000 | 2000.0000 | 124.18 MB |
| NpoiExportToXlsxBytesTest | 30000 | 1,478.00 ms | 48.6880 ms | 12.6441 ms | 1,457.50 ms | 1,489.99 ms | 1,480.52 ms | 59000.0000 | 16000.0000 | 4000.0000 | 315.85 MB |
| EpplusExportToBytesTest | 30000 | 624.67 ms | 40.5093 ms | 10.5201 ms | 616.60 ms | 642.67 ms | 621.37 ms | 31000.0000 | 10000.0000 | 3000.0000 | 172.73 MB |
| StructExportToCsvBytesTest | 30000 | 63.51 ms | 2.5019 ms | 0.6497 ms | 62.53 ms | 64.25 ms | 63.58 ms | 5875.0000 | 1375.0000 | 375.0000 | 36.47 MB |
| NpoiStructExportToXlsBytesTest | 30000 | 853.48 ms | 33.3918 ms | 8.6718 ms | 839.53 ms | 862.13 ms | 856.08 ms | 20000.0000 | 8000.0000 | 2000.0000 | 125.32 MB |
| NpoiStructExportToXlsxBytesTest | 30000 | 1,516.05 ms | 141.2409 ms | 36.6798 ms | 1,474.05 ms | 1,553.23 ms | 1,534.14 ms | 59000.0000 | 16000.0000 | 4000.0000 | 317 MB |
| EpplusStructExportToBytesTest | 30000 | 624.10 ms | 18.2990 ms | 4.7522 ms | 616.20 ms | 627.98 ms | 624.45 ms | 31000.0000 | 10000.0000 | 3000.0000 | 172.72 MB |
| **ExportToCsvBytesTest** | **50000** | **113.06 ms** | **1.6585 ms** | **0.4307 ms** | **112.55 ms** | **113.55 ms** | **113.01 ms** | **10000.0000** | **2000.0000** | **800.0000** | **60.81 MB** |
| NpoiExportToXlsBytesTest | 50000 | 1,666.19 ms | 43.1443 ms | 11.2044 ms | 1,651.36 ms | 1,677.04 ms | 1,669.51 ms | 33000.0000 | 12000.0000 | 3000.0000 | 212.25 MB |
| NpoiExportToXlsxBytesTest | 50000 | 2,562.64 ms | 130.8702 ms | 33.9866 ms | 2,516.62 ms | 2,595.77 ms | 2,573.09 ms | 96000.0000 | 24000.0000 | 4000.0000 | 532.54 MB |
| EpplusExportToBytesTest | 50000 | 1,059.02 ms | 76.3548 ms | 19.8291 ms | 1,041.61 ms | 1,093.02 ms | 1,052.11 ms | 51000.0000 | 13000.0000 | 2000.0000 | 270.94 MB |
| StructExportToCsvBytesTest | 50000 | 108.91 ms | 4.0316 ms | 1.0470 ms | 107.28 ms | 110.19 ms | 108.95 ms | 10000.0000 | 2000.0000 | 800.0000 | 60.81 MB |
| NpoiStructExportToXlsBytesTest | 50000 | 1,675.32 ms | 63.9457 ms | 16.6065 ms | 1,660.80 ms | 1,703.80 ms | 1,669.06 ms | 33000.0000 | 12000.0000 | 3000.0000 | 214.15 MB |
| NpoiStructExportToXlsxBytesTest | 50000 | 2,505.01 ms | 231.4485 ms | 60.1064 ms | 2,443.93 ms | 2,576.48 ms | 2,494.21 ms | 96000.0000 | 24000.0000 | 4000.0000 | 534.45 MB |
| EpplusStructExportToBytesTest | 50000 | 1,031.01 ms | 17.5706 ms | 4.5630 ms | 1,027.89 ms | 1,038.94 ms | 1,029.03 ms | 51000.0000 | 13000.0000 | 2000.0000 | 270.93 MB |
| **ExportToCsvBytesTest** | **65535** | **147.35 ms** | **1.3296 ms** | **0.3453 ms** | **147.03 ms** | **147.83 ms** | **147.16 ms** | **12750.0000** | **2000.0000** | **500.0000** | **79.73 MB** |
| NpoiExportToXlsBytesTest | 65535 | 2,456.24 ms | 21.4291 ms | 5.5651 ms | 2,448.12 ms | 2,462.39 ms | 2,455.63 ms | 43000.0000 | 15000.0000 | 3000.0000 | 277.42 MB |
| NpoiExportToXlsxBytesTest | 65535 | 3,292.05 ms | 120.2493 ms | 31.2284 ms | 3,257.61 ms | 3,327.38 ms | 3,280.70 ms | 127000.0000 | 30000.0000 | 5000.0000 | 685.91 MB |
| EpplusExportToBytesTest | 65535 | 1,365.16 ms | 27.3326 ms | 7.0982 ms | 1,355.48 ms | 1,374.40 ms | 1,363.77 ms | 68000.0000 | 17000.0000 | 3000.0000 | 343.35 MB |
| StructExportToCsvBytesTest | 65535 | 141.21 ms | 6.6211 ms | 1.7195 ms | 139.06 ms | 143.00 ms | 141.42 ms | 12750.0000 | 2000.0000 | 500.0000 | 79.73 MB |
| NpoiStructExportToXlsBytesTest | 65535 | 2,505.47 ms | 83.5632 ms | 21.7011 ms | 2,483.53 ms | 2,536.38 ms | 2,504.97 ms | 43000.0000 | 15000.0000 | 3000.0000 | 279.92 MB |
| NpoiStructExportToXlsxBytesTest | 65535 | 3,235.57 ms | 116.3763 ms | 30.2226 ms | 3,205.37 ms | 3,284.36 ms | 3,230.79 ms | 127000.0000 | 30000.0000 | 5000.0000 | 688.39 MB |
| EpplusStructExportToBytesTest | 65535 | 1,349.52 ms | 8.8304 ms | 2.2932 ms | 1,346.47 ms | 1,352.90 ms | 1,349.45 ms | 67000.0000 | 16000.0000 | 3000.0000 | 343.35 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report.csv
================================================
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,PowerPlan,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,RowsCount,Mean,Error,StdDev,Min,Max,Median,Gen 0,Gen 1,Gen 2,Allocated
ExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,22.77 ms,0.5667 ms,0.1472 ms,22.54 ms,22.95 ms,22.77 ms,2281.2500,937.5000,281.2500,12.12 MB
NpoiExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,219.87 ms,3.8409 ms,0.9975 ms,218.92 ms,221.40 ms,219.60 ms,6000.0000,2000.0000,1000.0000,43.99 MB
NpoiExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,470.79 ms,9.3139 ms,2.4188 ms,467.01 ms,473.70 ms,471.26 ms,20000.0000,6000.0000,2000.0000,104.31 MB
EpplusExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,203.82 ms,5.0193 ms,1.3035 ms,203.13 ms,206.15 ms,203.25 ms,11000.0000,4000.0000,1000.0000,56.66 MB
StructExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,21.46 ms,0.7542 ms,0.1959 ms,21.30 ms,21.73 ms,21.34 ms,2281.2500,937.5000,281.2500,12.12 MB
NpoiStructExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,212.54 ms,12.7005 ms,3.2983 ms,209.21 ms,216.65 ms,211.42 ms,7000.0000,3000.0000,1000.0000,44.37 MB
NpoiStructExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,495.55 ms,45.1010 ms,11.7126 ms,482.73 ms,514.33 ms,492.62 ms,20000.0000,7000.0000,2000.0000,104.69 MB
EpplusStructExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,208.60 ms,5.3520 ms,1.3899 ms,206.94 ms,210.32 ms,208.32 ms,11000.0000,4000.0000,1000.0000,56.66 MB
ExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,72.16 ms,3.2924 ms,0.8550 ms,71.34 ms,73.59 ms,71.86 ms,6000.0000,1571.4286,571.4286,36.47 MB
NpoiExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,839.63 ms,22.8596 ms,5.9366 ms,835.13 ms,849.85 ms,837.76 ms,20000.0000,8000.0000,2000.0000,124.18 MB
NpoiExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"1,478.00 ms",48.6880 ms,12.6441 ms,"1,457.50 ms","1,489.99 ms","1,480.52 ms",59000.0000,16000.0000,4000.0000,315.85 MB
EpplusExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,624.67 ms,40.5093 ms,10.5201 ms,616.60 ms,642.67 ms,621.37 ms,31000.0000,10000.0000,3000.0000,172.73 MB
StructExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,63.51 ms,2.5019 ms,0.6497 ms,62.53 ms,64.25 ms,63.58 ms,5875.0000,1375.0000,375.0000,36.47 MB
NpoiStructExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,853.48 ms,33.3918 ms,8.6718 ms,839.53 ms,862.13 ms,856.08 ms,20000.0000,8000.0000,2000.0000,125.32 MB
NpoiStructExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"1,516.05 ms",141.2409 ms,36.6798 ms,"1,474.05 ms","1,553.23 ms","1,534.14 ms",59000.0000,16000.0000,4000.0000,317 MB
EpplusStructExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,624.10 ms,18.2990 ms,4.7522 ms,616.20 ms,627.98 ms,624.45 ms,31000.0000,10000.0000,3000.0000,172.72 MB
ExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,113.06 ms,1.6585 ms,0.4307 ms,112.55 ms,113.55 ms,113.01 ms,10000.0000,2000.0000,800.0000,60.81 MB
NpoiExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"1,666.19 ms",43.1443 ms,11.2044 ms,"1,651.36 ms","1,677.04 ms","1,669.51 ms",33000.0000,12000.0000,3000.0000,212.25 MB
NpoiExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"2,562.64 ms",130.8702 ms,33.9866 ms,"2,516.62 ms","2,595.77 ms","2,573.09 ms",96000.0000,24000.0000,4000.0000,532.54 MB
EpplusExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"1,059.02 ms",76.3548 ms,19.8291 ms,"1,041.61 ms","1,093.02 ms","1,052.11 ms",51000.0000,13000.0000,2000.0000,270.94 MB
StructExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,108.91 ms,4.0316 ms,1.0470 ms,107.28 ms,110.19 ms,108.95 ms,10000.0000,2000.0000,800.0000,60.81 MB
NpoiStructExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"1,675.32 ms",63.9457 ms,16.6065 ms,"1,660.80 ms","1,703.80 ms","1,669.06 ms",33000.0000,12000.0000,3000.0000,214.15 MB
NpoiStructExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"2,505.01 ms",231.4485 ms,60.1064 ms,"2,443.93 ms","2,576.48 ms","2,494.21 ms",96000.0000,24000.0000,4000.0000,534.45 MB
EpplusStructExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"1,031.01 ms",17.5706 ms,4.5630 ms,"1,027.89 ms","1,038.94 ms","1,029.03 ms",51000.0000,13000.0000,2000.0000,270.93 MB
ExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,147.35 ms,1.3296 ms,0.3453 ms,147.03 ms,147.83 ms,147.16 ms,12750.0000,2000.0000,500.0000,79.73 MB
NpoiExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"2,456.24 ms",21.4291 ms,5.5651 ms,"2,448.12 ms","2,462.39 ms","2,455.63 ms",43000.0000,15000.0000,3000.0000,277.42 MB
NpoiExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"3,292.05 ms",120.2493 ms,31.2284 ms,"3,257.61 ms","3,327.38 ms","3,280.70 ms",127000.0000,30000.0000,5000.0000,685.91 MB
EpplusExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"1,365.16 ms",27.3326 ms,7.0982 ms,"1,355.48 ms","1,374.40 ms","1,363.77 ms",68000.0000,17000.0000,3000.0000,343.35 MB
StructExportToCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,141.21 ms,6.6211 ms,1.7195 ms,139.06 ms,143.00 ms,141.42 ms,12750.0000,2000.0000,500.0000,79.73 MB
NpoiStructExportToXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"2,505.47 ms",83.5632 ms,21.7011 ms,"2,483.53 ms","2,536.38 ms","2,504.97 ms",43000.0000,15000.0000,3000.0000,279.92 MB
NpoiStructExportToXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"3,235.57 ms",116.3763 ms,30.2226 ms,"3,205.37 ms","3,284.36 ms","3,230.79 ms",127000.0000,30000.0000,5000.0000,688.39 MB
EpplusStructExportToBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"1,349.52 ms",8.8304 ms,2.2932 ms,"1,346.47 ms","1,352.90 ms","1,349.45 ms",67000.0000,16000.0000,3000.0000,343.35 MB
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report.html
================================================
WeihanLi.Npoi.Benchmark.ExportExcelTest-20191108-071719
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-WDPKYY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
| ExportToCsvBytesTest | 10000 | 22.77 ms | 0.5667 ms | 0.1472 ms | 22.54 ms | 22.95 ms | 22.77 ms | 2281.2500 | 937.5000 | 281.2500 | 12.12 MB |
| NpoiExportToXlsBytesTest | 10000 | 219.87 ms | 3.8409 ms | 0.9975 ms | 218.92 ms | 221.40 ms | 219.60 ms | 6000.0000 | 2000.0000 | 1000.0000 | 43.99 MB |
| NpoiExportToXlsxBytesTest | 10000 | 470.79 ms | 9.3139 ms | 2.4188 ms | 467.01 ms | 473.70 ms | 471.26 ms | 20000.0000 | 6000.0000 | 2000.0000 | 104.31 MB |
| EpplusExportToBytesTest | 10000 | 203.82 ms | 5.0193 ms | 1.3035 ms | 203.13 ms | 206.15 ms | 203.25 ms | 11000.0000 | 4000.0000 | 1000.0000 | 56.66 MB |
| StructExportToCsvBytesTest | 10000 | 21.46 ms | 0.7542 ms | 0.1959 ms | 21.30 ms | 21.73 ms | 21.34 ms | 2281.2500 | 937.5000 | 281.2500 | 12.12 MB |
| NpoiStructExportToXlsBytesTest | 10000 | 212.54 ms | 12.7005 ms | 3.2983 ms | 209.21 ms | 216.65 ms | 211.42 ms | 7000.0000 | 3000.0000 | 1000.0000 | 44.37 MB |
| NpoiStructExportToXlsxBytesTest | 10000 | 495.55 ms | 45.1010 ms | 11.7126 ms | 482.73 ms | 514.33 ms | 492.62 ms | 20000.0000 | 7000.0000 | 2000.0000 | 104.69 MB |
| EpplusStructExportToBytesTest | 10000 | 208.60 ms | 5.3520 ms | 1.3899 ms | 206.94 ms | 210.32 ms | 208.32 ms | 11000.0000 | 4000.0000 | 1000.0000 | 56.66 MB |
| ExportToCsvBytesTest | 30000 | 72.16 ms | 3.2924 ms | 0.8550 ms | 71.34 ms | 73.59 ms | 71.86 ms | 6000.0000 | 1571.4286 | 571.4286 | 36.47 MB |
| NpoiExportToXlsBytesTest | 30000 | 839.63 ms | 22.8596 ms | 5.9366 ms | 835.13 ms | 849.85 ms | 837.76 ms | 20000.0000 | 8000.0000 | 2000.0000 | 124.18 MB |
| NpoiExportToXlsxBytesTest | 30000 | 1,478.00 ms | 48.6880 ms | 12.6441 ms | 1,457.50 ms | 1,489.99 ms | 1,480.52 ms | 59000.0000 | 16000.0000 | 4000.0000 | 315.85 MB |
| EpplusExportToBytesTest | 30000 | 624.67 ms | 40.5093 ms | 10.5201 ms | 616.60 ms | 642.67 ms | 621.37 ms | 31000.0000 | 10000.0000 | 3000.0000 | 172.73 MB |
| StructExportToCsvBytesTest | 30000 | 63.51 ms | 2.5019 ms | 0.6497 ms | 62.53 ms | 64.25 ms | 63.58 ms | 5875.0000 | 1375.0000 | 375.0000 | 36.47 MB |
| NpoiStructExportToXlsBytesTest | 30000 | 853.48 ms | 33.3918 ms | 8.6718 ms | 839.53 ms | 862.13 ms | 856.08 ms | 20000.0000 | 8000.0000 | 2000.0000 | 125.32 MB |
| NpoiStructExportToXlsxBytesTest | 30000 | 1,516.05 ms | 141.2409 ms | 36.6798 ms | 1,474.05 ms | 1,553.23 ms | 1,534.14 ms | 59000.0000 | 16000.0000 | 4000.0000 | 317 MB |
| EpplusStructExportToBytesTest | 30000 | 624.10 ms | 18.2990 ms | 4.7522 ms | 616.20 ms | 627.98 ms | 624.45 ms | 31000.0000 | 10000.0000 | 3000.0000 | 172.72 MB |
| ExportToCsvBytesTest | 50000 | 113.06 ms | 1.6585 ms | 0.4307 ms | 112.55 ms | 113.55 ms | 113.01 ms | 10000.0000 | 2000.0000 | 800.0000 | 60.81 MB |
| NpoiExportToXlsBytesTest | 50000 | 1,666.19 ms | 43.1443 ms | 11.2044 ms | 1,651.36 ms | 1,677.04 ms | 1,669.51 ms | 33000.0000 | 12000.0000 | 3000.0000 | 212.25 MB |
| NpoiExportToXlsxBytesTest | 50000 | 2,562.64 ms | 130.8702 ms | 33.9866 ms | 2,516.62 ms | 2,595.77 ms | 2,573.09 ms | 96000.0000 | 24000.0000 | 4000.0000 | 532.54 MB |
| EpplusExportToBytesTest | 50000 | 1,059.02 ms | 76.3548 ms | 19.8291 ms | 1,041.61 ms | 1,093.02 ms | 1,052.11 ms | 51000.0000 | 13000.0000 | 2000.0000 | 270.94 MB |
| StructExportToCsvBytesTest | 50000 | 108.91 ms | 4.0316 ms | 1.0470 ms | 107.28 ms | 110.19 ms | 108.95 ms | 10000.0000 | 2000.0000 | 800.0000 | 60.81 MB |
| NpoiStructExportToXlsBytesTest | 50000 | 1,675.32 ms | 63.9457 ms | 16.6065 ms | 1,660.80 ms | 1,703.80 ms | 1,669.06 ms | 33000.0000 | 12000.0000 | 3000.0000 | 214.15 MB |
| NpoiStructExportToXlsxBytesTest | 50000 | 2,505.01 ms | 231.4485 ms | 60.1064 ms | 2,443.93 ms | 2,576.48 ms | 2,494.21 ms | 96000.0000 | 24000.0000 | 4000.0000 | 534.45 MB |
| EpplusStructExportToBytesTest | 50000 | 1,031.01 ms | 17.5706 ms | 4.5630 ms | 1,027.89 ms | 1,038.94 ms | 1,029.03 ms | 51000.0000 | 13000.0000 | 2000.0000 | 270.93 MB |
| ExportToCsvBytesTest | 65535 | 147.35 ms | 1.3296 ms | 0.3453 ms | 147.03 ms | 147.83 ms | 147.16 ms | 12750.0000 | 2000.0000 | 500.0000 | 79.73 MB |
| NpoiExportToXlsBytesTest | 65535 | 2,456.24 ms | 21.4291 ms | 5.5651 ms | 2,448.12 ms | 2,462.39 ms | 2,455.63 ms | 43000.0000 | 15000.0000 | 3000.0000 | 277.42 MB |
| NpoiExportToXlsxBytesTest | 65535 | 3,292.05 ms | 120.2493 ms | 31.2284 ms | 3,257.61 ms | 3,327.38 ms | 3,280.70 ms | 127000.0000 | 30000.0000 | 5000.0000 | 685.91 MB |
| EpplusExportToBytesTest | 65535 | 1,365.16 ms | 27.3326 ms | 7.0982 ms | 1,355.48 ms | 1,374.40 ms | 1,363.77 ms | 68000.0000 | 17000.0000 | 3000.0000 | 343.35 MB |
| StructExportToCsvBytesTest | 65535 | 141.21 ms | 6.6211 ms | 1.7195 ms | 139.06 ms | 143.00 ms | 141.42 ms | 12750.0000 | 2000.0000 | 500.0000 | 79.73 MB |
| NpoiStructExportToXlsBytesTest | 65535 | 2,505.47 ms | 83.5632 ms | 21.7011 ms | 2,483.53 ms | 2,536.38 ms | 2,504.97 ms | 43000.0000 | 15000.0000 | 3000.0000 | 279.92 MB |
| NpoiStructExportToXlsxBytesTest | 65535 | 3,235.57 ms | 116.3763 ms | 30.2226 ms | 3,205.37 ms | 3,284.36 ms | 3,230.79 ms | 127000.0000 | 30000.0000 | 5000.0000 | 688.39 MB |
| EpplusStructExportToBytesTest | 65535 | 1,349.52 ms | 8.8304 ms | 2.2932 ms | 1,346.47 ms | 1,352.90 ms | 1,349.45 ms | 67000.0000 | 16000.0000 | 3000.0000 | 343.35 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report-github.md
================================================
``` ini
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-WDPKYY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
```
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------ |---------- |-----------:|-----------:|-----------:|-----------:|-----------:|-----------:|------------:|-----------:|----------:|----------:|
| **ImportFromCsvBytesTest** | **10000** | **171.2 ms** | **2.904 ms** | **0.7541 ms** | **170.0 ms** | **172.0 ms** | **171.2 ms** | **9333.3333** | **2000.0000** | **333.3333** | **36.44 MB** |
| ImportFromXlsBytesTest | 10000 | 353.8 ms | 10.170 ms | 2.6412 ms | 351.8 ms | 358.4 ms | 352.9 ms | 15000.0000 | 6000.0000 | 2000.0000 | 64.71 MB |
| ImportFromXlsxBytesTest | 10000 | 758.2 ms | 10.212 ms | 2.6520 ms | 755.6 ms | 762.3 ms | 757.8 ms | 25000.0000 | 11000.0000 | 3000.0000 | 110.87 MB |
| **ImportFromCsvBytesTest** | **30000** | **511.5 ms** | **17.159 ms** | **4.4562 ms** | **504.0 ms** | **514.9 ms** | **512.7 ms** | **31000.0000** | **7000.0000** | **1000.0000** | **109.1 MB** |
| ImportFromXlsBytesTest | 30000 | 1,050.8 ms | 33.740 ms | 8.7622 ms | 1,040.2 ms | 1,064.3 ms | 1,049.8 ms | 47000.0000 | 18000.0000 | 3000.0000 | 186.28 MB |
| ImportFromXlsxBytesTest | 30000 | 2,358.6 ms | 284.891 ms | 73.9854 ms | 2,228.2 ms | 2,405.3 ms | 2,378.8 ms | 67000.0000 | 23000.0000 | 4000.0000 | 331.5 MB |
| **ImportFromCsvBytesTest** | **50000** | **860.7 ms** | **11.026 ms** | **2.8634 ms** | **857.3 ms** | **865.1 ms** | **860.0 ms** | **50000.0000** | **12000.0000** | **1000.0000** | **182 MB** |
| ImportFromXlsBytesTest | 50000 | 1,703.0 ms | 23.050 ms | 5.9861 ms | 1,695.9 ms | 1,709.7 ms | 1,703.3 ms | 76000.0000 | 28000.0000 | 2000.0000 | 315.85 MB |
| ImportFromXlsxBytesTest | 50000 | 3,869.8 ms | 141.111 ms | 36.6460 ms | 3,817.0 ms | 3,909.6 ms | 3,872.4 ms | 110000.0000 | 36000.0000 | 3000.0000 | 552.76 MB |
| **ImportFromCsvBytesTest** | **65535** | **1,144.7 ms** | **65.693 ms** | **17.0602 ms** | **1,121.2 ms** | **1,162.6 ms** | **1,149.4 ms** | **65000.0000** | **16000.0000** | **1000.0000** | **238.24 MB** |
| ImportFromXlsBytesTest | 65535 | 2,324.6 ms | 23.299 ms | 6.0507 ms | 2,318.4 ms | 2,333.9 ms | 2,323.8 ms | 99000.0000 | 35000.0000 | 3000.0000 | 413.07 MB |
| ImportFromXlsxBytesTest | 65535 | 5,011.3 ms | 108.362 ms | 28.1414 ms | 4,977.1 ms | 5,054.4 ms | 5,012.6 ms | 145000.0000 | 48000.0000 | 3000.0000 | 723.66 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report.csv
================================================
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,PowerPlan,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,RowsCount,Mean,Error,StdDev,Min,Max,Median,Gen 0,Gen 1,Gen 2,Allocated
ImportFromCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,171.2 ms,2.904 ms,0.7541 ms,170.0 ms,172.0 ms,171.2 ms,9333.3333,2000.0000,333.3333,36.44 MB
ImportFromXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,353.8 ms,10.170 ms,2.6412 ms,351.8 ms,358.4 ms,352.9 ms,15000.0000,6000.0000,2000.0000,64.71 MB
ImportFromXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,758.2 ms,10.212 ms,2.6520 ms,755.6 ms,762.3 ms,757.8 ms,25000.0000,11000.0000,3000.0000,110.87 MB
ImportFromCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,511.5 ms,17.159 ms,4.4562 ms,504.0 ms,514.9 ms,512.7 ms,31000.0000,7000.0000,1000.0000,109.1 MB
ImportFromXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"1,050.8 ms",33.740 ms,8.7622 ms,"1,040.2 ms","1,064.3 ms","1,049.8 ms",47000.0000,18000.0000,3000.0000,186.28 MB
ImportFromXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"2,358.6 ms",284.891 ms,73.9854 ms,"2,228.2 ms","2,405.3 ms","2,378.8 ms",67000.0000,23000.0000,4000.0000,331.5 MB
ImportFromCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,860.7 ms,11.026 ms,2.8634 ms,857.3 ms,865.1 ms,860.0 ms,50000.0000,12000.0000,1000.0000,182 MB
ImportFromXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"1,703.0 ms",23.050 ms,5.9861 ms,"1,695.9 ms","1,709.7 ms","1,703.3 ms",76000.0000,28000.0000,2000.0000,315.85 MB
ImportFromXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"3,869.8 ms",141.111 ms,36.6460 ms,"3,817.0 ms","3,909.6 ms","3,872.4 ms",110000.0000,36000.0000,3000.0000,552.76 MB
ImportFromCsvBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"1,144.7 ms",65.693 ms,17.0602 ms,"1,121.2 ms","1,162.6 ms","1,149.4 ms",65000.0000,16000.0000,1000.0000,238.24 MB
ImportFromXlsBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"2,324.6 ms",23.299 ms,6.0507 ms,"2,318.4 ms","2,333.9 ms","2,323.8 ms",99000.0000,35000.0000,3000.0000,413.07 MB
ImportFromXlsxBytesTest,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"5,011.3 ms",108.362 ms,28.1414 ms,"4,977.1 ms","5,054.4 ms","5,012.6 ms",145000.0000,48000.0000,3000.0000,723.66 MB
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report.html
================================================
WeihanLi.Npoi.Benchmark.ImportExcelTest-20191108-072305
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-WDPKYY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
| ImportFromCsvBytesTest | 10000 | 171.2 ms | 2.904 ms | 0.7541 ms | 170.0 ms | 172.0 ms | 171.2 ms | 9333.3333 | 2000.0000 | 333.3333 | 36.44 MB |
| ImportFromXlsBytesTest | 10000 | 353.8 ms | 10.170 ms | 2.6412 ms | 351.8 ms | 358.4 ms | 352.9 ms | 15000.0000 | 6000.0000 | 2000.0000 | 64.71 MB |
| ImportFromXlsxBytesTest | 10000 | 758.2 ms | 10.212 ms | 2.6520 ms | 755.6 ms | 762.3 ms | 757.8 ms | 25000.0000 | 11000.0000 | 3000.0000 | 110.87 MB |
| ImportFromCsvBytesTest | 30000 | 511.5 ms | 17.159 ms | 4.4562 ms | 504.0 ms | 514.9 ms | 512.7 ms | 31000.0000 | 7000.0000 | 1000.0000 | 109.1 MB |
| ImportFromXlsBytesTest | 30000 | 1,050.8 ms | 33.740 ms | 8.7622 ms | 1,040.2 ms | 1,064.3 ms | 1,049.8 ms | 47000.0000 | 18000.0000 | 3000.0000 | 186.28 MB |
| ImportFromXlsxBytesTest | 30000 | 2,358.6 ms | 284.891 ms | 73.9854 ms | 2,228.2 ms | 2,405.3 ms | 2,378.8 ms | 67000.0000 | 23000.0000 | 4000.0000 | 331.5 MB |
| ImportFromCsvBytesTest | 50000 | 860.7 ms | 11.026 ms | 2.8634 ms | 857.3 ms | 865.1 ms | 860.0 ms | 50000.0000 | 12000.0000 | 1000.0000 | 182 MB |
| ImportFromXlsBytesTest | 50000 | 1,703.0 ms | 23.050 ms | 5.9861 ms | 1,695.9 ms | 1,709.7 ms | 1,703.3 ms | 76000.0000 | 28000.0000 | 2000.0000 | 315.85 MB |
| ImportFromXlsxBytesTest | 50000 | 3,869.8 ms | 141.111 ms | 36.6460 ms | 3,817.0 ms | 3,909.6 ms | 3,872.4 ms | 110000.0000 | 36000.0000 | 3000.0000 | 552.76 MB |
| ImportFromCsvBytesTest | 65535 | 1,144.7 ms | 65.693 ms | 17.0602 ms | 1,121.2 ms | 1,162.6 ms | 1,149.4 ms | 65000.0000 | 16000.0000 | 1000.0000 | 238.24 MB |
| ImportFromXlsBytesTest | 65535 | 2,324.6 ms | 23.299 ms | 6.0507 ms | 2,318.4 ms | 2,333.9 ms | 2,323.8 ms | 99000.0000 | 35000.0000 | 3000.0000 | 413.07 MB |
| ImportFromXlsxBytesTest | 65535 | 5,011.3 ms | 108.362 ms | 28.1414 ms | 4,977.1 ms | 5,054.4 ms | 5,012.6 ms | 145000.0000 | 48000.0000 | 3000.0000 | 723.66 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report-github.md
================================================
``` ini
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-CBYTBY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
```
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------------- |---------- |-----------:|-----------:|------------:|-----------:|-----------:|-----------:|------:|--------:|------------:|-----------:|----------:|-----------:|
| **NpoiXlsWorkbookInit** | **10000** | **324.7 ms** | **1.583 ms** | **0.4110 ms** | **324.3 ms** | **325.4 ms** | **324.6 ms** | **1.00** | **0.00** | **10000.0000** | **5000.0000** | **2000.0000** | **78.6 MB** |
| NpoiXlsxWorkbookInit | 10000 | 1,369.0 ms | 73.747 ms | 19.1517 ms | 1,341.3 ms | 1,384.4 ms | 1,381.1 ms | 4.22 | 0.06 | 57000.0000 | 14000.0000 | 4000.0000 | 306.45 MB |
| EpplusWorkbookInit | 10000 | 552.9 ms | 12.740 ms | 3.3085 ms | 549.7 ms | 557.7 ms | 552.4 ms | 1.70 | 0.01 | 18000.0000 | 7000.0000 | 3000.0000 | 121.05 MB |
| | | | | | | | | | | | | | |
| **NpoiXlsWorkbookInit** | **30000** | **1,222.4 ms** | **33.717 ms** | **8.7562 ms** | **1,209.0 ms** | **1,233.1 ms** | **1,222.5 ms** | **1.00** | **0.00** | **29000.0000** | **11000.0000** | **3000.0000** | **235.03 MB** |
| NpoiXlsxWorkbookInit | 30000 | 4,226.2 ms | 299.833 ms | 77.8658 ms | 4,109.5 ms | 4,308.6 ms | 4,257.2 ms | 3.46 | 0.08 | 174000.0000 | 34000.0000 | 6000.0000 | 913.9 MB |
| EpplusWorkbookInit | 30000 | 1,695.4 ms | 31.751 ms | 8.2457 ms | 1,686.3 ms | 1,706.5 ms | 1,694.2 ms | 1.39 | 0.02 | 48000.0000 | 17000.0000 | 5000.0000 | 358.51 MB |
| | | | | | | | | | | | | | |
| **NpoiXlsWorkbookInit** | **50000** | **2,323.5 ms** | **236.041 ms** | **61.2990 ms** | **2,286.0 ms** | **2,431.9 ms** | **2,294.2 ms** | **1.00** | **0.00** | **47000.0000** | **18000.0000** | **4000.0000** | **417.1 MB** |
| NpoiXlsxWorkbookInit | 50000 | 7,055.2 ms | 279.256 ms | 72.5218 ms | 6,982.8 ms | 7,150.2 ms | 7,027.2 ms | 3.04 | 0.10 | 288000.0000 | 51000.0000 | 6000.0000 | 1545.32 MB |
| EpplusWorkbookInit | 50000 | 2,806.9 ms | 56.266 ms | 14.6121 ms | 2,792.9 ms | 2,829.1 ms | 2,804.6 ms | 1.21 | 0.03 | 79000.0000 | 27000.0000 | 7000.0000 | 578.46 MB |
| | | | | | | | | | | | | | |
| **NpoiXlsWorkbookInit** | **65535** | **3,646.8 ms** | **131.129 ms** | **34.0537 ms** | **3,603.0 ms** | **3,696.3 ms** | **3,642.5 ms** | **1.00** | **0.00** | **61000.0000** | **21000.0000** | **4000.0000** | **504.46 MB** |
| NpoiXlsxWorkbookInit | 65535 | 9,295.6 ms | 486.761 ms | 126.4104 ms | 9,163.3 ms | 9,468.6 ms | 9,330.5 ms | 2.55 | 0.04 | 390000.0000 | 67000.0000 | 8000.0000 | 2048.14 MB |
| EpplusWorkbookInit | 65535 | 3,721.6 ms | 124.945 ms | 32.4478 ms | 3,680.7 ms | 3,766.8 ms | 3,714.1 ms | 1.02 | 0.01 | 102000.0000 | 35000.0000 | 8000.0000 | 747.85 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.csv
================================================
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,PowerPlan,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,RowsCount,Mean,Error,StdDev,Min,Max,Median,Ratio,RatioSD,Gen 0,Gen 1,Gen 2,Allocated
NpoiXlsWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,324.7 ms,1.583 ms,0.4110 ms,324.3 ms,325.4 ms,324.6 ms,1.00,0.00,10000.0000,5000.0000,2000.0000,78.6 MB
NpoiXlsxWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,"1,369.0 ms",73.747 ms,19.1517 ms,"1,341.3 ms","1,384.4 ms","1,381.1 ms",4.22,0.06,57000.0000,14000.0000,4000.0000,306.45 MB
EpplusWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,10000,552.9 ms,12.740 ms,3.3085 ms,549.7 ms,557.7 ms,552.4 ms,1.70,0.01,18000.0000,7000.0000,3000.0000,121.05 MB
NpoiXlsWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"1,222.4 ms",33.717 ms,8.7562 ms,"1,209.0 ms","1,233.1 ms","1,222.5 ms",1.00,0.00,29000.0000,11000.0000,3000.0000,235.03 MB
NpoiXlsxWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"4,226.2 ms",299.833 ms,77.8658 ms,"4,109.5 ms","4,308.6 ms","4,257.2 ms",3.46,0.08,174000.0000,34000.0000,6000.0000,913.9 MB
EpplusWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,30000,"1,695.4 ms",31.751 ms,8.2457 ms,"1,686.3 ms","1,706.5 ms","1,694.2 ms",1.39,0.02,48000.0000,17000.0000,5000.0000,358.51 MB
NpoiXlsWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"2,323.5 ms",236.041 ms,61.2990 ms,"2,286.0 ms","2,431.9 ms","2,294.2 ms",1.00,0.00,47000.0000,18000.0000,4000.0000,417.1 MB
NpoiXlsxWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"7,055.2 ms",279.256 ms,72.5218 ms,"6,982.8 ms","7,150.2 ms","7,027.2 ms",3.04,0.10,288000.0000,51000.0000,6000.0000,1545.32 MB
EpplusWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,50000,"2,806.9 ms",56.266 ms,14.6121 ms,"2,792.9 ms","2,829.1 ms","2,804.6 ms",1.21,0.03,79000.0000,27000.0000,7000.0000,578.46 MB
NpoiXlsWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"3,646.8 ms",131.129 ms,34.0537 ms,"3,603.0 ms","3,696.3 ms","3,642.5 ms",1.00,0.00,61000.0000,21000.0000,4000.0000,504.46 MB
NpoiXlsxWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"9,295.6 ms",486.761 ms,126.4104 ms,"9,163.3 ms","9,468.6 ms","9,330.5 ms",2.55,0.04,390000.0000,67000.0000,8000.0000,2048.14 MB
EpplusWorkbookInit,Default,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,X64,Core,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,1,5,Default,1,Default,Default,Default,Default,Default,16,1,65535,"3,721.6 ms",124.945 ms,32.4478 ms,"3,680.7 ms","3,766.8 ms","3,714.1 ms",1.02,0.01,102000.0000,35000.0000,8000.0000,747.85 MB
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.html
================================================
WeihanLi.Npoi.Benchmark.WorkbookBasicTest-20191108-065532
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100
[Host] : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
Job-CBYTBY : .NET Core 2.2.6 (CoreCLR 4.6.27817.03, CoreFX 4.6.27818.02), 64bit RyuJIT
IterationCount=5 LaunchCount=1 WarmupCount=1
| Method | RowsCount | Mean | Error | StdDev | Min | Max | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
| NpoiXlsWorkbookInit | 10000 | 324.7 ms | 1.583 ms | 0.4110 ms | 324.3 ms | 325.4 ms | 324.6 ms | 1.00 | 0.00 | 10000.0000 | 5000.0000 | 2000.0000 | 78.6 MB |
| NpoiXlsxWorkbookInit | 10000 | 1,369.0 ms | 73.747 ms | 19.1517 ms | 1,341.3 ms | 1,384.4 ms | 1,381.1 ms | 4.22 | 0.06 | 57000.0000 | 14000.0000 | 4000.0000 | 306.45 MB |
| EpplusWorkbookInit | 10000 | 552.9 ms | 12.740 ms | 3.3085 ms | 549.7 ms | 557.7 ms | 552.4 ms | 1.70 | 0.01 | 18000.0000 | 7000.0000 | 3000.0000 | 121.05 MB |
| NpoiXlsWorkbookInit | 30000 | 1,222.4 ms | 33.717 ms | 8.7562 ms | 1,209.0 ms | 1,233.1 ms | 1,222.5 ms | 1.00 | 0.00 | 29000.0000 | 11000.0000 | 3000.0000 | 235.03 MB |
| NpoiXlsxWorkbookInit | 30000 | 4,226.2 ms | 299.833 ms | 77.8658 ms | 4,109.5 ms | 4,308.6 ms | 4,257.2 ms | 3.46 | 0.08 | 174000.0000 | 34000.0000 | 6000.0000 | 913.9 MB |
| EpplusWorkbookInit | 30000 | 1,695.4 ms | 31.751 ms | 8.2457 ms | 1,686.3 ms | 1,706.5 ms | 1,694.2 ms | 1.39 | 0.02 | 48000.0000 | 17000.0000 | 5000.0000 | 358.51 MB |
| NpoiXlsWorkbookInit | 50000 | 2,323.5 ms | 236.041 ms | 61.2990 ms | 2,286.0 ms | 2,431.9 ms | 2,294.2 ms | 1.00 | 0.00 | 47000.0000 | 18000.0000 | 4000.0000 | 417.1 MB |
| NpoiXlsxWorkbookInit | 50000 | 7,055.2 ms | 279.256 ms | 72.5218 ms | 6,982.8 ms | 7,150.2 ms | 7,027.2 ms | 3.04 | 0.10 | 288000.0000 | 51000.0000 | 6000.0000 | 1545.32 MB |
| EpplusWorkbookInit | 50000 | 2,806.9 ms | 56.266 ms | 14.6121 ms | 2,792.9 ms | 2,829.1 ms | 2,804.6 ms | 1.21 | 0.03 | 79000.0000 | 27000.0000 | 7000.0000 | 578.46 MB |
| NpoiXlsWorkbookInit | 65535 | 3,646.8 ms | 131.129 ms | 34.0537 ms | 3,603.0 ms | 3,696.3 ms | 3,642.5 ms | 1.00 | 0.00 | 61000.0000 | 21000.0000 | 4000.0000 | 504.46 MB |
| NpoiXlsxWorkbookInit | 65535 | 9,295.6 ms | 486.761 ms | 126.4104 ms | 9,163.3 ms | 9,468.6 ms | 9,330.5 ms | 2.55 | 0.04 | 390000.0000 | 67000.0000 | 8000.0000 | 2048.14 MB |
| EpplusWorkbookInit | 65535 | 3,721.6 ms | 124.945 ms | 32.4478 ms | 3,680.7 ms | 3,766.8 ms | 3,714.1 ms | 1.02 | 0.01 | 102000.0000 | 35000.0000 | 8000.0000 | 747.85 MB |
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/ExportExcelTest.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using BenchmarkDotNet.Attributes;
using EPPlus.Core.Extensions;
using EPPlus.Core.Extensions.Attributes;
using System.Runtime.CompilerServices;
namespace WeihanLi.Npoi.Benchmark;
[SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
[MemoryDiagnoser]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class ExportExcelTest
{
private class TestEntity
{
[ExcelTableColumn("PKID")]
public int PKID { get; set; }
[ExcelTableColumn("UserName")]
public string? Username { get; set; }
[ExcelTableColumn("PasswordHash")]
public string? PasswordHash { get; set; }
[ExcelTableColumn("Amount")]
public decimal Amount { get; set; }
[ExcelTableColumn("WechatOpenId")]
public string? WechatOpenId { get; set; }
[ExcelTableColumn("IsActive")]
public bool IsActive { get; set; }
[ExcelTableColumn("CreateTime")]
public DateTime CreateTime => DateTime.Now;
}
private struct TestStruct
{
[ExcelTableColumn("PKID")]
public int PKID { get; set; }
[ExcelTableColumn("UserName")]
public string? Username { get; set; }
[ExcelTableColumn("PasswordHash")]
public string? PasswordHash { get; set; }
[ExcelTableColumn("Amount")]
public decimal Amount { get; set; }
[ExcelTableColumn("WechatOpenId")]
public string? WechatOpenId { get; set; }
[ExcelTableColumn("IsActive")]
public bool IsActive { get; set; }
[ExcelTableColumn("CreateTime")]
public DateTime CreateTime => DateTime.Now;
}
private readonly List testData = new(51200);
private readonly List testStructData = new(51200);
[Params(10000, 30000, 50000, 65535)]
public int RowsCount;
[GlobalSetup]
public void GlobalSetup()
{
for (var i = 1; i <= RowsCount; i++)
{
testData.Add(new TestEntity()
{
Amount = 1000,
Username = "xxxx",
PKID = i,
});
testStructData.Add(new TestStruct()
{
Amount = 1000,
Username = "xxxx",
PKID = i,
});
}
}
[GlobalCleanup]
public void GlobalCleanup()
{
// Disposing logic
testData.Clear();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] ExportToCsvBytesTest()
{
return testData.ToCsvBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] NpoiExportToXlsBytesTest()
{
return testData.ToExcelBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] NpoiExportToXlsxBytesTest()
{
return testData.ToExcelBytes(ExcelFormat.Xlsx);
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] EpplusExportToBytesTest()
{
return testData.ToExcelPackage().GetAsByteArray();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] StructExportToCsvBytesTest()
{
return testStructData.ToCsvBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] NpoiStructExportToXlsBytesTest()
{
return testStructData.ToExcelBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] NpoiStructExportToXlsxBytesTest()
{
return testStructData.ToExcelBytes(ExcelFormat.Xlsx);
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] EpplusStructExportToBytesTest()
{
return testStructData.ToExcelPackage().GetAsByteArray();
}
}
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/ImportExcelTest.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
namespace WeihanLi.Npoi.Benchmark;
[SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
[MemoryDiagnoser]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class ImportExcelTest
{
private class TestEntity
{
public int PKID { get; set; }
public string? Username { get; set; }
public string? PasswordHash { get; set; }
public decimal Amount { get; set; }
public string? WechatOpenId { get; set; }
public bool IsActive { get; set; }
public DateTime CreateTime { get; set; } = DateTime.Now;
}
private readonly List testData = new(51200);
private byte[] xlsBytes = Array.Empty(), xlsxBytes = Array.Empty(), csvBytes = Array.Empty();
[Params(10000, 30000, 50000, 65535)]
public int RowsCount;
[GlobalSetup]
public void GlobalSetup()
{
for (var i = 1; i <= RowsCount; i++)
{
testData.Add(new TestEntity()
{
Amount = 1000,
Username = "xxxx",
PKID = i,
});
}
xlsBytes = testData.ToExcelBytes();
xlsxBytes = testData.ToExcelBytes(ExcelFormat.Xlsx);
csvBytes = testData.ToCsvBytes();
}
[GlobalCleanup]
public void GlobalCleanup()
{
// Disposing logic
testData.Clear();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public int ImportFromCsvBytesTest()
{
var list = CsvHelper.ToEntityList(csvBytes);
return list.Count;
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public int ImportFromXlsBytesTest()
{
var list = ExcelHelper.ToEntityList(xlsBytes, ExcelFormat.Xls);
return list.Count;
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public int ImportFromXlsxBytesTest()
{
var list = ExcelHelper.ToEntityList(xlsxBytes, ExcelFormat.Xlsx);
return list.Count;
}
}
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/Program.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using BenchmarkDotNet.Running;
namespace WeihanLi.Npoi.Benchmark;
public class Program
{
public static void Main(string[] args)
{
// BenchmarkRunner.Run();
BenchmarkRunner.Run();
BenchmarkRunner.Run();
}
}
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/WeihanLi.Npoi.Benchmark.csproj
================================================
Exe
================================================
FILE: perf/WeihanLi.Npoi.Benchmark/WorkbookBasicTest.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using BenchmarkDotNet.Attributes;
using OfficeOpenXml;
using System.Runtime.CompilerServices;
namespace WeihanLi.Npoi.Benchmark;
[SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
[MemoryDiagnoser]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class WorkbookBasicTest
{
private const int ColsCount = 10;
[Params(10000, 30000, 50000, 65535)]
public int RowsCount;
[Benchmark(Baseline = true)]
public byte[] NpoiXlsWorkbookInit()
{
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xls);
var sheet = workbook.CreateSheet("tempSheet");
for (var i = 0; i < RowsCount; i++)
{
var row = sheet.CreateRow(i);
for (var j = 0; j < ColsCount; j++)
{
var cell = row.CreateCell(j);
cell.SetCellValue($"as ({i}, {j}) sa");
}
}
return workbook.ToExcelBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] NpoiXlsxWorkbookInit()
{
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);
var sheet = workbook.CreateSheet("tempSheet");
for (var i = 0; i < RowsCount; i++)
{
var row = sheet.CreateRow(i);
for (var j = 0; j < ColsCount; j++)
{
var cell = row.CreateCell(j);
cell.SetCellValue($"as ({i}, {j}) sa");
}
}
return workbook.ToExcelBytes();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public byte[] EpplusWorkbookInit()
{
var excel = new ExcelPackage();
var sheet = excel.Workbook.Worksheets.Add("tempSheet");
for (var i = 1; i <= RowsCount; i++)
{
for (var j = 1; j <= ColsCount; j++)
{
sheet.Cells[i, j].Value = $"as ({i}, {j}) sa";
}
}
return excel.GetAsByteArray();
}
}
================================================
FILE: samples/Directory.Build.props
================================================
================================================
FILE: samples/DotNetCoreSample/DotNetCoreSample.csproj
================================================
Exe
Always
================================================
FILE: samples/DotNetCoreSample/ImportImageTestModel.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace DotNetCoreSample;
internal class ImportImageTestModel
{
public int Id { get; set; }
public string? Name { get; set; }
public byte[]? Image { get; set; }
}
================================================
FILE: samples/DotNetCoreSample/IssueSamples.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Extensions;
public static partial class IssueSamples
{
public static void Issue169Sample()
{
var filePath = @"C:\Users\Weiha\Downloads\test\2.xlsx";
var workbook = ExcelHelper.LoadExcel(
File.OpenRead(filePath),
ExcelFormat.Xlsx
);
var settings = FluentSettings.For();
settings.WithPostImportAction((x, rowIndex) => x?.RowNum = rowIndex + 1);
var list = workbook.ToEntityList();
foreach (var item in list)
{
Console.WriteLine(item.ToJson());
}
}
}
[Sheet(SheetIndex = 0, StartRowIndex = 6)]
public class Issue169Dto
{
[Column(IsIgnored = true)]
public int RowNum { get; set; }
///
/// 编号
///
[Column("物料编号", Index = 0)]
public string No { get; set; }
///
/// 物料名称
///
[Column("物料名称", Index = 1)]
public string Name { get; set; }
///
/// 规格型号
///
[Column("规格型号", Index = 2)]
public string Specification { get; set; }
///
/// 特殊库存
///
[Column("特殊库存", Index = 3)]
public string QuantityM { get; set; }
///
/// 单位
///
[Column("计量单位", Index = 4)]
public string Unit { get; set; }
[Column("会计年度", Index = 5)]
public int Ytime { get; set; }
[Column("会计期间", Index = 6)]
public int Mtime { get; set; }
// 期初余额
[Column("方向", Index = 7)]
public string Direction1 { get; set; }
///
/// 数量
///
[Column("数量", Index = 8)]
public decimal Quantity1 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 9)]
public decimal UnitPrice1 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 10)]
public decimal TotalAmount1 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 11)]
public decimal StandardUnitPrice1 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 12)]
public decimal StandardotalAmount1 { get; set; }
// 期初余额
//本期借方
///
/// 数量
///
[Column("数量", Index = 13)]
public decimal Quantity2 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 14)]
public decimal UnitPrice2 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 15)]
public decimal TotalAmount2 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 16)]
public decimal StandardUnitPrice2 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 17)]
public decimal StandardotalAmount2 { get; set; }
//本期贷方
///
/// 数量
///
[Column("数量", Index = 18)]
public decimal Quantity3 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 19)]
public decimal UnitPrice3 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 20)]
public decimal TotalAmount3 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 21)]
public decimal StandardUnitPrice3 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 22)]
public decimal StandardotalAmount3 { get; set; }
//期末余额
[Column("方向", Index = 23)]
public string Direction2 { get; set; }
///
/// 数量
///
[Column("数量", Index = 24)]
public decimal Quantity4 { get; set; }
///
/// 实际单价
///
[Column("实际单价", Index = 25)]
public decimal UnitPrice4 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 26)]
public decimal TotalAmount4 { get; set; }
[Column("核算类别名称", Index = 27)]
public string CategoryName { get; set; }
[Column("是否可用", Index = 28)]
public string IsStop { get; set; }
}
================================================
FILE: samples/DotNetCoreSample/ProductPriceMapping.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
// ReSharper disable InconsistentNaming
namespace DotNetCoreSample;
internal class ProductPriceMapping
{
public string? Type { get; set; }
public string? Pid { get; set; }
public string? ShopCode { get; set; }
public decimal Price { get; set; }
public long ItemID { get; set; }
public long SkuID { get; set; }
public DateTime LastUpdateDateTime { get; set; }
}
================================================
FILE: samples/DotNetCoreSample/Program.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using WeihanLi.Common.Helpers;
using WeihanLi.Common.Logging;
using WeihanLi.Extensions;
// ReSharper disable All
LogHelper.ConfigureLogging(x => x.WithMinimumLevel(LogHelperLogLevel.Info).AddConsole());
{
IssueSamples.Issue169Sample();
ConsoleHelper.ReadLineWithPrompt();
}
// multi sheets sample
{
var collection1 = new List()
{
new TestEntity()
{
PKID = 1,
SettingId = Guid.NewGuid(),
SettingName = "Setting1",
SettingValue = "Value1",
DisplayName = "dd"
},
new TestEntity()
{
PKID=2,
SettingId = Guid.NewGuid(),
SettingName = "Setting2",
SettingValue = "Value2",
Enabled = true
},
};
await collection1.ToCsvFileAsync($"{nameof(collection1)}.csv");
var collection2 = new[]
{
new TestEntity2()
{
Id = 999,
Title = "test"
}
};
// prepare a workbook
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);
workbook.ImportData(collection1);
workbook.ImportData(collection2, 1);
workbook.WriteToFile("multi-sheets-sample.xlsx");
// using var ms = new MemoryStream();
// workbook.Write(ms);
Console.WriteLine("multi-sheets-sample excel generated.");
Console.ReadLine();
}
//
// var testSurveyExcelPath = @"C:\Users\Weiha\Desktop\temp\QuizBulkUpload.xlsx";
// var surveyList = ExcelHelper.ToEntityList(testSurveyExcelPath);
// SheetNameTest();
FluentSettings.LoadMappingProfile();
var tempDirPath = $@"{Environment.GetEnvironmentVariable("USERPROFILE")}\Desktop\temp\test";
{
// custom CsvSeparatorCharacter sample
var csvOptions = new CsvOptions() { SeparatorCharacter = '\t' };
var text = CsvHelper.GetCsvText(new[]
{
new
{
Title = "123",
Desc = "234"
}
}, csvOptions);
var dt1233 = CsvHelper.ToDataTable(text.GetBytes(), csvOptions);
}
// image export/import test
//var imageExcelPath = @"C:\Users\Weiha\Desktop\temp\test\imageTest.xls";
//var imgaeModelList = ExcelHelper.ToEntityList(imageExcelPath);
//Console.WriteLine(imgaeModelList.Count(x => x?.Image is not null));
//imgaeModelList.ToExcelFile(imageExcelPath + ".1.xls");
//var imgModeList2 = ExcelHelper.ToEntityList(imageExcelPath + ".1.xls");
//Console.WriteLine($"{imgaeModelList[0]?.Image?.Length},{imgModeList2[0]?.Image?.Length}");
//imgaeModelList.ToExcelFile(imageExcelPath + ".1.xlsx");
//Console.ReadLine();
//FluentSettings.For()
// .HasSheetSetting(sheet =>
// {
// sheet.CellFilter = cell => cell.ColumnIndex <= 10;
// });
//var tempExcelPath = Path.Combine(tempDirPath, "testdata.xlsx");
//var t_list = ExcelHelper.ToEntityList(tempExcelPath);
//var tempTable = ExcelHelper.ToDataTable(tempExcelPath);
//var entityList = ExcelHelper.ToEntityList(ApplicationHelper.MapPath("test.xlsx"));
//Console.WriteLine("Success!");
//var mapping = ExcelHelper.ToEntityList($@"{Environment.GetEnvironmentVariable("USERPROFILE")}\Desktop\temp\tempFiles\mapping.xlsx");
//var mappingTemp = ExcelHelper.ToEntityList($@"{Environment.GetEnvironmentVariable("USERPROFILE")}\Desktop\temp\tempFiles\mapping_temp.xlsx");
//Console.WriteLine($"-----normal({mapping.Count}【{mapping.Select(_ => _.Pid).Distinct().Count()}】)----");
//foreach (var shop in mapping.GroupBy(_ => _.ShopCode).OrderBy(_ => _.Key))
//{
// Console.WriteLine($"{shop.Key}---{shop.Count()}---distinct pid count:{shop.Select(_ => _.Pid).Distinct().Count()}");
//}
//Console.WriteLine($"-----temp({mappingTemp.Count}【{mappingTemp.Select(_ => _.Pid).Distinct().Count()}】)----");
//foreach (var shop in mappingTemp.GroupBy(_ => _.ShopCode).OrderBy(_ => _.Key))
//{
// Console.WriteLine($"{shop.Key}---{shop.Count()}---distinct pid count:{shop.Select(_ => _.Pid).Distinct().Count()}");
//}
//Console.WriteLine("Press Enter to continue...");
//Console.ReadLine();
//var list2 = new List();
//list2.Add(null);
//for (var i = 0; i < 100_000; i++)
//{
// list2.Add(new TestEntity2
// {
// Id = i + 1,
// Title = $"Title_{i}",
// Description = $"{Enumerable.Range(1, 200).StringJoin(",")}__{i}",
// });
//}
//list2.Add(new TestEntity2()
//{
// Id = 999,
// Title = $"{Enumerable.Repeat(1, 10).StringJoin(",")}",
// Description = null
//});
//var watch = Stopwatch.StartNew();
//list2.ToExcelFile($@"{tempDirPath}\testEntity2.xls");
//watch.Stop();
//Console.WriteLine($"ElapsedMilliseconds: {watch.ElapsedMilliseconds}ms");
////var listTemp = ExcelHelper.ToEntityList($@"{tempDirPath}\testEntity2.xlsx");
//var dataTableTemp = ExcelHelper.ToDataTable($@"{tempDirPath}\testEntity2.xlsx");
//Console.WriteLine("Press Enter to continue...");
//Console.ReadLine();
var entities = new List()
{
new TestEntity()
{
PKID = 1,
SettingId = Guid.NewGuid(),
SettingName = "Setting1",
SettingValue = "Value1",
DisplayName = "dd\"d,1"
},
new TestEntity()
{
PKID=2,
SettingId = Guid.NewGuid(),
SettingName = "Setting2",
SettingValue = "Value2",
Enabled = true,
CreatedBy = "li\"_"
},
};
entities.ToCsvFile("test.csv");
var csvFilePath = $@"{tempDirPath}\test.csv";
//entities.ToExcelFileByTemplate(
// Path.Combine(ApplicationHelper.AppRoot, "Templates", "testTemplate.xlsx"),
// ApplicationHelper.MapPath("templateTestEntities.xlsx"),
// extraData: new
// {
// Author = "WeihanLi",
// Title = "Export Result"
// }
//);
entities.ToExcelFile(csvFilePath.Replace(".csv", ".xlsx"));
entities.ToCsvFile(csvFilePath);
var entitiesT0 = ExcelHelper.ToEntityList(csvFilePath.Replace(".csv", ".xlsx"));
var dataTable = entities.ToDataTable();
dataTable.ToCsvFile(csvFilePath.Replace(".csv", ".datatable.csv"));
var dt = CsvHelper.ToDataTable(csvFilePath.Replace(".csv", ".datatable.csv"));
Console.WriteLine(dt.Columns.Count);
var entities1 = CsvHelper.ToEntityList(csvFilePath);
entities1[1]!.DisplayName = ",tadadada";
entities1[0]!.SettingValue = "value2,345";
entities1.ToCsvFile(csvFilePath.Replace(".csv", ".1.csv"));
entities1.ToDataTable().ToCsvFile(csvFilePath.Replace(".csv", ".1.datatable.csv"));
var list = CsvHelper.ToEntityList(csvFilePath.Replace(".csv", ".1.csv"));
dt = CsvHelper.ToDataTable(csvFilePath.Replace(".csv", ".1.datatable.csv"));
Console.WriteLine(dt.Columns.Count);
var entities2 = CsvHelper.ToEntityList(csvFilePath.Replace(".csv", ".1.csv"));
entities.ToExcelFile(csvFilePath.Replace(".csv", ".xlsx"));
var vals = new[] { 1, 2, 3, 5, 4 };
vals.ToCsvFile(csvFilePath);
var numList = CsvHelper.ToEntityList(csvFilePath);
Console.WriteLine(numList.StringJoin(","));
Console.ReadLine();
SheetNameTest();
static void SheetNameTest()
{
List exprotDataList = new List();
for (int i = 0; i < 10; i++)
{
var temp = new ExcelExportDTO
{
Name = "张三" + i,
Address = "北京海淀" + i,
Birthday = DateTime.Now,
Remark = "Remark" + i
};
exprotDataList.Add(temp);
}
var setting = FluentSettings.For();
setting.HasSheetConfiguration(1, "我是一个Sheet_111", true);
setting.HasSheetSetting(s =>
{
s.SheetName = "Shee-0000";
});
var deskTopFullPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var exportFileName = Path.Combine(deskTopFullPath, "Test_for_weihanli.xlsx");
exprotDataList.ToExcelFile(exportFileName);
}
class TestEntityExcelMappingProfile : IMappingProfile
{
public void Configure(IExcelConfiguration setting)
{
// ExcelSetting
setting.HasAuthor("WeihanLi")
.HasTitle("WeihanLi.Npoi test")
.HasDescription("WeihanLi.Npoi test")
.HasSubject("WeihanLi.Npoi test")
;
setting.HasSheetSetting(config =>
{
config.StartRowIndex = 1;
config.SheetName = "SystemSettingsList";
config.AutoColumnWidthEnabled = true;
config.RowAction = row =>
{
if (row.RowNum == 0)
{
var style = row.Sheet.Workbook.CreateCellStyle();
style.Alignment = HorizontalAlignment.Center;
var font = row.Sheet.Workbook.CreateFont();
font.FontName = "JetBrains Mono";
font.IsBold = true;
font.FontHeight = 200;
style.SetFont(font);
row.Cells.ForEach(c => c.CellStyle = style);
}
};
config.CellAction = cell =>
{
if (cell.RowIndex == 0 && cell.StringCellValue == "EntityType")
{
var enumNames = Enum.GetNames();
var validationHelper = cell.Sheet.GetDataValidationHelper();
var constraint = validationHelper.CreateExplicitListConstraint(enumNames);
var addressList = new CellRangeAddressList(1, 3, cell.ColumnIndex, cell.ColumnIndex); // Col B
var validation = validationHelper.CreateValidation(constraint, addressList);
validation.ShowErrorBox = true;
cell.Sheet.AddValidationData(validation);
}
};
});
// setting.HasFilter(0, 1).HasFreezePane(0, 1, 2, 1);
setting.Property(_ => _.SettingId)
.HasColumnIndex(0);
setting.Property(_ => _.SettingName)
.HasColumnTitle("SettingName")
.HasColumnIndex(1);
setting.Property(_ => _.DisplayName)
.HasOutputFormatter((entity, displayName) => $"AAA_{entity?.SettingName}_{displayName}")
.HasInputFormatter((entity, originVal) => originVal?.Split(new[] { '_' })[2])
.HasColumnTitle("DisplayName")
.HasColumnIndex(2);
setting.Property(_ => _.SettingValue)
.HasColumnTitle("SettingValue")
.HasColumnIndex(3);
setting.Property(_ => _.CreatedTime)
.HasColumnTitle("CreatedTime")
.HasColumnIndex(4)
.HasColumnWidth(10)
.HasColumnFormatter("yyyy-MM-dd HH:mm:ss");
setting.Property(_ => _.CreatedBy)
.HasColumnInputFormatter(x => x += "_test")
.HasColumnIndex(4)
.HasColumnTitle("CreatedBy");
setting.Property(x => x.Enabled)
.HasColumnInputFormatter(val => "Enabled".EqualsIgnoreCase(val))
.HasColumnOutputFormatter(v => v ? "Enabled" : "Disabled");
setting.Property("HiddenProp")
.HasOutputFormatter((entity, val) => $"HiddenProp_{entity?.PKID}");
setting.Property(x => x.Type)
.HasColumnTitle("EntityType")
.HasColumnIndex(8);
setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
}
}
internal abstract class BaseEntity
{
public int PKID { get; set; }
}
internal class TestEntity : BaseEntity
{
public Guid SettingId { get; set; }
public string? SettingName { get; set; }
public string? DisplayName { get; set; }
public string? SettingValue { get; set; }
public string CreatedBy { get; set; } = "liweihan";
public DateTime CreatedTime { get; set; } = DateTime.Now;
public string? UpdatedBy { get; set; }
public DateTime UpdatedTime { get; set; }
public bool Enabled { get; set; }
public EntityType Type { get; set; }
}
public enum EntityType
{
Default = 0,
Special = 1
}
[Sheet(SheetIndex = 0, SheetName = "TestSheet", AutoColumnWidthEnabled = true)]
internal class TestEntity2
{
[Column(Index = 0)]
public int Id { get; set; }
[Column(Index = 1)]
public string? Title { get; set; }
[Column(Index = 2, Width = 50)]
public string? Description { get; set; }
[Column(Index = 3, Width = 20)]
public string? Extra { get; set; } = "{}";
}
public class ExcelExportDTO
{
[Column("姓名")]
public string? Name { get; set; }
[Column("住址")]
public string? Address { get; set; }
[Column("出生日期")]
public DateTime Birthday { get; set; }
public string? Remark { get; set; }
}
#nullable disable
internal sealed class SurveyImportDto
{
[Column(IsIgnored = true)]
public string ExternalId { get; set; }
[Column(0)]
public string ContentSource { get; set; }
[Column(1)]
public string ExternalKey { get; set; }
[Column(2)]
public string Title { get; set; }
[Column(3)]
public string OptionA { get; set; }
[Column(4)]
public string OptionB { get; set; }
[Column(5)]
public string OptionC { get; set; }
[Column(6)]
public string CorrectAnswer { get; set; }
[Column(7)]
public string Tips { get; set; }
}
#nullable restore
================================================
FILE: samples/DotNetCoreSample/TestModel.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace DotNetCoreSample;
[Sheet(SheetIndex = 0, SheetName = "Abc", StartRowIndex = 1, EndRowIndex = 10, StartColumnIndex = 1, EndColumnIndex = 19)]
internal class ppDto
{
[Column("创建日期")]
public DateTime? CreateDate { get; set; }
[Column("体积")]
public decimal? Volume { get; set; }
[Column("总重量")]
public decimal? TotalWeight { get; set; }
[Column("出错")]
public string? Error { get; set; }
[Column("真假")]
public Boolean? TrueOrFalse { get; set; }
[Column("范围")]
public string? Range { get; set; }
[Column("从")]
public long? CtnFm { get; set; }
[Column("到")]
public long? CtnTo { get; set; }
[Column("开始序列号")]
public long? SerialStart { get; set; }
[Column("截止序列号")]
public long? SerialEnd { get; set; }
[Column("包装代码")]
public string? PackCode { get; set; }
[Column("行号")]
public string? Row { get; set; }
[Column("买方项目号")]
public string? BuyerNo { get; set; }
[Column("SKU号")]
public string? SKUNo { get; set; }
[Column("订单号码")]
public string? TradingPO { get; set; }
[Column("MAIN LINE #")]
public string? Item { get; set; }
[Column("Color Name")]
public string? ColorCode { get; set; }
[Column("Size")]
public string? Size { get; set; }
[Column("简短描述")]
public string? ContractColor { get; set; }
[Column("发货方式")]
public string? ShipWay { get; set; }
[Column("数量")]
public int? TtlQty { get; set; }
[Column("内部包装的项目数量")]
public int? Qty { get; set; }
[Column("内包装计数")]
public int? RatioQty { get; set; }
[Column("箱数")]
public int? CntQty { get; set; }
[Column("R")]
public string? LastCarton { get; set; }
[Column("外箱代码")]
public string? CartonCode { get; set; }
[Column("净净重")]
public decimal? NNWeight { get; set; }
[Column("净重")]
public decimal? NWeight { get; set; }
[Column("毛重")]
public decimal? GWeight { get; set; }
[Column("单位")]
public string? Unit { get; set; }
[Column("长")]
public decimal? cartonL { get; set; }
[Column("宽")]
public decimal? cartonW { get; set; }
[Column("高")]
public decimal? cartonH { get; set; }
[Column("单位2")]
public string? Unit2 { get; set; }
[Column("扫描ID")]
public string? ScanID { get; set; }
}
================================================
FILE: samples/run-file-samples/issue-169.cs
================================================
var filePath = @"C:\Users\Weiha\Downloads\test\2.xlsx";
var workbook = ExcelHelper.LoadExcel(
File.OpenRead(filePath),
ExcelFormat.Xlsx
);
var settings = FluentSettings.For();
settings.WithPostImportAction((x, rowIndex) => x?.RowNum = rowIndex + 1);
var list = workbook.ToEntityList();
foreach (var item in list)
{
Console.WriteLine($"#{item.RowNum}\t => {item.No}\t{item.Name}\t{item.Specification}\t{item.QuantityM}\t{item.Unit}\t{item.TotalAmount4}\t{item.CategoryName}\t{item.IsStop}");
}
[Sheet(SheetIndex = 0, StartRowIndex = 6)]
public class MaterielDetailDto
{
public int RowNum { get; set; }
///
/// 编号
///
[Column("物料编号", Index = 0)]
public string No { get; set; }
///
/// 物料名称
///
[Column("物料名称", Index = 1)]
public string Name { get; set; }
///
/// 规格型号
///
[Column("规格型号", Index = 2)]
public string Specification { get; set; }
///
/// 特殊库存
///
[Column("特殊库存", Index = 3)]
public string QuantityM { get; set; }
///
/// 单位
///
[Column("计量单位", Index = 4)]
public string Unit { get; set; }
[Column("会计年度", Index = 5)]
public int Ytime { get; set; }
[Column("会计期间", Index = 6)]
public int Mtime { get; set; }
// 期初余额
[Column("方向", Index = 7)]
public string Direction1 { get; set; }
///
/// 数量
///
[Column("数量", Index = 8)]
public decimal Quantity1 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 9)]
public decimal UnitPrice1 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 10)]
public decimal TotalAmount1 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 11)]
public decimal StandardUnitPrice1 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 12)]
public decimal StandardotalAmount1 { get; set; }
// 期初余额
//本期借方
///
/// 数量
///
[Column("数量", Index = 13)]
public decimal Quantity2 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 14)]
public decimal UnitPrice2 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 15)]
public decimal TotalAmount2 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 16)]
public decimal StandardUnitPrice2 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 17)]
public decimal StandardotalAmount2 { get; set; }
//本期贷方
///
/// 数量
///
[Column("数量", Index = 18)]
public decimal Quantity3 { get; set; }
///
/// 单价
///
[Column("实际单价", Index = 19)]
public decimal UnitPrice3 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 20)]
public decimal TotalAmount3 { get; set; }
///
/// 标准单价
///
[Column("标准单价", Index = 21)]
public decimal StandardUnitPrice3 { get; set; }
///
/// 标准金额
///
[Column("标准金额", Index = 22)]
public decimal StandardotalAmount3 { get; set; }
//期末余额
[Column("方向", Index = 23)]
public string Direction2 { get; set; }
///
/// 数量
///
[Column("数量", Index = 24)]
public decimal Quantity4 { get; set; }
///
/// 实际单价
///
[Column("实际单价", Index = 25)]
public decimal UnitPrice4 { get; set; }
///
/// 总金额
///
[Column("实际金额", Index = 26)]
public decimal TotalAmount4 { get; set; }
[Column("核算类别名称", Index = 27)]
public string CategoryName { get; set; }
[Column("是否可用", Index = 28)]
public string IsStop { get; set; }
}
================================================
FILE: samples/run-file-samples/style-customization-sample.cs
================================================
using NPOI.SS.UserModel;
using NPOI.SS.Util;
FluentSettings.LoadMappingProfile();
var list = new List
{
new StyledEntity { Id = 1, Name = "Alice", Amount = 1500.50m, Status = "Approved", Date = DateTime.Now.AddDays(-10) },
new StyledEntity { Id = 2, Name = "Bob", Amount = -200.75m, Status = "Pending", Date = DateTime.Now.AddDays(-5) },
new StyledEntity { Id = 3, Name = "Charlie", Amount = 300.00m, Status = "Rejected", Date = DateTime.Now.AddDays(-2) },
new StyledEntity { Id = 4, Name = "Diana", Amount = 450.25m, Status = "Approved", Date = DateTime.Now.AddDays(-1) },
};
const string path = @"C:\Users\Weiha\Downloads\test\styled-report.xlsx";
list.ToExcelFile(path);
Console.WriteLine($"Excel file generated at: {path}");
public class StyledEntity
{
public int Id { get; set; }
public required string Name { get; set; }
public decimal Amount { get; set; }
public required string Status { get; set; }
public DateTime Date { get; set; }
}
public class StyledEntityProfile : IMappingProfile
{
public void Configure(IExcelConfiguration configuration)
{
configuration.HasAuthor("Spark")
.HasTitle("Styled Report")
.HasDescription("Professional styled Excel report");
configuration.HasSheetSetting(config =>
{
config.SheetName = "Report";
config.StartRowIndex = 1;
config.AutoColumnWidthEnabled = true;
// Style header row
config.RowAction = row =>
{
if (row.RowNum == 0)
{
var headerStyle = row.Sheet.Workbook.CreateCellStyle();
headerStyle.Alignment = HorizontalAlignment.Center;
headerStyle.VerticalAlignment = VerticalAlignment.Center;
headerStyle.FillForegroundColor = IndexedColors.Grey25Percent.Index;
headerStyle.FillPattern = FillPattern.SolidForeground;
var headerFont = row.Sheet.Workbook.CreateFont();
headerFont.FontName = "JetBrains Mono";
headerFont.IsBold = true;
headerFont.FontHeight = 240; // 12pt
headerStyle.SetFont(headerFont);
// Add borders
headerStyle.BorderBottom = BorderStyle.Thin;
headerStyle.BorderTop = BorderStyle.Thin;
headerStyle.BorderLeft = BorderStyle.Thin;
headerStyle.BorderRight = BorderStyle.Thin;
row.Cells.ForEach(c => c.CellStyle = headerStyle);
}
};
// Add validation and conditional formatting
config.CellAction = cell =>
{
// Add validation for status column
if (cell.RowIndex == 0 && cell.StringCellValue == "Status")
{
var validationHelper = cell.Sheet.GetDataValidationHelper();
var statusList = new[] { "Approved", "Pending", "Rejected" };
var constraint = validationHelper.CreateExplicitListConstraint(statusList);
var addressList = new CellRangeAddressList(1, 1000, cell.ColumnIndex, cell.ColumnIndex);
var validation = validationHelper.CreateValidation(constraint, addressList);
validation.ShowErrorBox = true;
cell.Sheet.AddValidationData(validation);
}
// Highlight negative amounts in red
if (cell.RowIndex > 0 && cell.ColumnIndex == 2) // Amount column
{
try
{
if (cell.NumericCellValue < 0)
{
var redStyle = cell.Sheet.Workbook.CreateCellStyle();
var redFont = cell.Sheet.Workbook.CreateFont();
redFont.Color = IndexedColors.Red.Index;
redFont.IsBold = true;
redStyle.SetFont(redFont);
cell.CellStyle = redStyle;
}
}
catch { } // Skip if not a numeric cell
}
};
});
// Configure properties
configuration.Property(x => x.Id).HasColumnIndex(0);
configuration.Property(x => x.Name).HasColumnIndex(1);
configuration.Property(x => x.Amount).HasColumnIndex(2);
configuration.Property(x => x.Status).HasColumnIndex(3);
configuration.Property(x => x.Date)
.HasColumnIndex(4)
.HasColumnFormatter("yyyy-MM-dd");
}
}
================================================
FILE: src/Directory.Build.props
================================================
true
$(NoWarn);1591
https://github.com/WeihanLi/WeihanLi.Common
true
true
true
snupkg
false
https://github.com/WeihanLi/WeihanLi.Common/blob/dev/docs/ReleaseNotes.md
icon.jpg
README.md
MIT
true
================================================
FILE: src/WeihanLi.Npoi/Abstract/ICell.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace WeihanLi.Npoi.Abstract;
internal interface ICell
{
CellType CellType { get; set; }
object? Value { get; set; }
}
internal enum CellType
{
Unknown = -1, // 0xFFFFFFFF
String = 0,
Numeric = 1,
Formula = 2,
Blank = 3,
Boolean = 4,
Error = 5
}
================================================
FILE: src/WeihanLi.Npoi/Abstract/IRow.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace WeihanLi.Npoi.Abstract;
internal interface IRow
{
///
/// Gets the number of defined cells (NOT number of cells in the actual row!).
/// That is to say if only columns 0,4,5 have values then there would be 3.
///
/// int representing the number of defined cells in the row.
int CellsCount { get; }
///
/// 1-based column number of the first cell
///
int FirstCellNum { get; }
///
/// 1-based column number of the last cell
///
int LastCellNum { get; }
///
/// UnderlyingValue
///
object? UnderlyingValue { get; }
ICell? GetCell(int cellIndex);
///
/// Create a cell
///
///
/// cellIndex
/// maxValue: (255 for *.xls, 1048576 for *.xlsx)
///
///
ICell CreateCell(int cellIndex);
}
================================================
FILE: src/WeihanLi.Npoi/Abstract/ISheet.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace WeihanLi.Npoi.Abstract;
internal interface ISheet
{
///
/// FirstRowNum, 1 based rowNum
/// 0 if no rows here
///
int FirstRowNum { get; }
///
/// lastRowIndex +1, 1 based rowNum
/// 0 if no rows here
///
int LastRowNum { get; }
IRow? GetRow(int rowIndex);
IRow CreateRow(int rowIndex);
void SetColumnWidth(int columnIndex, int width);
void AutoSizeColumn(int columnIndex);
void CreateFreezePane(int colSplit, int rowSplit, int leftMostCol, int topRow);
void SetAutoFilter(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex);
void ShiftRows(int startRow, int endRow, int n);
IRow CopyRow(int sourceIndex, int targetIndex);
void RemoveRow(IRow row);
}
================================================
FILE: src/WeihanLi.Npoi/Abstract/IWorkbook.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace WeihanLi.Npoi.Abstract;
internal interface IWorkbook
{
int SheetCount { get; }
ISheet? GetSheet(int sheetIndex);
ISheet CreateSheet(string sheetName);
byte[] ToBytes();
}
================================================
FILE: src/WeihanLi.Npoi/Abstract/NPOIWorkbook.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using NPOI.SS.Util;
using NModel = NPOI.SS.UserModel;
namespace WeihanLi.Npoi.Abstract;
///
/// Thin adapter that exposes the internal NPOI workbook via the abstraction interfaces.
///
internal sealed class NPOIWorkbook : IWorkbook
{
private readonly NModel.IWorkbook _workbook;
///
/// Creates a new adapter for the provided NPOI workbook.
///
/// Underlying workbook instance.
public NPOIWorkbook(NModel.IWorkbook workbook) => _workbook = workbook;
///
/// Gets the number of sheets available.
///
public int SheetCount => _workbook.NumberOfSheets;
///
/// Wraps the specified sheet index in an adapter.
///
public ISheet GetSheet(int sheetIndex) => new NPOISheet(_workbook.GetSheetAt(sheetIndex));
///
/// Creates a new sheet and returns the adapter around it.
///
public ISheet CreateSheet(string sheetName) => new NPOISheet(_workbook.CreateSheet(sheetName));
///
/// Serializes the workbook to bytes using helper extensions.
///
public byte[] ToBytes() => _workbook.ToExcelBytes();
}
///
/// Adapter for .
///
internal sealed class NPOISheet : ISheet
{
private readonly NModel.ISheet _sheet;
///
/// Initializes the adapter with the underlying sheet.
///
public NPOISheet(NModel.ISheet sheet) => _sheet = sheet;
///
/// Gets the first row index using one-based indexing to align with the abstractions.
///
public int FirstRowNum => _sheet.FirstRowNum + 1;
///
/// Gets the last row index using one-based indexing to align with the abstractions.
///
public int LastRowNum => _sheet.LastRowNum + 1;
///
/// Retrieves the requested row and wraps it, if present.
///
public IRow? GetRow(int rowIndex)
{
var nRow = _sheet.GetRow(rowIndex);
if (null == nRow)
{
return null;
}
return new NPOIRow(nRow);
}
///
/// Creates a new row and returns its adapter.
///
public IRow CreateRow(int rowIndex) => new NPOIRow(_sheet.CreateRow(rowIndex));
///
/// Sets the column width in the underlying sheet.
///
public void SetColumnWidth(int columnIndex, int width) => _sheet.SetColumnWidth(columnIndex, width);
///
/// Auto sizes the requested column.
///
public void AutoSizeColumn(int columnIndex) => _sheet.AutoSizeColumn(columnIndex);
///
/// Applies a freeze pane to the sheet.
///
public void CreateFreezePane(int colSplit, int rowSplit, int leftMostCol, int topRow) =>
_sheet.CreateFreezePane(colSplit, rowSplit, leftMostCol, topRow);
///
/// Applies an auto-filter range to the sheet.
///
public void SetAutoFilter(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex) =>
_sheet.SetAutoFilter(new CellRangeAddress(firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex));
///
/// Shifts the specified row range.
///
public void ShiftRows(int startRow, int endRow, int n) => _sheet.ShiftRows(startRow, endRow, n);
///
/// Copies a row and wraps the result.
///
public IRow CopyRow(int sourceIndex, int targetIndex) => new NPOIRow(_sheet.CopyRow(sourceIndex, targetIndex));
///
/// Removes the given row from the sheet.
///
public void RemoveRow(IRow row) => _sheet.RemoveRow(row.UnderlyingValue as NModel.IRow);
}
///
/// Adapter for .
///
internal sealed class NPOIRow : IRow
{
private readonly NModel.IRow _row;
///
/// Initializes the adapter with the underlying row.
///
public NPOIRow(NModel.IRow row) => _row = row;
///
/// Gets the number of physical cells.
///
public int CellsCount => _row.PhysicalNumberOfCells;
///
/// Gets the first cell index using one-based indexing.
///
public int FirstCellNum => _row.FirstCellNum + 1;
///
/// Gets the last cell index.
///
public int LastCellNum => _row.LastCellNum;
///
/// Retrieves and wraps the specified cell.
///
public ICell? GetCell(int cellIndex)
{
var nCell = _row.GetCell(cellIndex);
if (nCell is null)
{
return null;
}
return new NPOICell(nCell);
}
///
/// Creates and wraps a new cell.
///
public ICell CreateCell(int cellIndex) => new NPOICell(_row.CreateCell(cellIndex));
///
/// Provides direct access to the underlying NPOI object.
///
public object UnderlyingValue => _row;
}
///
/// Adapter for .
///
internal sealed class NPOICell : ICell
{
private readonly NModel.ICell _cell;
///
/// Initializes the adapter with the underlying cell.
///
public NPOICell(NModel.ICell cell) => _cell = cell;
///
/// Gets or sets the cell type using the abstraction enum.
///
public CellType CellType
{
get => (CellType)Enum.Parse(typeof(CellType), _cell.CellType.ToString());
set => _cell.SetCellType((NModel.CellType)Enum.Parse(typeof(NModel.CellType), value.ToString()));
}
///
/// Gets or sets the cell value while translating common NPOI types.
///
public object? Value
{
get
{
if (_cell.CellType == NModel.CellType.Blank || _cell.CellType == NModel.CellType.Error)
{
return null;
}
switch (_cell.CellType)
{
case NModel.CellType.Numeric:
if (NModel.DateUtil.IsCellDateFormatted(_cell))
{
return _cell.DateCellValue;
}
return _cell.NumericCellValue;
case NModel.CellType.String:
return _cell.StringCellValue;
case NModel.CellType.Boolean:
return _cell.BooleanCellValue;
default:
return _cell.ToString();
}
}
set => _cell.SetCellValue(value ?? string.Empty);
}
}
================================================
FILE: src/WeihanLi.Npoi/Attributes/ColumnAttribute.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Npoi.Configurations;
namespace WeihanLi.Npoi.Attributes;
///
/// Describes column-level metadata for a property.
///
[AttributeUsage(AttributeTargets.Property)]
public sealed class ColumnAttribute : Attribute
{
///
/// Initializes a column attribute with default configuration.
///
public ColumnAttribute() => PropertyConfiguration = new PropertyConfiguration();
///
/// Initializes a column attribute targeting the specified index.
///
/// Target column index.
public ColumnAttribute(int index) => PropertyConfiguration = new PropertyConfiguration { ColumnIndex = index };
///
/// Initializes a column attribute with the provided title.
///
/// Column header title.
public ColumnAttribute(string title) => PropertyConfiguration = new PropertyConfiguration
{
ColumnTitle = title ?? throw new ArgumentNullException(nameof(title))
};
internal PropertyConfiguration PropertyConfiguration { get; }
///
/// ColumnIndex
///
public int Index
{
get => PropertyConfiguration.ColumnIndex;
set
{
if (value >= 0)
{
PropertyConfiguration.ColumnIndex = value;
}
}
}
///
/// ColumnTitle
///
public string Title
{
get => PropertyConfiguration.ColumnTitle;
set => PropertyConfiguration.ColumnTitle = value;
}
///
/// Formatter
///
public string? Formatter
{
get => PropertyConfiguration.ColumnFormatter;
set => PropertyConfiguration.ColumnFormatter = value;
}
///
/// IsIgnored
///
public bool IsIgnored
{
get => PropertyConfiguration.IsIgnored;
set => PropertyConfiguration.IsIgnored = value;
}
///
/// ColumnWidth
/// Characters Count
///
public int Width
{
get => PropertyConfiguration.ColumnWidth;
set => PropertyConfiguration.ColumnWidth = value;
}
}
================================================
FILE: src/WeihanLi.Npoi/Attributes/FilterAttribute.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Npoi.Settings;
namespace WeihanLi.Npoi.Attributes;
///
/// Specifies the auto-filter range that should be applied to a sheet.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class FilterAttribute : Attribute
{
///
/// Initializes the attribute for a single column.
///
public FilterAttribute(int firstColumn) : this(firstColumn, null)
{
}
///
/// Initializes the attribute for an explicit column range.
///
/// First column index.
/// Last column index.
public FilterAttribute(int firstColumn, int? lastColumn) =>
FilterSetting = new FilterSetting(firstColumn, lastColumn);
internal FilterSetting FilterSetting { get; }
///
/// Gets or sets the first column index.
///
public int FirstColumn => FilterSetting.FirstColumn;
///
/// Gets or sets the last column index.
///
public int? LastColumn => FilterSetting.LastColumn;
}
================================================
FILE: src/WeihanLi.Npoi/Attributes/FreezeAttribute.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Npoi.Settings;
namespace WeihanLi.Npoi.Attributes;
///
/// Declares a freeze pane for a mapped sheet.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class FreezeAttribute : Attribute
{
///
/// Initializes a freeze pane using default anchors.
///
public FreezeAttribute(int colSplit, int rowSplit) : this(colSplit, rowSplit, 0, 1)
{
}
///
/// Initializes a freeze pane with explicit anchors.
///
/// Horizontal split position.
/// Vertical split position.
/// Left column visible in right pane.
/// Top row visible in bottom pane.
public FreezeAttribute(int colSplit, int rowSplit, int leftmostColumn, int topRow) =>
FreezeSetting = new FreezeSetting(colSplit, rowSplit, leftmostColumn, topRow);
internal FreezeSetting FreezeSetting { get; }
///
/// Horizontal position of split
///
public int ColSplit => FreezeSetting.ColSplit;
///
/// Vertical position of split
///
public int RowSplit => FreezeSetting.RowSplit;
///
/// Top row visible in bottom pane
///
public int LeftMostColumn => FreezeSetting.LeftMostColumn;
///
/// Left column visible in right pane
///
public int TopRow => FreezeSetting.TopRow;
}
================================================
FILE: src/WeihanLi.Npoi/Attributes/SheetAttribute.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Npoi.Settings;
namespace WeihanLi.Npoi.Attributes;
///
/// Declares per-sheet metadata for an entity mapping.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class SheetAttribute : Attribute
{
private int _endColumnIndex = -1;
private int _startColumnIndex;
///
/// Initializes an attribute backed by a fresh .
///
public SheetAttribute() => SheetSetting = new SheetSetting();
///
/// Target sheet index (zero-based).
///
public int SheetIndex { get; set; }
///
/// Gets or sets the sheet name override.
///
public string SheetName
{
get => SheetSetting.SheetName;
set => SheetSetting.SheetName = value ?? throw new ArgumentNullException(nameof(value));
}
///
/// Gets or sets the first row to start reading/writing (zero-based).
///
public int StartRowIndex
{
get => SheetSetting.StartRowIndex;
set => SheetSetting.StartRowIndex = value;
}
///
/// Gets the header row index.
///
public int HeaderRowIndex => SheetSetting.HeaderRowIndex;
///
/// Gets or sets the last row (inclusive) participating in the mapping.
///
public int EndRowIndex
{
get => SheetSetting.EndRowIndex ?? -1;
set => SheetSetting.EndRowIndex = value >= 0 ? value : -1;
}
///
/// StartColumnIndex
/// Start Column Index when import
///
public int StartColumnIndex
{
get => _startColumnIndex;
set
{
if (value >= 0)
{
_startColumnIndex = value;
if (_endColumnIndex >= value)
{
SheetSetting.CellFilter = cell =>
cell.ColumnIndex >= _startColumnIndex && cell.ColumnIndex <= _endColumnIndex
;
}
else
{
SheetSetting.CellFilter = cell => cell.ColumnIndex >= _startColumnIndex;
}
}
}
}
///
/// EndColumnIndex
/// End Column Index when import
///
public int EndColumnIndex
{
get => _endColumnIndex;
set
{
if (value >= _startColumnIndex)
{
_endColumnIndex = value;
SheetSetting.CellFilter = cell =>
cell.ColumnIndex >= _startColumnIndex && cell.ColumnIndex <= _endColumnIndex
;
}
else
{
SheetSetting.CellFilter = cell => cell.ColumnIndex >= _startColumnIndex;
_endColumnIndex = -1;
}
}
}
///
/// Gets or sets whether column widths should be auto-sized.
///
public bool AutoColumnWidthEnabled
{
get => SheetSetting.AutoColumnWidthEnabled;
set => SheetSetting.AutoColumnWidthEnabled = value;
}
internal SheetSetting SheetSetting { get; }
}
================================================
FILE: src/WeihanLi.Npoi/CellPosition.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
namespace WeihanLi.Npoi;
///
/// Represents a zero-based row/column coordinate within a sheet.
///
/// Row index.
/// Column index.
public readonly record struct CellPosition(int Row, int Column);
================================================
FILE: src/WeihanLi.Npoi/Compat.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
#if NETSTANDARD
// ReSharper disable once CheckNamespace
namespace System.Runtime.CompilerServices;
internal sealed class IsExternalInit;
#endif
================================================
FILE: src/WeihanLi.Npoi/ConfigurationExtensions.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using WeihanLi.Common.Services;
using WeihanLi.Npoi.Configurations;
namespace WeihanLi.Npoi;
///
/// Provides convenience extension methods for configuring Excel import/export metadata.
///
public static class ConfigurationExtensions
{
///
/// Sheet Configuration
///
/// excel configuration
/// sheetIndex
/// sheetName
/// current excel configuration
public static IExcelConfiguration HasSheetConfiguration(this IExcelConfiguration configuration, int sheetIndex,
string sheetName) => configuration.HasSheetSetting(config => { config.SheetName = sheetName; }, sheetIndex);
///
/// Sheet Configuration
///
/// excel configuration
/// sheetIndex
/// sheetName
/// enable auto column width if true otherwise false
/// current excel configuration
public static IExcelConfiguration HasSheetConfiguration(this IExcelConfiguration configuration, int sheetIndex,
string sheetName, bool enableAutoColumnWidth) => configuration.HasSheetSetting(config =>
{
config.SheetName = sheetName;
config.AutoColumnWidthEnabled = enableAutoColumnWidth;
}, sheetIndex);
///
/// Sheet Configuration
///
/// excel configuration
/// sheetIndex
/// sheetName
/// startRowIndex
/// current excel configuration
public static IExcelConfiguration HasSheetConfiguration(this IExcelConfiguration configuration, int sheetIndex,
string sheetName, int startRowIndex) => configuration.HasSheetSetting(config =>
{
config.SheetName = sheetName;
config.StartRowIndex = startRowIndex;
}, sheetIndex);
///
/// Sheet Configuration
///
/// excel configuration
/// sheetIndex
/// sheetName
/// startRowIndex
/// enable auto column width if true otherwise false
/// endRowIndex, set this if you wanna control where to end(included)
/// current excel configuration
public static IExcelConfiguration HasSheetConfiguration(this IExcelConfiguration configuration, int sheetIndex,
string sheetName, int startRowIndex,
bool enableAutoColumnWidth, int? endRowIndex = null) => configuration.HasSheetSetting(config =>
{
config.SheetName = sheetName;
config.StartRowIndex = startRowIndex;
config.AutoColumnWidthEnabled = enableAutoColumnWidth;
config.EndRowIndex = endRowIndex;
}, sheetIndex);
///
/// Configure excel author
///
/// excel configuration
/// excel document author name
/// current excel configuration
public static IExcelConfiguration HasAuthor(this IExcelConfiguration configuration, string author) =>
configuration.HasExcelSetting(setting => { setting.Author = author; });
///
/// Configure excel author
///
/// excel configuration
/// excel document title
/// current excel configuration
public static IExcelConfiguration HasTitle(this IExcelConfiguration configuration, string title) =>
configuration.HasExcelSetting(setting => { setting.Title = title; });
///
/// Configure excel author
///
/// excel configuration
/// excel document description
/// current excel configuration
public static IExcelConfiguration HasDescription(this IExcelConfiguration configuration, string description) =>
configuration.HasExcelSetting(setting => { setting.Description = description; });
///
/// Configure excel author
///
/// excel configuration
/// excel document subject
/// current excel configuration
public static IExcelConfiguration HasSubject(this IExcelConfiguration configuration, string subject) =>
configuration.HasExcelSetting(setting => { setting.Subject = subject; });
///
/// Configure excel author
///
/// excel configuration
/// excel document company
/// current excel configuration
public static IExcelConfiguration HasCompany(this IExcelConfiguration configuration, string company) =>
configuration.HasExcelSetting(setting => { setting.Company = company; });
///
/// Configure excel author
///
/// excel configuration
/// excel document category
/// current excel configuration
public static IExcelConfiguration HasCategory(this IExcelConfiguration configuration, string category) =>
configuration.HasExcelSetting(setting => { setting.Category = category; });
///
/// excel data validator
///
/// configuration
/// validator
/// entity type
/// current configuration
public static IExcelConfiguration WithValidator(this IExcelConfiguration configuration,
IValidator validator)
{
return configuration.WithValidator(validator.GetCommonValidator());
}
///
/// property configuration
///
/// TEntity
/// excelConfiguration
/// propertyName
/// PropertyConfiguration
public static IPropertyConfiguration Property(
this IExcelConfiguration excelConfiguration, string propertyName) =>
excelConfiguration.Property(propertyName);
///
/// has column output formatter
///
/// entity type
/// property type
/// property configuration
/// column output formatter
/// property configuration
public static IPropertyConfiguration HasColumnOutputFormatter(
this IPropertyConfiguration configuration, Func? formatter)
{
if (formatter is null)
{
return configuration.HasOutputFormatter(null);
}
return configuration.HasOutputFormatter((_, prop) => formatter.Invoke(prop));
}
}
================================================
FILE: src/WeihanLi.Npoi/Configurations/CsvOptions.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using System.Text;
namespace WeihanLi.Npoi.Configurations;
///
/// Represents the configurable behaviors of the CSV helper.
///
public sealed class CsvOptions
{
///
/// Gets the separator character expressed as a string.
///
public string SeparatorString => new(SeparatorCharacter, 1);
///
/// Gets the quote character expressed as a string.
///
public string QuoteString => new(QuoteCharacter, 1);
///
/// Gets or sets the separator used between values.
///
public char SeparatorCharacter { get; set; }
///
/// Gets or sets the character used to wrap textual values.
///
public char QuoteCharacter { get; set; }
///
/// Gets or sets whether the header row should be emitted.
///
public bool IncludeHeader { get; set; }
///
/// Gets or sets the synthetic property name to use for basic types.
///
public string PropertyNameForBasicType { get; set; }
///
/// Gets or sets the encoding of the generated CSV.
///
public Encoding Encoding { get; set; }
///
/// Initializes options with default separator, quote, and encoding.
///
public CsvOptions()
{
SeparatorCharacter = CsvHelper.CsvSeparatorCharacter;
QuoteCharacter = CsvHelper.CsvQuoteCharacter;
IncludeHeader = true;
PropertyNameForBasicType = InternalConstants.DefaultPropertyNameForBasicType;
Encoding = Encoding.UTF8;
}
///
/// Provides a shared instance representing sensible defaults.
///
public static readonly CsvOptions Default = new()
{
SeparatorCharacter = ',',
QuoteCharacter = '"',
PropertyNameForBasicType = InternalConstants.DefaultPropertyNameForBasicType
};
}
================================================
FILE: src/WeihanLi.Npoi/Configurations/ExcelConfiguration.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using System.Linq.Expressions;
using System.Reflection;
using WeihanLi.Common;
using WeihanLi.Common.Services;
using WeihanLi.Extensions;
using WeihanLi.Npoi.Settings;
namespace WeihanLi.Npoi.Configurations;
internal abstract class ExcelConfiguration : IExcelConfiguration
{
///
/// PropertyConfigurationDictionary
///
public IDictionary PropertyConfigurationDictionary { get; } =
new Dictionary();
///
/// Gets the Excel-level document metadata.
///
public ExcelSetting ExcelSetting { get; } = ExcelHelper.DefaultExcelSetting;
///
/// Gets the configured freeze panes for the workbook.
///
public IList FreezeSettings { get; } = new List();
///
/// Gets or sets the filter configuration for the sheet.
///
public FilterSetting? FilterSetting { get; set; }
///
/// Gets the registered sheet settings keyed by sheet index.
///
public IDictionary SheetSettings { get; } =
new Dictionary { { 0, new SheetSetting() } };
#region ExcelSettings FluentAPI
///
/// Updates the Excel document metadata in a fluent manner.
///
/// Configuration delegate.
/// The current configuration instance.
public IExcelConfiguration HasExcelSetting(Action configAction)
{
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
// allow nullable but we do not want a null
configAction?.Invoke(ExcelSetting);
return this;
}
#endregion ExcelSettings FluentAPI
#region Sheet
///
/// Updates the sheet configuration for the specified index.
///
/// Configuration delegate.
/// Target sheet index.
/// The current configuration instance.
public IExcelConfiguration HasSheetSetting(Action configAction, int sheetIndex = 0)
{
if (configAction is null)
{
throw new ArgumentNullException(nameof(configAction));
}
if (sheetIndex >= 0)
{
if (!SheetSettings.TryGetValue(sheetIndex, out var sheetSetting))
{
SheetSettings[sheetIndex]
= sheetSetting
= new SheetSetting();
}
configAction.Invoke(sheetSetting);
}
return this;
}
#endregion Sheet
#region FreezePane
///
/// Adds a freeze pane using default anchor values.
///
public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit)
{
FreezeSettings.Add(new FreezeSetting(colSplit, rowSplit));
return this;
}
///
/// Adds a freeze pane with the specified anchor.
///
public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow)
{
FreezeSettings.Add(new FreezeSetting(colSplit, rowSplit, leftmostColumn, topRow));
return this;
}
#endregion FreezePane
#region Filter
///
/// Adds an auto-filter that starts at the specified column.
///
public IExcelConfiguration HasFilter(int firstColumn) => HasFilter(firstColumn, null);
///
/// Adds an auto-filter covering the specified column range.
///
public IExcelConfiguration HasFilter(int firstColumn, int? lastColumn)
{
FilterSetting = new FilterSetting(firstColumn, lastColumn);
return this;
}
#endregion Filter
}
internal sealed class ExcelConfiguration : ExcelConfiguration, IExcelConfiguration
{
///
/// Gets the entity type represented by this configuration.
///
public Type EntityType => typeof(TEntity);
internal Func? DataFilter { get; private set; }
internal Action? PostImportAction { get; private set; }
internal IComparer? PropertyComparer { get; private set; }
internal IValidator? Validator { get; private set; }
#region Property
///
/// Assigns a custom validator.
///
public IExcelConfiguration WithValidator(IValidator? validator)
{
Validator = validator;
return this;
}
///
/// Applies a data filter that can skip entities during export.
///
public IExcelConfiguration WithDataFilter(Func? dataFilter)
{
DataFilter = dataFilter;
return this;
}
public IExcelConfiguration WithPostImportAction(Action? postAction)
{
PostImportAction = postAction;
return this;
}
///
/// Controls the ordering of properties.
///
public IExcelConfiguration WithPropertyComparer(IComparer? propertyComparer)
{
PropertyComparer = propertyComparer;
return this;
}
///
/// Gets the property configuration by the specified property expression for the specified
/// and its .
///
/// The .
/// The property expression.
/// The type of parameter.
public IPropertyConfiguration Property(
Expression> propertyExpression)
{
var memberInfo = propertyExpression.GetMemberInfo();
if (memberInfo is PropertyInfo property &&
PropertyConfigurationDictionary.TryGetValue(property, out var propertyConfiguration))
return (IPropertyConfiguration)propertyConfiguration;
property = CacheUtil.GetTypeProperties(EntityType).FirstOrDefault(p => p.Name == memberInfo.Name)
?? throw new InvalidOperationException($"the property [{memberInfo.Name}] does not exists");
return (IPropertyConfiguration)PropertyConfigurationDictionary[property];
}
///
/// Retrieves (or builds) a configuration for the specified property name.
///
/// Property type.
/// Property name.
/// Property configuration.
public IPropertyConfiguration Property(string propertyName)
{
var property = PropertyConfigurationDictionary.Keys.FirstOrDefault(p => p.Name == propertyName);
if (property is not null)
{
return (IPropertyConfiguration)PropertyConfigurationDictionary[property];
}
var propertyType = typeof(TProperty);
property = new FakePropertyInfo(EntityType, propertyType, propertyName);
var propertyConfigurationType =
typeof(PropertyConfiguration<,>).MakeGenericType(EntityType, propertyType);
var propertyConfiguration =
(PropertyConfiguration)Guard.NotNull(Activator.CreateInstance(propertyConfigurationType, property));
PropertyConfigurationDictionary[property] = propertyConfiguration;
return (IPropertyConfiguration)propertyConfiguration;
}
#endregion Property
}
================================================
FILE: src/WeihanLi.Npoi/Configurations/IExcelConfiguration.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using System.Linq.Expressions;
using System.Reflection;
using WeihanLi.Common.Services;
using WeihanLi.Npoi.Settings;
namespace WeihanLi.Npoi.Configurations;
///
/// Abstraction describing the fluent configuration surface exposed to consumers.
///
public interface IExcelConfiguration
{
///
/// Sheet Configuration
///
/// sheet config delegate
/// sheetIndex, 0 is the default value
/// current excel configuration
IExcelConfiguration HasSheetSetting(Action configAction, int sheetIndex = 0);
///
/// excel setting configure
///
/// config delegate
/// current excel configuration
IExcelConfiguration HasExcelSetting(Action configAction);
///
/// setting freeze pane
/// Creates a split (freeze pane). Any existing freeze pane or split pane is overwritten.
///
/// Horizontal position of split
/// Vertical position of split
/// current excel configuration
IExcelConfiguration HasFreezePane(int colSplit, int rowSplit);
///
/// setting freeze pane
/// Creates a split (freeze pane). Any existing freeze pane or split pane is overwritten.
///
/// Horizontal position of split
/// Vertical position of split
/// Top row visible in bottom pane
/// Left column visible in right pane
/// current excel configuration
IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow);
///
/// setting filter
///
/// firstCol Index of first column
/// current excel configuration
IExcelConfiguration HasFilter(int firstColumn);
///
/// setting filter
///
/// firstCol Index of first column
/// lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}
/// current excel configuration
IExcelConfiguration HasFilter(int firstColumn, int? lastColumn);
}
///
/// Strongly typed configuration contract for a specific entity.
///
/// Entity type.
public interface IExcelConfiguration : IExcelConfiguration
{
///
/// register validator for excel import
///
/// validator
/// current excel configuration
IExcelConfiguration WithValidator(IValidator? validator);
///
/// register data filter
///
/// data filter logic
/// current excel configuration
IExcelConfiguration WithDataFilter(Func? dataFilter);
///
/// register post action for T and rowIndex based func
///
/// postAction
///
IExcelConfiguration WithPostImportAction(Action? postAction);
///
/// register property comparer
///
/// propertyComparer
/// current excel configuration
IExcelConfiguration WithPropertyComparer(IComparer? propertyComparer);
///
/// property configuration
///
/// PropertyType
/// propertyExpression to get property info
/// current property configuration
IPropertyConfiguration Property(
Expression> propertyExpression);
///
/// property configuration
///
/// PropertyType
/// propertyName
/// current property configuration
IPropertyConfiguration Property(string propertyName);
}
================================================
FILE: src/WeihanLi.Npoi/Configurations/IPropertyConfiguration.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using NPOI.SS.UserModel;
namespace WeihanLi.Npoi.Configurations;
///
/// PropertyConfiguration
///
public interface IPropertyConfiguration;
///
/// Describes the fluent property-level configuration API for an entity.
///
/// Entity type.
/// Property type.
public interface IPropertyConfiguration : IPropertyConfiguration
{
///
/// HasColumnIndex
///
/// index
///
IPropertyConfiguration HasColumnIndex(int index);
///
/// HasColumnWidth
///
/// width
///
IPropertyConfiguration HasColumnWidth(int width);
///
/// HasColumnTitle
///
/// title
///
IPropertyConfiguration HasColumnTitle(string title);
///
/// HasColumnFormatter
///
/// formatter
///
IPropertyConfiguration HasColumnFormatter(string? formatter);
///
/// Ignored
///
///
IPropertyConfiguration Ignored(bool ignored = true);
///
/// HasCellReader(For excel only)
///
/// custom cell value reader
///
IPropertyConfiguration HasCellReader(
Func? cellReader);
///
/// HasColumnInputFormatter
///
/// formatterFunc
///
IPropertyConfiguration HasColumnInputFormatter(Func? formatterFunc);
///
/// HasOutputFormatter
///
/// columnFormatter
///
IPropertyConfiguration HasOutputFormatter(
Func? formatterFunc);
///
/// HasInputFormatter
///
/// columnFormatter
///
IPropertyConfiguration HasInputFormatter(
Func? formatterFunc);
}
================================================
FILE: src/WeihanLi.Npoi/Configurations/PropertyConfiguration.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using NPOI.SS.UserModel;
using System.Reflection;
using WeihanLi.Extensions;
namespace WeihanLi.Npoi.Configurations;
internal class PropertyConfiguration : IPropertyConfiguration
{
///
/// ColumnIndex
///
public int ColumnIndex { get; set; } = -1;
///
/// ColumnWidth
///
public int ColumnWidth { get; set; }
///
/// Title
///
public string ColumnTitle { get; set; } = string.Empty;
///
/// Formatter
///
public string? ColumnFormatter { get; set; }
///
/// the property is ignored.
///
public bool IsIgnored { get; set; }
///
/// PropertyName
///
public string? PropertyName { get; set; }
}
internal sealed class PropertyConfiguration : PropertyConfiguration,
IPropertyConfiguration
{
private readonly PropertyInfo _propertyInfo;
///
/// Initializes a configuration wrapper for the specified property.
///
/// Property metadata.
public PropertyConfiguration(PropertyInfo propertyInfo)
{
_propertyInfo = propertyInfo;
PropertyName = propertyInfo.Name;
ColumnTitle = propertyInfo.Name;
}
///
/// Sets the column index explicitly.
///
public IPropertyConfiguration HasColumnIndex(int index)
{
if (index >= 0)
{
ColumnIndex = index;
}
return this;
}
///
/// Assigns the header text used for the column.
///
public IPropertyConfiguration HasColumnTitle(string title)
{
ColumnTitle = title ?? throw new ArgumentNullException(nameof(title));
return this;
}
///
/// Sets the column width (characters).
///
public IPropertyConfiguration HasColumnWidth(int width)
{
ColumnWidth = width;
return this;
}
///
/// Assigns the formatter string used when writing out the column.
///
public IPropertyConfiguration HasColumnFormatter(string? formatter)
{
ColumnFormatter = formatter;
return this;
}
///
/// Marks the property as ignored when exporting/importing.
///
public IPropertyConfiguration Ignored(bool ignored = true)
{
IsIgnored = ignored;
return this;
}
///
/// Registers a custom cell reader for imports.
///
public IPropertyConfiguration HasCellReader(Func? cellReader)
{
InternalCache.CellReaderFuncCache.AddOrUpdate(_propertyInfo, cellReader);
return this;
}
///
/// Registers a formatter used when exporting the property.
///
public IPropertyConfiguration HasOutputFormatter(
Func? formatterFunc)
{
InternalCache.OutputFormatterFuncCache.AddOrUpdate(_propertyInfo, formatterFunc);
return this;
}
///
/// Registers a formatter used when importing cell values.
///
public IPropertyConfiguration HasInputFormatter(
Func? formatterFunc)
{
InternalCache.InputFormatterFuncCache.AddOrUpdate(_propertyInfo, formatterFunc);
return this;
}
///
/// Registers a formatter that manipulates the raw column text before parsing.
///
public IPropertyConfiguration HasColumnInputFormatter(
Func? formatterFunc)
{
InternalCache.ColumnInputFormatterFuncCache.AddOrUpdate(_propertyInfo, formatterFunc);
return this;
}
}
================================================
FILE: src/WeihanLi.Npoi/CsvHelper.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.
using System.Data;
using System.Diagnostics;
using System.Text;
using WeihanLi.Common;
using WeihanLi.Common.Helpers;
using WeihanLi.Extensions;
using WeihanLi.Npoi.Configurations;
namespace WeihanLi.Npoi;
///
/// CsvHelper provides utilities for reading and writing CSV files,
/// supporting conversion between CSV data and DataTables or strongly-typed entities.
///
public static class CsvHelper
{
///
/// CSV separator character, ',' by default.
/// Can be changed to support different CSV formats (e.g., ';' for European format).
///
public static char CsvSeparatorCharacter = ',';
///
/// CSV quote character used to escape values containing special characters, " by default.
/// Values containing the separator character will be wrapped with this quote character.
///
public static char CsvQuoteCharacter = '"';
///
/// Saves a DataTable to a CSV file with default options (includes header).
///
/// The DataTable to export
/// The destination file path
/// True if the file was successfully created; otherwise, false
public static bool ToCsvFile(this DataTable dt, string filePath) => ToCsvFile(dt, filePath, CsvOptions.Default);
///
/// Saves a DataTable to a CSV file with optional header.
///
/// The DataTable to export
/// The destination file path
/// Whether to include column headers in the output
/// True if the file was successfully created; otherwise, false
public static bool ToCsvFile(this DataTable dataTable, string filePath, bool includeHeader)
{
return ToCsvFile(dataTable, filePath, includeHeader ? CsvOptions.Default : new CsvOptions()
{
IncludeHeader = false
});
}
///
/// Saves a DataTable to a CSV file with custom CSV options.
///
/// The DataTable to export
/// The destination file path
/// Custom CSV formatting options (encoding, separator, quote character, etc.)
/// True if the file was successfully created; otherwise, false
public static bool ToCsvFile(this DataTable dataTable, string filePath, CsvOptions csvOptions)
{
if (dataTable is null)
{
throw new ArgumentNullException(nameof(dataTable));
}
var csvText = GetCsvText(dataTable, csvOptions);
if (csvText.IsNullOrEmpty())
{
return false;
}
InternalHelper.EnsureFileIsNotReadOnly(filePath);
var dir = Path.GetDirectoryName(filePath);
if (dir.IsNotNullOrEmpty())
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
File.WriteAllText(filePath, csvText, csvOptions.Encoding);
return true;
}
///
/// Converts a DataTable to CSV formatted byte array with default encoding (includes header).
///
/// The DataTable to convert
/// CSV data as a byte array
public static byte[] ToCsvBytes(this DataTable dt) => ToCsvBytes(dt, true);
///
/// Converts a DataTable to CSV formatted byte array with optional header.
///
/// The DataTable to convert
/// Whether to include column headers in the output
/// CSV data as a byte array
public static byte[] ToCsvBytes(this DataTable dataTable, bool includeHeader) =>
GetCsvText(dataTable, includeHeader).GetBytes();
///
/// Converts a DataTable to CSV formatted byte array with custom options.
///
/// The DataTable to convert
/// Custom CSV formatting options
/// CSV data as a byte array
public static byte[] ToCsvBytes(this DataTable dataTable, CsvOptions csvOptions) =>
GetCsvText(dataTable, csvOptions).GetBytes();
///
/// Converts CSV byte data to a DataTable with default options.
///
/// CSV data as byte array
/// A DataTable populated with CSV data
public static DataTable ToDataTable(byte[] csvBytes)
=> ToDataTable(csvBytes, CsvOptions.Default);
///
/// Converts CSV byte data to a DataTable with custom CSV options.
///
/// CSV data as byte array
/// Custom CSV parsing options (encoding, separator, etc.)
/// A DataTable populated with CSV data
public static DataTable ToDataTable(byte[] csvBytes, CsvOptions csvOptions)
{
if (csvBytes is null)
{
throw new ArgumentNullException(nameof(csvBytes));
}
using var ms = new MemoryStream(csvBytes);
return ToDataTable(ms, csvOptions);
}
///
/// Converts CSV stream data to a DataTable with default options.
///
/// Stream containing CSV data
/// A DataTable populated with CSV data
public static DataTable ToDataTable(Stream stream) => ToDataTable(stream, CsvOptions.Default);
///
/// Converts CSV stream data to a DataTable with custom CSV options.
/// The first row is treated as column headers.
///
/// Stream containing CSV data
/// Custom CSV parsing options
/// A DataTable populated with CSV data
public static DataTable ToDataTable(Stream stream, CsvOptions csvOptions)
{
Guard.NotNull(stream);
Guard.NotNull(csvOptions);
var dt = new DataTable();
if (stream.CanRead)
{
using var sr = new StreamReader(stream, csvOptions.Encoding);
string strLine;
var isFirst = true;
while ((strLine = sr.ReadLine()!).IsNotNullOrEmpty())
{
var rowData = ParseLine(strLine, csvOptions);
var dtColumns = rowData.Count;
if (isFirst)
{
for (var i = 0; i < dtColumns; i++)
{
var columnName = rowData[i];
if (dt.Columns.Contains(columnName))
{
columnName = InternalHelper.GetEncodedColumnName(columnName);
}
dt.Columns.Add(columnName);
}
isFirst = false;
}
else
{
var dataRow = dt.NewRow();
for (var j = 0; j < dt.Columns.Count; j++)
{
dataRow[j] = rowData[j];
}
dt.Rows.Add(dataRow);
}
}
}
return dt;
}
///
/// Converts CSV file data to a DataTable with default options.
///
/// Path to the CSV file
/// A DataTable populated with CSV data
/// Thrown when filePath is null
/// Thrown when the file does not exist
public static DataTable ToDataTable(string filePath)
{
if (filePath is null)
{
throw new ArgumentNullException(nameof(filePath));
}
if (!File.Exists(filePath))
{
throw new ArgumentException(Resource.FileNotFound, nameof(filePath));
}
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return ToDataTable(fs);
}
///
/// Converts CSV file data to a strongly-typed entity list with default options.
///
/// The entity type to map CSV data to
/// Path to the CSV file
/// A list of entities populated from CSV data
public static List ToEntityList(string filePath)
=> ToEntityList(filePath, CsvOptions.Default);
///
/// Converts CSV file data to a strongly-typed entity list with custom options.
///
/// The entity type to map CSV data to
/// Path to the CSV file
/// Custom CSV parsing options
/// A list of entities populated from CSV data
/// Thrown when the file does not exist
public static List ToEntityList(string filePath, CsvOptions csvOptions)
{
Guard.NotNull(filePath);
if (!File.Exists(filePath))
{
throw new ArgumentException(Resource.FileNotFound, nameof(filePath));
}
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return ToEntityList(fs, csvOptions);
}
///
/// Converts CSV file data to a lazy-loaded sequence of strongly-typed entities.
/// Use this method for large files to avoid loading all data into memory at once.
///
/// The entity type to map CSV data to
/// Path to the CSV file
/// Optional custom CSV parsing options
/// A lazy-loaded enumerable of entities
/// Thrown when the file does not exist
public static IEnumerable ToEntities(string filePath, CsvOptions? csvOptions = null)
{
Guard.NotNull(filePath);
if (!File.Exists(filePath))
{
throw new ArgumentException(Resource.FileNotFound, nameof(filePath));
}
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// https://stackoverflow.com/questions/1539114/yield-return-statement-inside-a-using-block-disposes-before-executing
foreach (var entity in ToEntities(fs, csvOptions))
{
yield return entity;
}
}
///
/// Converts CSV byte data to a strongly-typed entity list with default options.
///
/// The entity type to map CSV data to
/// CSV data as byte array
/// A list of entities populated from CSV data
public static List ToEntityList(byte[] csvBytes)
=> ToEntityList(csvBytes, CsvOptions.Default);
///
/// Converts CSV byte data to a strongly-typed entity list with custom options.
///
/// The entity type to map CSV data to
/// CSV data as byte array
/// Custom CSV parsing options
/// A list of entities populated from CSV data
public static List ToEntityList(byte[] csvBytes, CsvOptions csvOptions)
{
Guard.NotNull(csvBytes);
using var ms = new MemoryStream(csvBytes);
return ToEntityList(ms, csvOptions);
}
///
/// Converts CSV byte data to a lazy-loaded sequence of strongly-typed entities.
///
/// The entity type to map CSV data to
/// CSV data as byte array
/// Optional custom CSV parsing options
/// A lazy-loaded enumerable of entities
public static IEnumerable ToEntities(byte[] csvBytes, CsvOptions? csvOptions = null)
{
Guard.NotNull(csvBytes);
using var ms = new MemoryStream(csvBytes);
foreach (var entity in ToEntities(ms, csvOptions))
{
yield return entity;
}
}
///
/// Converts CSV stream data to a strongly-typed entity list with default options.
///
/// The entity type to map CSV data to
/// Stream containing CSV data
/// A list of entities populated from CSV data
public static List ToEntityList(Stream csvStream)
=> ToEntityList(csvStream, CsvOptions.Default);
///