Full Code of WeihanLi/WeihanLi.Npoi for AI

dev d65c688ac36e cached
132 files
531.0 KB
139.5k tokens
477 symbols
1 requests
Download .txt
Showing preview only (575K chars total). Download the full file or copy to clipboard to get everything.
Repository: WeihanLi/WeihanLi.Npoi
Branch: dev
Commit: d65c688ac36e
Files: 132
Total size: 531.0 KB

Directory structure:
gitextract_te4pkn3w/

├── .codacy.yml
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── stale.yml
│   └── workflows/
│       ├── docfx.yml
│       ├── dotnet-format-pr-validation.yml
│       ├── dotnet-format.yml
│       ├── dotnet.yml
│       └── release.yml
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE
├── README.md
├── WeihanLi.Npoi.sln.DotSettings
├── WeihanLi.Npoi.slnx
├── azure-pipelines.yml
├── build/
│   ├── common.props
│   ├── getReleaseVersion.ps1
│   ├── sign.props
│   ├── version.props
│   └── weihanli.snk
├── build.cs
├── docs/
│   ├── ReleaseNotes.md
│   ├── api/
│   │   ├── .gitignore
│   │   └── index.md
│   ├── articles/
│   │   ├── en/
│   │   │   ├── CustomizeStyle.md
│   │   │   ├── GetStarted.md
│   │   │   ├── InputOutputFormatter.md
│   │   │   ├── MultiSheets.md
│   │   │   ├── ShadowProperty.md
│   │   │   └── TemplateExport.md
│   │   ├── intro.md
│   │   ├── toc.yml
│   │   └── zh/
│   │       ├── CustomizeStyle.md
│   │       ├── GetStarted.md
│   │       ├── InputOutputFormatter.md
│   │       ├── MultiSheets.md
│   │       ├── ShadowProperty.md
│   │       └── TemplateExport.md
│   ├── docfx.json
│   └── toc.yml
├── global.json
├── nuget.config
├── perf/
│   └── WeihanLi.Npoi.Benchmark/
│       ├── BenchmarkDotNet.Artifacts/
│       │   └── results/
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report.csv
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report.html
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report.csv
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report.html
│       │       ├── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.csv
│       │       └── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.html
│       ├── ExportExcelTest.cs
│       ├── ImportExcelTest.cs
│       ├── Program.cs
│       ├── WeihanLi.Npoi.Benchmark.csproj
│       └── WorkbookBasicTest.cs
├── samples/
│   ├── Directory.Build.props
│   ├── DotNetCoreSample/
│   │   ├── DotNetCoreSample.csproj
│   │   ├── ImportImageTestModel.cs
│   │   ├── IssueSamples.cs
│   │   ├── ProductPriceMapping.cs
│   │   ├── Program.cs
│   │   ├── Templates/
│   │   │   └── testTemplate.xlsx
│   │   └── TestModel.cs
│   └── run-file-samples/
│       ├── issue-169.cs
│       └── style-customization-sample.cs
├── src/
│   ├── Directory.Build.props
│   └── WeihanLi.Npoi/
│       ├── Abstract/
│       │   ├── ICell.cs
│       │   ├── IRow.cs
│       │   ├── ISheet.cs
│       │   ├── IWorkbook.cs
│       │   └── NPOIWorkbook.cs
│       ├── Attributes/
│       │   ├── ColumnAttribute.cs
│       │   ├── FilterAttribute.cs
│       │   ├── FreezeAttribute.cs
│       │   └── SheetAttribute.cs
│       ├── CellPosition.cs
│       ├── Compat.cs
│       ├── ConfigurationExtensions.cs
│       ├── Configurations/
│       │   ├── CsvOptions.cs
│       │   ├── ExcelConfiguration.cs
│       │   ├── IExcelConfiguration.cs
│       │   ├── IPropertyConfiguration.cs
│       │   └── PropertyConfiguration.cs
│       ├── CsvHelper.cs
│       ├── ExcelFormat.cs
│       ├── ExcelHelper.cs
│       ├── FakePropertyInfo.cs
│       ├── FluentSettings.cs
│       ├── IMappingProfile.cs
│       ├── InternalCache.cs
│       ├── InternalConstants.cs
│       ├── InternalExtensions.cs
│       ├── InternalHelper.cs
│       ├── NpoiCollection.cs
│       ├── NpoiExtensions.cs
│       ├── NpoiHelper.cs
│       ├── NpoiTemplateHelper.cs
│       ├── Resource.Designer.cs
│       ├── Resource.resx
│       ├── Settings/
│       │   ├── ExcelSetting.cs
│       │   ├── FilterSetting.cs
│       │   ├── FreezeSetting.cs
│       │   └── SheetSetting.cs
│       ├── TemplateHelper.cs
│       └── WeihanLi.Npoi.csproj
└── test/
    └── WeihanLi.Npoi.Test/
        ├── CsvTest.cs
        ├── ExcelFormatData.cs
        ├── ExcelTest.cs
        ├── Extensions.cs
        ├── MappingProfiles/
        │   └── NoticeProfile.cs
        ├── Models/
        │   ├── Job.cs
        │   ├── Notice.cs
        │   └── OrderTestModels.cs
        ├── Startup.cs
        ├── TestData/
        │   ├── EmptyColumns/
        │   │   ├── emptyColumns.csv
        │   │   ├── emptyColumns.xls
        │   │   └── emptyColumns.xlsx
        │   ├── EmptyRows/
        │   │   ├── emptyRows.xls
        │   │   └── emptyRows.xlsx
        │   └── NonStringColumns/
        │       ├── nonStringColumns.csv
        │       ├── nonStringColumns.xls
        │       └── nonStringColumns.xlsx
        └── WeihanLi.Npoi.Test.csproj

================================================
FILE CONTENTS
================================================

================================================
FILE: .codacy.yml
================================================
exclude_paths:
  - samples/
  - test/

================================================
FILE: .devcontainer/Dockerfile
================================================
FROM mcr.microsoft.com/dotnet/sdk:10.0
RUN apt-get update \ 
    && apt-get install -y libgdiplus libc6-dev \ 
    && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll


================================================
FILE: .devcontainer/devcontainer.json
================================================
{
    "name": "CodeSpace",
    "dockerFile": "Dockerfile",
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-dotnettools.csharp",
                "davidanson.vscode-markdownlint"
            ]
        }
    }
}

================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome:http://EditorConfig.org

# top-most EditorConfig file
root = true

# Don't use tabs for indentation.
[*]
indent_style = space
# (Please don't specify an indent_size here; that has too many unintended consequences.)

# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom

# Xml project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2

# Xml config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2

# JSON files
[*.json]
indent_size = 2

# Dotnet code style settings:
[*.{cs,vb}]
# File header
file_header_template = Copyright (c) Weihan Li. All rights reserved.\nLicensed under the Apache license.

# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion

# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion

# CSharp code style settings:
[*.cs]
# namespace style
csharp_style_namespace_declarations=file_scoped:warning

# Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion

# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none

# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none

# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion

# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true

# Fix formatting, https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#rule-id-ide0055-fix-formatting
dotnet_diagnostic.IDE00055.severity = warning
# Remove unnecessary usings, https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
dotnet_diagnostic.IDE0005.severity = warning
# File header template
dotnet_diagnostic.IDE0073.severity = warning


================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

*.sh text eol=lf
*.ps1 text eol=crlf

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**

A clear and concise description of what the bug is.

**To Reproduce**

Steps to reproduce the behavior:
1. ...
2. ....
3. ....

**Expected behavior**

A clear and concise description of what you expected to happen.

**Screenshots**

If applicable, add screenshots to help explain your problem.

**Runtime Version**

- dotnet version: 
- `WeihanLi.Npoi` version:

**Additional context**

Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
  - pinned
  - security
# Label to use when marking an issue as stale
staleLabel: inactive
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
  This issue has been automatically marked as stale because it has not had
  recent activity. It will be closed if no further activity occurs. Thank you
  for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false


================================================
FILE: .github/workflows/docfx.yml
================================================
name: docfx
on:
  push:
    branches:
      - "main"
      - "master"
      - "dev"

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  actions: read
  pages: write
  id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in progress and the latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  build:
    name: "publish docs"
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      # Check out the branch that triggered this workflow to the 'source' subdirectory
      - name: Checkout Code
        uses: actions/checkout@v6
      - name: Setup .NET SDK
        uses: WeihanLi/dotnet-install@v0.2.0
        with:
          version: |
            10.0.x
      - name: install dotnet tools
        run: |
          dotnet tool install -g dotnet-execute
          dotnet tool install -g docfx
      # Run a build
      - name: Build docs
        run: |
          dotnet-exec info
          dotnet build
          cp ./README.md ./docs/index.md
          docfx ./docs/docfx.json
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: 'docs/_site'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
      - name: cloudflare-pages
        uses: cloudflare/wrangler-action@v3
        with:
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: pages deploy docs/_site --project-name=weihanli-npoi


================================================
FILE: .github/workflows/dotnet-format-pr-validation.yml
================================================
name: dotnet-format-validation

on: [pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
            10.0.x
    - name: build
      run: dotnet build
    - name: check format
      run: dotnet format --verify-no-changes


================================================
FILE: .github/workflows/dotnet-format.yml
================================================
name: dotnet-format

on:
  push:
    branches: [ dev ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
          10.0.x
    - name: build
      run: dotnet build
    - name: format
      run: dotnet format
    - name: check for changes
      run: |
        if git diff --exit-code; then
          echo "has_changes=false" >> $GITHUB_ENV
        else
          echo "has_changes=true" >> $GITHUB_ENV
        fi
    - name: Commit and Push
      if: ${{ env.has_changes == 'true' }}
      shell: bash
      run: |
        git config --local user.name "github-actions[bot]"
        git config --local user.email "weihanli@outlook.com"
        git add -u
        git commit -m "Automated dotnet-format update from commit ${GITHUB_SHA} on ${GITHUB_REF}"
        git log -1
        remote_repo="https://${GITHUB_ACTOR}:${{secrets.GITHUB_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git"
        git push "${remote_repo}" HEAD:${GITHUB_REF}


================================================
FILE: .github/workflows/dotnet.yml
================================================
name: default

on: [push, pull_request]

jobs:
  mac-build:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
            10.0.x
    - name: dotnet info
      run: |
        dotnet tool install -g dotnet-execute
        dotnet-exec info
    - name: build
      run: dotnet build.cs --target=test

  linux-build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
            10.0.x
    - name: dotnet info
      run: |
        dotnet tool install -g dotnet-execute
        dotnet-exec info
    # - name: font configure
    #   run: |
    #      sudo apt update && sudo apt-get install -y ttf-mscorefonts-installer fontconfig fonts-lato libgdiplus libc6-dev && sudo ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
    - name: build
      run: dotnet build.cs --target=build
      
  windows-build:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
            10.0.x
    - name: dotnet info
      run: |
        dotnet tool install -g dotnet-execute
        dotnet-exec info
    - name: build
      run: dotnet build.cs


================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
  push:
    branches: [ master ]
jobs:
  build:
    name: Release
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v6
    - name: Setup .NET SDK
      uses: WeihanLi/dotnet-install@v0.2.0
      with:
        version: |
            10.0.x
    - name: Build
      shell: pwsh
      run: dotnet build.cs --stable=true
    - name: Get Release Version
      shell: pwsh
      run: .\build\getReleaseVersion.ps1
    - name: Create GitHub release
      uses: marvinpinto/action-automatic-releases@latest
      with:
        repo_token: "${{ secrets.GITHUB_TOKEN }}"
        automatic_release_tag: ${{ env.ReleaseVersion }}
        title: ${{ env.ReleaseVersion }}
        prerelease: false


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# Cutom files
localBuild/
_site
.vscode

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Typescript v1 declaration files
typings/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
tools/**

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs


================================================
FILE: .travis.yml
================================================
language: csharp

# runtime config
mono: none
dotnet: 5.0.100
dist: bionic

# branch build config
branches:
    only:        
        - master
        - preview
        - dev

    except:
        - gh-pages

# git config
git:
    # depth: 1
    lfs_skip_smudge: true # disable the download of LFS objects when cloning

script:
    - bash build.sh --target=build


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at weihanli@outlook.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: Directory.Build.props
================================================
<Project>
  <Import Project="./build/version.props"/>
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <LangVersion>preview</LangVersion>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <Authors>WeihanLi.Npoi Contributors</Authors>
    <Copyright>Copyright 2017-$([System.DateTime]::Now.Year) (c) WeihanLi</Copyright>
    <NoWarn>$(NoWarn);NU5048;</NoWarn>
  </PropertyGroup>
</Project>


================================================
FILE: Directory.Packages.props
================================================
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
    <!-- https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages -->
    <NuGetAudit>true</NuGetAudit>
    <NuGetAuditMode>direct</NuGetAuditMode>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
    <PackageVersion Include="coverlet.collector" Version="10.0.0" />
    <PackageVersion Include="EPPlus.Core.Extensions" Version="2.4.0" />
    <PackageVersion Include="GitHubActionsTestLogger" Version="3.0.3" />
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
    <PackageVersion Include="NPOI" Version="2.7.6" />
    <PackageVersion Include="WeihanLi.Common" Version="1.0.88" />
    <PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.2" />
    <PackageVersion Include="Xunit.DependencyInjection" Version="11.2.1" />
  </ItemGroup>
</Project>


================================================
FILE: LICENSE
================================================
Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2018 WeihanLi

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: README.md
================================================
# WeihanLi.Npoi

[![WeihanLi.Npoi](https://img.shields.io/nuget/v/WeihanLi.Npoi)](https://www.nuget.org/packages/WeihanLi.Npoi/)
[![WeihanLi.Npoi Latest](https://img.shields.io/nuget/vpre/WeihanLi.Npoi)](https://www.nuget.org/packages/WeihanLi.Npoi/absoluteLatest)
[![NuGet Downloads](https://img.shields.io/nuget/dt/WeihanLi.Npoi)](https://www.nuget.org/packages/WeihanLi.Npoi/) 
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/WeihanLi/WeihanLi.Npoi)

[![Azure Pipeline Build Status](https://weihanli.visualstudio.com/Pipelines/_apis/build/status/WeihanLi.WeihanLi.Npoi?branchName=dev)](https://weihanli.visualstudio.com/Pipelines/_build/latest?definitionId=13&branchName=dev) [![Github Build Status](https://github.com/WeihanLi/WeihanLi.Npoi/actions/workflows/dotnet.yml/badge.svg)](https://github.com/WeihanLi/WeihanLi.Npoi/actions/workflows/dotnet.yml)

## Introduction

[NPOI](https://www.nuget.org/packages/NPOI/) extensions based on target framework `netstandard2.0`.

`WeihanLi.Npoi` provides a powerful and easy-to-use toolkit for working with Excel and CSV files in .NET applications. It offers:

- **Simple API**: Intuitive extension methods for common import/export operations
- **Flexible Configuration**: Support for both Attribute-based and FluentAPI configuration
- **High Performance**: Optimized for handling large datasets efficiently
- **Rich Features**: Advanced capabilities like template export, multi-sheet support, and shadow properties
- **CSV Support**: Full support for CSV file operations alongside Excel

## Core Features

### 📥 Data Import

- Import Excel files to `List<TEntity>` or `IEnumerable<TEntity>`
- Import Excel files to `DataTable`
- Import CSV files to entities or DataTable
- Support for custom header rows and sheet selection
- Automatic type conversion and data mapping

### 📤 Data Export

- Export `IEnumerable<TEntity>` or `DataTable` to Excel files (.xls/.xlsx)
- Export data to Excel byte arrays or streams
- Export to CSV files or byte arrays
- Template-based export with placeholders for complex layouts
- Multi-sheet export in a single workbook

### ⚙️ Configuration Options

- **Attribute Configuration**: Simple decoration with `[Column]` and `[Sheet]` attributes
- **FluentAPI Configuration**: Powerful and flexible configuration with fluent syntax (Recommended)
- Custom column mapping, formatting, and transformations
- Support for shadow properties (columns not in the model)

### 🎨 Advanced Capabilities

- **InputFormatter/OutputFormatter**: Transform data during import/export operations
- **ColumnInputFormatter/ColumnOutputFormatter**: Column-specific data transformations
- **CellReader**: Custom cell reading logic
- **Template Export**: Export data based on pre-designed Excel templates
- **Multi-Sheet Support**: Handle multiple sheets in a single workbook
- **Shadow Properties**: Define additional export columns not present in your models
- **Auto Column Width**: Automatic column width adjustment
- **Freeze Panes**: Set freeze panes for better data viewing
- **Filters**: Add auto-filters to your Excel sheets

### GetStarted

#### Installation

```sh
dotnet add package WeihanLi.Npoi
```

#### Quick Start

1. Export list/dataTable to Excel/csv

    ``` csharp
    var entities = new List<Entity>();
    
    // Export to Excel file
    entities.ToExcelFile(string excelPath);
    
    // Export to Excel bytes
    entities.ToExcelBytes(ExcelFormat excelFormat);
    
    // Export to CSV file
    entities.ToCsvFile(string csvPath);
    
    // Export to CSV bytes
    entities.ToCsvBytes();
    ```

2. Import Excel/csv to List

    ``` csharp
    // Read Excel first sheet content to List<T>
    var entityList = ExcelHelper.ToEntityList<T>(string excelPath);

    // Read Excel first sheet content to IEnumerable<T>
    var entityList = ExcelHelper.ToEntities<T>(string excelPath);

    // Read Excel specific sheet content to List<T>
    // You can customize header row index via sheet attribute or fluent api HasSheet
    var entityList1 = ExcelHelper.ToEntityList<T>(string excelPath, int sheetIndex);

    // Import CSV to List<T>
    var entityList2 = CsvHelper.ToEntityList<T>(string csvPath);
    var entityList3 = CsvHelper.ToEntityList<T>(byte[] csvBytes);
    ```

3. Import Excel/csv to DataTable

    ``` csharp
    // Read Excel to DataTable directly, by default read the first sheet content
    var dataTable = ExcelHelper.ToDataTable(string excelPath);

    // Read Excel workbook's specific sheet to DataTable
    var dataTableOfSheetIndex = ExcelHelper.ToDataTable(string excelPath, int sheetIndex);

    // Read Excel with custom header row index
    var dataTableOfSheetIndex = ExcelHelper.ToDataTable(string excelPath, int sheetIndex, int headerRowIndex);

    // Read Excel to DataTable using mapping relations and settings from typeof(T)
    var dataTableT = ExcelHelper.ToDataTable<T>(string excelPath);

    // Read CSV file data to DataTable
    var dataTable1 = CsvHelper.ToDataTable(string csvFilePath);
    ```

More Api documentation: <https://weihanli.github.io/WeihanLi.Npoi/api/WeihanLi.Npoi.html>

### Configuration

#### 1. Using Attributes

Add `ColumnAttribute` on the properties of your entity for export or import operations.

Add `SheetAttribute` on the entity to configure sheet settings. You can set the `StartRowIndex` as needed (default is `1`).

Example:

``` csharp
[Sheet(SheetName = "TestSheet", SheetIndex = 0, AutoColumnWidthEnabled = true)]
public class TestEntity
{
    [Column("ID", Index = 0)]
    public int PKID { get; set; }

    [Column("Bill Title", Index = 1)]
    public string BillTitle { get; set; }

    [Column("Bill Details", Index = 2)]
    public string BillDetails { get; set; }

    [Column("Created By", Index = 3)]
    public string CreatedBy { get; set; }

    [Column("Created Time", Index = 4, Formatter = "yyyy-MM-dd HH:mm:ss")]
    public DateTime CreatedTime { get; set; }
    
    [Column(IsIgnored = true)]
    public string InternalNote { get; set; }
}

public class TestEntity1
{
    [Column("Username")]
    public string Username { get; set; }

    [Column(IsIgnored = true)]
    public string PasswordHash { get; set; }

    [Column("Amount")]
    public decimal Amount { get; set; } = 1000M;

    [Column("WeChat OpenID")]
    public string WechatOpenId { get; set; }

    [Column("Is Active")]
    public bool IsActive { get; set; }
}
```

#### 2. Using FluentAPI (Recommended)

FluentAPI provides greater flexibility and more powerful configuration options.

Example:

``` csharp
var setting = FluentSettings.For<TestEntity>();

// Excel document settings
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

// Sheet configuration (sheetIndex, sheetName, startRowIndex, autoColumnWidth)
setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);

// Apply filters and freeze panes
// setting.HasFilter(0, 1).HasFreezePane(0, 1, 2, 1);

// Configure individual properties
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(5)
    .HasColumnTitle("CreatedBy");

setting.Property(x => x.Enabled)
    .HasColumnInputFormatter(val => "Enabled".Equals(val))
    .HasColumnOutputFormatter(v => v ? "Enabled" : "Disabled");

// Shadow property - define a column that doesn't exist in the model
setting.Property("HiddenProp")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

// Ignore specific properties
setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
```

### Advanced Features

#### Template-based Export

Export data based on pre-designed Excel templates with placeholder support:

```csharp
entities.ToExcelFileByTemplate(
    templatePath: "path/to/template.xlsx",
    excelPath: "path/to/output.xlsx",
    extraData: new { Author = "WeihanLi", Title = "Export Result" }
);
```

Learn more: [Template Export Documentation](https://weihanli.github.io/WeihanLi.Npoi/articles/en/TemplateExport.html)

#### Multi-Sheet Export

Export multiple collections to different sheets in a single workbook:

```csharp
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);
workbook.ImportData(collection1, sheetIndex: 0);
workbook.ImportData(collection2, sheetIndex: 1);
workbook.WriteToFile("multi-sheets.xlsx");
```

Learn more: [Multi-Sheet Documentation](https://weihanli.github.io/WeihanLi.Npoi/articles/en/MultiSheets.html)

#### Shadow Properties

Define additional export columns that don't exist in your model:

```csharp
var settings = FluentSettings.For<TestEntity>();
settings.Property("Employee ID")
    .HasOutputFormatter((entity, val) => $"{entity.UserFields[2].Value}");
settings.Property("Department")
    .HasOutputFormatter((entity, val) => $"{entity.UserFields[1].Value}");
```

Learn more: [Shadow Property Documentation](https://weihanli.github.io/WeihanLi.Npoi/articles/en/ShadowProperty.html)

### Documentation

- 📖 [Complete Documentation](https://weihanli.github.io/WeihanLi.Npoi/)
- 🚀 [Getting Started Guide](https://weihanli.github.io/WeihanLi.Npoi/articles/en/GetStarted.html)
- 📚 [API Reference](https://weihanli.github.io/WeihanLi.Npoi/api/WeihanLi.Npoi.html)
- 🌐 [Articles](https://weihanli.github.io/WeihanLi.Npoi/articles/intro.html)

### More

see some articles here: <https://weihanli.github.io/WeihanLi.Npoi/articles/intro.html>

more usage:

<details>
<summary>Get a workbook</summary>

``` csharp
// load excel workbook from file
var workbook = LoadExcel(string excelPath);

// prepare a workbook accounting to excelPath
var workbook = PrepareWorkbook(string excelPath);

// prepare a workbook accounting to excelPath and custom excel settings
var workbook = PrepareWorkbook(string excelPath, ExcelSetting excelSetting);

// prepare a workbook whether *.xls file
var workbook = PrepareWorkbook(bool isXls);

// prepare a workbook whether *.xls file and custom excel setting
var workbook = PrepareWorkbook(bool isXlsx, ExcelSetting excelSetting);
```

</details>

<details>
<summary>Rich extensions</summary>

``` csharp
List<TEntity> ToEntityList<TEntity>([NotNull]this IWorkbook workbook)

DataTable ToDataTable([NotNull]this IWorkbook workbook)

ISheet ImportData<TEntity>([NotNull] this ISheet sheet, DataTable dataTable)

int ImportData<TEntity>([NotNull] this IWorkbook workbook, IEnumerable<TEntity> list,
            int sheetIndex)

int ImportData<TEntity>([NotNull] this ISheet sheet, IEnumerable<TEntity> list)

int ImportData<TEntity>([NotNull] this IWorkbook workbook, [NotNull] DataTable dataTable,
            int sheetIndex)

ToExcelFile<TEntity>([NotNull] this IEnumerable<TEntity> entityList,
            [NotNull] string excelPath)

int ToExcelStream<TEntity>([NotNull] this IEnumerable<TEntity> entityList,
            [NotNull] Stream stream)

byte[] ToExcelBytes<TEntity>([NotNull] this IEnumerable<TEntity> entityList)

int ToExcelFile([NotNull] this DataTable dataTable, [NotNull] string excelPath)

int ToExcelStream([NotNull] this DataTable dataTable, [NotNull] Stream stream)

byte[] ToExcelBytes([NotNull] this DataTable dataTable)

byte[] ToExcelBytes([NotNull] this IWorkbook workbook)

int WriteToFile([NotNull] this IWorkbook workbook, string filePath)

object GetCellValue([NotNull] this ICell cell, Type propertyType)

T GetCellValue<T>([NotNull] this ICell cell)

void SetCellValue([NotNull] this ICell cell, object value)

byte[] ToCsvBytes<TEntity>(this IEnumerable<TEntity> entities, bool includeHeader)

ToCsvFile<TEntity>(this IEnumerable<TEntity> entities, string filePath, bool includeHeader)

void ToCsvFile(this DataTable dt, string filePath, bool includeHeader)

byte[] ToCsvBytes(this DataTable dt, bool includeHeader)

```

</details>

### Samples

- [.NET Core Sample](https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/samples/DotNetCoreSample/Program.cs)
- [More Samples in Unit Tests](https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/test/WeihanLi.Npoi.Test/ExcelTest.cs)
- [Guide Posts](https://weihanli.github.io/WeihanLi.Npoi/articles/intro.html)

### Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

### Acknowledgements

- Thanks to all the [contributors](https://github.com/WeihanLi/WeihanLi.Npoi/graphs/contributors) and users of this project
- Thanks to [NPOI](https://github.com/tonyqus/npoi) for the excellent Excel library
- Thanks to [FluentExcel](https://github.com/Arch/FluentExcel/) for the FluentAPI inspiration
- Thanks to JetBrains for the free Rider license

### License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.

### Contact & Support

- 📧 Report Issues/Questions/Discussions: [GitHub Issues](https://github.com/WeihanLi/WeihanLi.Npoi/issues)
- 📦 NuGet Package: [WeihanLi.Npoi](https://www.nuget.org/packages/WeihanLi.Npoi/)


================================================
FILE: WeihanLi.Npoi.sln.DotSettings
================================================
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
	<s:Boolean x:Key="/Default/UserDictionary/Words/=weihan/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

================================================
FILE: WeihanLi.Npoi.slnx
================================================
<Solution>
  <Folder Name="/perf/">
    <Project Path="perf/WeihanLi.Npoi.Benchmark/WeihanLi.Npoi.Benchmark.csproj" />
  </Folder>
  <Folder Name="/samples/">
    <Project Path="samples/DotNetCoreSample/DotNetCoreSample.csproj" />
  </Folder>
  <Folder Name="/Solution Items/">
    <File Path=".editorconfig" />
    <File Path="build/version.props" />
    <File Path="Directory.Build.props" />
    <File Path="Directory.Packages.props" />
    <File Path="docs/ReleaseNotes.md" />
    <File Path="README.md" />
  </Folder>
  <Folder Name="/src/">
    <Project Path="src/WeihanLi.Npoi/WeihanLi.Npoi.csproj" />
  </Folder>
  <Folder Name="/test/">
    <Project Path="test/WeihanLi.Npoi.Test/WeihanLi.Npoi.Test.csproj" />
  </Folder>
</Solution>


================================================
FILE: azure-pipelines.yml
================================================
trigger:
  branches:
    include:
    - '*' # must quote since "*" is a YAML reserved character; we want a string
  paths:
    exclude:
    - '*.md'

pool:
  vmImage: 'windows-latest'

steps:
- task: UseDotNet@2
  displayName: 'Use .NET SDK'
  inputs:
    packageType: sdk
    version: 10.0.x

- script: dotnet --info
  displayName: 'dotnet info'

- powershell: dotnet build.cs
  displayName: 'Powershell Script'
  env:
    NuGet__ApiKey: $(nugetApiKey)
    NuGet__Source: $(nugetSourceUrl)


================================================
FILE: build/common.props
================================================
<Project>
  <PropertyGroup>        
    <TargetFramework>netstandard2.0</TargetFramework>  
    <Title>WeihanLi.Npoi</Title>
    <PackageId>WeihanLi.Npoi</PackageId>
    <Authors>WeihanLi</Authors>
    <Company>WeihanLi</Company>
    <Product>WeihanLi.Npoi</Product>
    <PackageIconUrl>https://avatars3.githubusercontent.com/u/7604648</PackageIconUrl>
    <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
    <PackageProjectUrl>https://github.com/WeihanLi/WeihanLi.Npoi</PackageProjectUrl>
    <RepositoryUrl>https://github.com/WeihanLi/WeihanLi.Npoi</RepositoryUrl>
    <RepositoryType>git</RepositoryType>
    <PackageTags>npoi excel csv</PackageTags>
    <Description>
      Amazing NPOI Extensions
      Import/Export excel or csv to/from entity list or DataTable(DataSet)	
      Custom configuration and mappings via Attribute/FluentAPI
    </Description>
    <PackageReleaseNotes>
      https://github.com/WeihanLi/WeihanLi.Npoi/tree/dev/docs/ReleaseNotes.md
    </PackageReleaseNotes>
    <EnablePackageValidation>true</EnablePackageValidation>
    <PackageValidationBaselineVersion>3.3.0</PackageValidationBaselineVersion>
  </PropertyGroup>
</Project>


================================================
FILE: build/getReleaseVersion.ps1
================================================
$versionPath=$PSScriptRoot+"/version.props"
$versionXml=([xml](Get-Content $versionPath))
$versionProperty=$versionXml.Project.PropertyGroup
$ReleaseVersion=$versionProperty.VersionMajor+"."+$versionProperty.VersionMinor+"."+$versionProperty.VersionPatch
$ReleaseVersion
Add-Content -Path $env:GITHUB_ENV -Value "ReleaseVersion=${ReleaseVersion}"

================================================
FILE: build/sign.props
================================================
<Project>
  <PropertyGroup Condition="'$(OS)' == 'Windows_NT' AND '$(Configuration)' == 'Release'">
    <SignAssembly>True</SignAssembly>
    <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)weihanli.snk</AssemblyOriginatorKeyFile>
    <DelaySign>False</DelaySign>
  </PropertyGroup>
</Project>

================================================
FILE: build/version.props
================================================
<Project>
  <PropertyGroup>
    <VersionMajor>3</VersionMajor>
    <VersionMinor>3</VersionMinor>
    <VersionPatch>0</VersionPatch>
    <VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
    <InformationalVersion>$(PackageVersion)</InformationalVersion>
  </PropertyGroup>
</Project>


================================================
FILE: build.cs
================================================
// Copyright (c) Weihan Li. All rights reserved.
// Licensed under the Apache license.

#:package WeihanLi.Common

using WeihanLi.Common.Helpers;

var solutionPath = "./WeihanLi.Npoi.slnx";
string[] srcProjects = [ 
    "./src/WeihanLi.Npoi/WeihanLi.Npoi.csproj"
];
string[] testProjects = [ 
    "./test/WeihanLi.Npoi.Test/WeihanLi.Npoi.Test.csproj"
];
string[] runFileSamplesFolders = [
    "./samples/run-file-samples"
];

await DotNetPackageBuildProcess
    .Create(options => 
    {
        options.SolutionPath = solutionPath;
        options.SrcProjects = srcProjects;
        options.TestProjects = testProjects;
        options.RunFileSampleFolders = runFileSamplesFolders;
    })
    .ExecuteAsync(args);


================================================
FILE: docs/ReleaseNotes.md
================================================
# WeihanLi.Npoi Release Notes

## [3.3.0](https://www.nuget.org/packages/WeihanLi.Npoi/3.3.0)

- Support `HasPostImportAction` to support post handler when import entity
- Code Refactoring to keep clean code
- Modernize dependenncies and integrate GithubActionsTestLogger and improve build script

## [3.2.0](https://www.nuget.org/packages/WeihanLi.Npoi/3.2.0)

- Upgrade dependencies
- Update samples/tests to .NET 10
- refine build scripts

## [3.1.0](https://www.nuget.org/packages/WeihanLi.Npoi/3.1.0)

- Upgrade NPOI package to fix merged region handling bug which causes export excel by template with merged region exception
- Migrate to slnx, xunit v3

## [3.0.0](https://www.nuget.org/packages/WeihanLi.Npoi/3.0.0)

- Remove `net6.0` target, and update build sdk and samples/tests to `net8.0`
- Adjust column index enhancements, respect property index by default and support `WithPropertyComparer`

## [2.5.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.5.0)

- Upgrade dependencies to fix upstream breaking changes
- Enable central package version management

## [2.4.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.4.0)

- Fixes <https://github.com/WeihanLi/WeihanLi.Npoi/issues/146>, fix csv encoding handling issue, thanks @yesyeey for spotting the issue
- `CsvHelper` enhancements

## [2.3.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.3.0)

- Add check before `WriteToFile`
- Close workbook when the workbook would not be used anymore
- Fixes <https://github.com/WeihanLi/WeihanLi.Npoi/issues/142>, great thanks for @hansolehuang's help

## [2.2.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.2.0)

- Fix exception when read header that cell format is not string, <https://github.com/WeihanLi/WeihanLi.Npoi/pull/140>, great thanks for @ensleep's help
- Fix exception when export excel path without directory info, <https://github.com/WeihanLi/WeihanLi.Npoi/pull/140>, great thanks for @ensleep's help

## [2.1.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.1.0)

- Add `HasCellReader` to support more read flexibility

## [2.0.0](https://www.nuget.org/packages/WeihanLi.Npoi/2.0.0)

- Add `net6.0` target support
- Refactor `CsvHelper`
- Add `CsvOptions` for `CsvHelper`
- Add support for validation, fixes #102
- Add support for `ToEntities`, fixes #113

## [1.21.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.21.0)

- Add support for duplicate column name for dataTable
- Fix sheet name not applied bug #127

## [1.20.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.20.0)

- The `ExcelHelper.ToDataTable` was extended with two arguments `bool removeEmptyRows = false, int? maxColumns = null`
- Fix possible `IndexOutOfRangeException` when loading rows

## [1.19.1](https://www.nuget.org/packages/WeihanLi.Npoi/1.19.1)

- Fix `ExcelHelper.ToDataTable` bug when the imported excel column value is not the string value, thanks for @Ninjanaut's contribution

## [1.19.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.19.0)

- Fix `ExcelHelper.ToDataTable` bug when the imported excel file first column is empty, thanks for @Ninjanaut's contribution
- `FluentSettings.LoadMappingProfile` enhancement

## [1.18.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.18.0)

- add `MappingProfile` support so that we could split mappings into separate mapping profiles

## [1.17.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.17.0)

- add `DrawingPatriarch` null check for `GetPicturesAndPosition`

## [1.16.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.16.0)

- add `CellAction`/`RowAction`/`SheetAction` for more flexible export

## [1.15.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.15.0)

- add support for image import/export

## [1.14.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.14.0)

- enable nullable reference
- remove `net45` target

## [1.13.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.13.0)

- add support for `EntityList`/`DataTable` export auto split sheets when needed

## [1.12.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.12.0)

- refactor `ExcelSetting` and `SheetSetting`
- add support for `RowFilter` and `CellFilter`(mainly for import)
- add support for reading file when file opened by another process

## [1.11.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.11.0)

- add support for formula value import

## [1.10.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.10.0)

- add `EndRowIndex` for `SheetSetting`(zero-based, included)
- add FluentAPI `WithDataValidation` for excel setting, if set will ignore invalid data when import excel
- remove `CSVHelper` `TEntity` `new()` constraint

## [1.9.6](https://www.nuget.org/packages/WeihanLi.Npoi/1.9.6)

- fix xlsx workbook `AppVersion` property value caused warning

## [1.9.5](https://www.nuget.org/packages/WeihanLi.Npoi/1.9.5)

- fix `ExcelHelper.ToDataTable` bug with blank cell, thanks for hokis's feedback

## [1.9.4](https://www.nuget.org/packages/WeihanLi.Npoi/1.9.4)

- expose `CsvHelper.GetCsvText` extensions

## [1.9.2](https://www.nuget.org/packages/WeihanLi.Npoi/1.9.2)

- fix `CsvHelper.ParseLine` bug with quoted value, thanks for hokis's effort

## [1.9.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.9.0)

- remove `return 1` code fix #64
- optimize fluent formatter performance
- add `FluentSettings.For` instead of `ExcelHelper.SettingsFor`, fluent settings is not only for excel, but also work with csv

## [1.8.2](https://www.nuget.org/packages/WeihanLi.Npoi/1.8.2)

- add `TemplateHelper.ConfigureTemplateOptions` to allow user config templateParamFormat

## [1.8.1](https://www.nuget.org/packages/WeihanLi.Npoi/1.8.1)

- add `ExportExcelByTemplate`, fix #33
- update `NpoiRowCollection`
- optimize `DataTable` support for csv
- export csv as utf8 encoding
- update export generic type constraint, remove `new()` constraint

## [1.7.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.7.0)

- add `HasColumnInputFormatter`/`HasColumnOutputFormatter`
- simply `IExcelConfiguration` SheetConfiguration

## [1.6.1](https://www.nuget.org/packages/WeihanLi.Npoi/1.6.1)

- fix inherit property configure bug
- fix empty column skipped bug, fix with `row.Cells.Count` => `row.LastCellNumber`
- optimize `AdjustColumnIndex`
- allow use `Ignored(false)` to unignore property

## [1.6.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.6.0)

- add shadow property support
- add version info when export `*.xlsx` excel

## [1.5.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.5.0)

- add support for more format, treat as xlsx
- add `AutoColumnWidthEnabled` setting to `SheetSetting`, no autoSizeColumn by default
- add `CsvHelper.ToEntityList(byte[] bytes)`/`CsvHelper.ToEntityList(Stream stream)`
- use xls for default ExcelFormat(better performance)

## [1.4.5](https://www.nuget.org/packages/WeihanLi.Npoi/1.4.5)

- try to auto adjust column index when import excel(do not update existing settings)
- add `InputFormatter`/`OutputFormatter`
- apply column settings for CSV
- remove unused SheetConfiguration

## [1.4.4](https://www.nuget.org/packages/WeihanLi.Npoi/1.4.4)

- add `ExcelHelper.LoadExcel()`/`ExcelHelper.ToEntityList` override for stream/bytes

## [1.4.3](https://www.nuget.org/packages/WeihanLi.Npoi/1.4.3)

- fix possible `NullReferenceException` when `ExcelHelper.ToEntityList()`/`ToExcelFile()`
- fix treat `string.Empty` as `null` bug, `SetCellType` after `SetCellValue` so that `null` => `CellType.Blank`, `string.Empty` => `CellType.String`

## [1.4.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.4.0)

- add support for custom column width
- fix `ToExcelFile`/`ImportData` extension not applied configuration bug
- add support for specific sheetIndex when export excel

## [1.3.8](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.8)

- fix : `CsvHelper.ToDataTable()` and export DataTable to csv (Thanks for Arek's feedback)
- add support for no header when export excel(to fix #26 )

## [1.3.7](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.7)

- add `HasColumnFormatter<TEntity, TProperty>(Func<TEntity, TProperty, object> columnFormatter)` to support for custom column output for export

## [1.3.6](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.6)

- add [sourcelink](http://github.com/dotnet/sourcelink) support

## [1.3.5](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.5)

- add support for csv escape

## [1.3.3](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.3)

- fix csv custom columnIndex bug
- Optimize csv operation for entity list

## [1.3.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.3.0)

- Update NPOI package to 2.4.1
- Add support for struct types
- Add default excel settings

## [1.2.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.2.0)

- Update NPOI package to 2.4.0, use NPOI for netstandard2.0 also
- Add CsvHelper for import and export csv file, and mapping to entities

## [1.1.0](https://www.nuget.org/packages/WeihanLi.Npoi/1.1.0)

- StrongNaming package


================================================
FILE: docs/api/.gitignore
================================================
###############
#  temp file  #
###############
*.yml
.manifest


================================================
FILE: docs/api/index.md
================================================
# PLACEHOLDER

TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*!


================================================
FILE: docs/articles/en/CustomizeStyle.md
================================================
# Customize Excel Styles

## Introduction

WeihanLi.Npoi provides powerful styling capabilities through the `RowAction` and `CellAction` callbacks in sheet configuration. You can customize fonts, colors, alignment, borders, and add data validation to create professional-looking Excel files.

## Auto Column Width

The simplest styling feature is enabling automatic column width adjustment:

```csharp
var settings = FluentSettings.For<TestEntity>();
settings.HasSheetSetting(config =>
{
    config.AutoColumnWidthEnabled = true;
});
```

This automatically adjusts column widths based on content, making your spreadsheet more readable without manual width adjustments.

## Styling Header Rows

Use `RowAction` to customize the appearance of rows. A common use case is styling the header row:

```csharp
settings.HasSheetSetting(config =>
{
    config.StartRowIndex = 1;
    config.SheetName = "StyledSheet";
    config.AutoColumnWidthEnabled = true;

    config.RowAction = row =>
    {
        if (row.RowNum == 0) // Header row
        {
            // Create a cell style
            var style = row.Sheet.Workbook.CreateCellStyle();
            style.Alignment = HorizontalAlignment.Center;
            
            // Create and configure font
            var font = row.Sheet.Workbook.CreateFont();
            font.FontName = "Arial";
            font.IsBold = true;
            font.FontHeight = 220; // 11pt (font height is in 1/20th of a point)
            font.Color = IndexedColors.White.Index;
            
            style.SetFont(font);
            
            // Set background color
            style.FillForegroundColor = IndexedColors.DarkBlue.Index;
            style.FillPattern = FillPattern.SolidForeground;
            
            // Apply style to all cells in the row
            row.Cells.ForEach(c => c.CellStyle = style);
        }
    };
});
```

### Font Properties

Available font properties include:

- `FontName`: Font family (e.g., "Arial", "Calibri", "Times New Roman")
- `FontHeight`: Font size in 1/20th of a point (e.g., 200 = 10pt, 220 = 11pt)
- `IsBold`: Bold text
- `IsItalic`: Italic text
- `IsStrikeout`: Strikethrough text
- `Underline`: Text underline style
- `Color`: Font color using `IndexedColors`

### Cell Style Properties

Key cell style properties:

- `Alignment`: Horizontal alignment (`Left`, `Center`, `Right`, `Justify`)
- `VerticalAlignment`: Vertical alignment (`Top`, `Center`, `Bottom`)
- `FillForegroundColor`: Background color
- `FillPattern`: Fill pattern (usually `SolidForeground` for solid colors)
- `BorderTop`, `BorderBottom`, `BorderLeft`, `BorderRight`: Border styles
- `WrapText`: Enable text wrapping

## Styling Individual Cells

Use `CellAction` to customize individual cells based on their position or content:

```csharp
settings.HasSheetSetting(config =>
{
    config.CellAction = cell =>
    {
        // Style specific columns
        if (cell.ColumnIndex == 0) // First column
        {
            var style = cell.Sheet.Workbook.CreateCellStyle();
            var font = cell.Sheet.Workbook.CreateFont();
            font.IsBold = true;
            style.SetFont(font);
            cell.CellStyle = style;
        }
        
        // Conditional styling based on content
        if (cell.RowIndex > 0 && cell.ColumnIndex == 3) // Data rows, 4th column
        {
            if (cell.NumericCellValue < 0) // Negative numbers in red
            {
                var style = cell.Sheet.Workbook.CreateCellStyle();
                var font = cell.Sheet.Workbook.CreateFont();
                font.Color = IndexedColors.Red.Index;
                style.SetFont(font);
                cell.CellStyle = style;
            }
        }
    };
});
```

## Data Validation

Add dropdown lists and other validation rules to cells:

```csharp
settings.HasSheetSetting(config =>
{
    config.CellAction = cell =>
    {
        // Add dropdown validation for header cell matching "Status"
        if (cell.RowIndex == 0 && cell.StringCellValue == "Status")
        {
            var validationHelper = cell.Sheet.GetDataValidationHelper();
            
            // Define allowed values
            var statusValues = new[] { "Active", "Inactive", "Pending" };
            var constraint = validationHelper.CreateExplicitListConstraint(statusValues);
            
            // Apply validation to data rows (rows 1-100, current column)
            var addressList = new CellRangeAddressList(1, 100, cell.ColumnIndex, cell.ColumnIndex);
            var validation = validationHelper.CreateValidation(constraint, addressList);
            
            validation.ShowErrorBox = true;
            validation.CreateErrorBox("Invalid Status", "Please select from the dropdown list");
            validation.ShowPromptBox = true;
            validation.CreatePromptBox("Status Selection", "Choose a status from the list");
            
            cell.Sheet.AddValidationData(validation);
        }
    };
});
```

### Validation Types

Different validation types are available:

```csharp
// List validation (dropdown)
var constraint = validationHelper.CreateExplicitListConstraint(new[] { "Option1", "Option2" });

// Integer validation
var intConstraint = validationHelper.CreateIntegerConstraint(
    OperatorType.Between, "1", "100");

// Decimal validation
var decimalConstraint = validationHelper.CreateDecimalConstraint(
    OperatorType.GreaterThan, "0", null);

// Date validation
var dateConstraint = validationHelper.CreateDateConstraint(
    OperatorType.Between, "2024-01-01", "2024-12-31", "yyyy-MM-dd");

// Text length validation
var textConstraint = validationHelper.CreateTextLengthConstraint(
    OperatorType.LessThan, "100", null);
```

## Complete Example

Here's a comprehensive example combining multiple styling features:

```csharp
public class StyledEntityProfile : IMappingProfile<StyledEntity>
{
    public void Configure(IExcelConfiguration<StyledEntity> configuration)
    {
        configuration.HasAuthor("Your Name")
            .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 = "Calibri";
                    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");
    }
}
```

## Best Practices

1. **Reuse Styles**: Create styles once and reuse them rather than creating new styles for each cell to improve performance and reduce file size.

2. **Performance**: Be mindful of performance when applying styles to large datasets. Consider styling only header rows or specific columns.

3. **Color Consistency**: Use `IndexedColors` for consistent coloring across different Excel versions.

4. **Font Sizes**: Remember that font height is in 1/20th of a point (multiply point size by 20).

5. **Validation Ranges**: Set appropriate ranges for data validation to cover expected data rows.

## References

- [Sample Implementation](https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/samples/DotNetCoreSample/Program.cs)
- [NPOI Documentation](http://poi.apache.org/)


================================================
FILE: docs/articles/en/GetStarted.md
================================================
# `WeihanLi.Npoi` Getting Started

## Introduction

`WeihanLi.Npoi` is an Excel import/export library based on NPOI that provides many useful extension methods and also supports CSV import/export.

- Import excel/csv data into `DataTable` or `List<TEntity>`
- Export `IEnumerable<TEntity>` or `DataTable` to Excel files, byte arrays, or streams
- Export `IEnumerable<TEntity>` or `DataTable` to CSV files or byte arrays
- Configuration through `Attributes` or `FluentAPI` (inspired by [FluentExcel](https://github.com/Arch/FluentExcel/))

## Basic Examples

``` csharp
internal class BaseModel
{
    public int Id { get; set; }
}

internal class Notice : BaseModel
{
    public string Title { get; set; }

    public string Content { get; set; }

    public DateTime PublishedAt { get; set; }

    public string Publisher { get; set; }
}
```

Basic import and export:

``` csharp
// entities excel import/export
[Theory]
[InlineData(ExcelFormat.Xls)]
[InlineData(ExcelFormat.Xlsx)]
public void BasicImportExportTest(ExcelFormat excelFormat)
{
    var list = new List<Notice>();
    for (var i = 0; i < 10; i++)
    {
        list.Add(new Notice()
        {
            Id = i + 1,
            Content = $"content_{i}",
            Title = $"title_{i}",
            PublishedAt = DateTime.UtcNow.AddDays(-i),
            Publisher = $"publisher_{i}"
        });
    }
    list.Add(new Notice() { Title = "nnnn" });
    list.Add(null);
    var excelBytes = list.ToExcelBytes(excelFormat);

    var importedList = ExcelHelper.ToEntityList<Notice>(excelBytes, excelFormat);
    Assert.Equal(list.Count, importedList.Count);
    for (var i = 0; i < list.Count; i++)
    {
        if (list[i] is null)
        {
            Assert.Null(importedList[i]);
        }
        else
        {
            Assert.Equal(list[i].Id, importedList[i].Id);
            Assert.Equal(list[i].Title, importedList[i].Title);
            Assert.Equal(list[i].Content, importedList[i].Content);
            Assert.Equal(list[i].Publisher, importedList[i].Publisher);
            Assert.Equal(list[i].PublishedAt.ToTimeString(), importedList[i].PublishedAt.ToTimeString());
        }
    }
}

// DataTable Excel import/export
[Theory]
[InlineData(ExcelFormat.Xls)]
[InlineData(ExcelFormat.Xlsx)]
public void DataTableImportExportTest(ExcelFormat excelFormat)
{
    var dt = new DataTable();
    dt.Columns.AddRange(new[]
    {
        new DataColumn("Name"),
        new DataColumn("Age"),
        new DataColumn("Desc"),
    });
    for (var i = 0; i < 10; i++)
    {
        var row = dt.NewRow();
        row.ItemArray = new object[] { $"Test_{i}", i + 10, $"Desc_{i}" };
        dt.Rows.Add(row);
    }
    //
    var excelBytes = dt.ToExcelBytes(excelFormat);
    var importedData = ExcelHelper.ToDataTable(excelBytes, excelFormat);
    Assert.NotNull(importedData);
    Assert.Equal(dt.Rows.Count, importedData.Rows.Count);
    for (var i = 0; i < dt.Rows.Count; i++)
    {
        Assert.Equal(dt.Rows[i].ItemArray.Length, importedData.Rows[i].ItemArray.Length);
        for (var j = 0; j < dt.Rows[i].ItemArray.Length; j++)
        {
            Assert.Equal(dt.Rows[i].ItemArray[j], importedData.Rows[i].ItemArray[j]);
        }
    }
}

// entities csv import/export
[Fact]
public void BasicImportExportTest()
{
    var list = new List<Notice>();
    for (var i = 0; i < 10; i++)
    {
        list.Add(new Notice()
        {
            Id = i + 1,
            Content = $"content_{i}",
            Title = $"title_{i}",
            PublishedAt = DateTime.UtcNow.AddDays(-i),
            Publisher = $"publisher_{i}"
        });
    }
    list.Add(new Notice()
    {
        Id = 11,
        Content = $"content",
        Title = $"title",
        PublishedAt = DateTime.UtcNow.AddDays(1),
    });
    var csvBytes = list.ToCsvBytes();
    var importedList = CsvHelper.ToEntityList<Notice>(csvBytes);
    Assert.Equal(list.Count, importedList.Count);
    for (var i = 0; i < list.Count; i++)
    {
        Assert.Equal(list[i].Id, importedList[i].Id);
        Assert.Equal(list[i].Title ?? "", importedList[i].Title);
        Assert.Equal(list[i].Content ?? "", importedList[i].Content);
        Assert.Equal(list[i].Publisher ?? "", importedList[i].Publisher);
        Assert.Equal(list[i].PublishedAt.ToTimeString(), importedList[i].PublishedAt.ToTimeString());
    }
}
// DataTable csv import/export
[Fact]
public void DataTableImportExportTest()
{
    var dt = new DataTable();
    dt.Columns.AddRange(new[]
    {
        new DataColumn("Name"),
        new DataColumn("Age"),
        new DataColumn("Desc"),
    });
    for (var i = 0; i < 10; i++)
    {
        var row = dt.NewRow();
        row.ItemArray = new object[] { $"Test_{i}", i + 10, $"Desc_{i}" };
        dt.Rows.Add(row);
    }
    //
    var csvBytes = dt.ToCsvBytes();
    var importedData = CsvHelper.ToDataTable(csvBytes);
    Assert.NotNull(importedData);
    Assert.Equal(dt.Rows.Count, importedData.Rows.Count);
    for (var i = 0; i < dt.Rows.Count; i++)
    {
        Assert.Equal(dt.Rows[i].ItemArray.Length, importedData.Rows[i].ItemArray.Length);
        for (var j = 0; j < dt.Rows[i].ItemArray.Length; j++)
        {
            Assert.Equal(dt.Rows[i].ItemArray[j], importedData.Rows[i].ItemArray[j]);
        }
    }
}
```

## Custom Mapping and Configuration

Using Attributes:

``` csharp
internal class Model
{
    [Column("Hotel ID", Index = 0)]
    public string HotelId { get; set; }

    [Column("Order No", Index = 1)]
    public string OrderNo { get; set; }

    [Column("Hotel Name", Index = 2)]
    public string HotelName { get; set; }

    [Column("Customer Name", Index = 3)]
    public string CustomerName { get; set; }

    [Column(nameof(RoomType), Index = 4)]
    public string RoomType { get; set; }

    [Column(nameof(CheckInDate), Index = 5, Formatter = "yyyy/M/d")]
    public DateTime CheckInDate { get; set; }

    [Column(nameof(CheckOutDate), Index = 6, Formatter = "yyyy/M/d")]
    public DateTime CheckOutDate { get; set; }

    [Column(nameof(RoomNights), Index = 7)]
    public int RoomNights { get; set; }

    [Column(nameof(PaymentType), Index = 8)]
    public string PaymentType { get; set; }

    [Column(nameof(OrderAmount), Index = 9)]
    public decimal OrderAmount { get; set; }

    [Column(nameof(CommissionRate), Index = 10)]
    public decimal CommissionRate { get; set; }

    [Column(nameof(ServiceFee), Index = 11)]
    public decimal ServiceFee { get; set; }
}

[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; } = "{}";
}
```

Using FluentAPI (Recommended for greater flexibility):

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true); // sheet configuration

// setting
//     .HasFilter(0, 1) // Set filter on columns
//     .HasFreezePane(0, 1, 2, 1); // Set freeze pane

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) // Set column width
    .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".Equals(val))
    .HasColumnOutputFormatter(v => v ? "Enabled" : "Disabled");

setting.Property("ShadowProperty")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored(); // ignore column
```


================================================
FILE: docs/articles/en/InputOutputFormatter.md
================================================
# InputOutputFormatter Introduction

## Introduction

WeihanLi.Npoi introduces `OutputFormatter`/`InputFormatter`/`ColumnInputFormatter`/`ColumnOutputFormatter`, greatly enhancing the flexibility of import and export operations. These are only supported through FluentAPI configuration. Let's look at the following example.

## InputFormatter/OutputFormatter

Example Model:

``` csharp
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; }
}
```

Example Configuration:

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);

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".Equals(val))
    .HasColumnOutputFormatter(v => v ? "Enabled" : "Disabled");

setting.Property("HiddenProp")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
```

Test Code:

``` csharp
var entities = new List<TestEntity>()
{
    new TestEntity()
    {
        PKID = 1,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting1",
        SettingValue = "Value1",
        DisplayName = "ddd1"
    },
    new TestEntity()
    {
        PKID=2,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting2",
        SettingValue = "Value2",
        Enabled = true
    },
};
var path = $@"{tempDirPath}\test.xlsx";
entities.ToExcelFile(path);
var entitiesT0 = ExcelHelper.ToEntityList<TestEntity>(path);
```

Export Result:

![Export Result](../images/489462-20200104112133779-1180097402.png)


Import Result:

![Import Result 1](../images/489462-20200104112017420-1450911242.png)

![Import Result 2](../images/489462-20200104112025927-873408781.png)


================================================
FILE: docs/articles/en/MultiSheets.md
================================================
# Multi-Sheet Export

## Introduction

Sometimes we may want to export multiple collections of data in multiple sheets within a single Excel file. You can refer to the following example code:

## Sample

```c#
var collection1 = new[]
{
    new TestEntity1() { Id = 1, Title = "test1" },
    new TestEntity1() { Id = 2, Title = "test2" }
};
var collection2 = new[]
{
    new TestEntity2() { Id = 1, Title = "test1", Description = "description"},
    new TestEntity2() { Id = 2, Title = "test2" }
};
// Prepare a workbook
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);
// Import collection1 to the first sheet
workbook.ImportData(collection1);
// Import collection2 to the second sheet
workbook.ImportData(collection2, 1);
// Export workbook to local file
workbook.WriteToFile("multi-sheets.xlsx");
```

If you need to customize configurations, it works the same as before - you can use attributes or fluent API:

```c#
[Sheet(SheetName = "TestSheet", SheetIndex = 0)]
file sealed class TestEntity1
{
    [Column("ID", Index = 0)]
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
}

file sealed class TestEntity2
{
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Description { get; set; }
}
```

Fluent API configuration:

```c#
var settings = FluentSettings.For<TestEntity2>();
settings.HasSheetSetting(sheet => sheet.SheetName = "TestEntity2", 1);
settings.Property(x => x.Id)
    .HasColumnIndex(0)
    .HasColumnOutputFormatter(v => v.ToString("#0000"))
    ;
settings.Property(x => x.Title)
    .HasColumnIndex(1)
    ;
settings.Property(x => x.Description)
    .HasColumnIndex(2)
    ;
```

Export results:

![Sheet 0](../images/image-20241029231320957.png)

![Sheet 1](../images/image-20241029231519274.png)

## References

- <https://github.com/WeihanLi/SamplesInPractice/blob/main/NPOISample/MultiSheetsSample.cs>
- <https://github.com/WeihanLi/WeihanLi.Npoi/issues/157>


================================================
FILE: docs/articles/en/ShadowProperty.md
================================================
# WeihanLi.Npoi Now Supports `ShadowProperty`

## Introduction

In Entity Framework, there's a concept called `ShadowProperty` (Shadow Property). You can define a property through FluentAPI that is not defined in the .NET model, and this property can only be operated through EF's `Change Tracker`.

When exporting to Excel, you might want some exported columns not to be defined in your model. Some columns might just be added to export a nested property value, or you simply want to define an additional column while the model is defined elsewhere and is inconvenient to modify.

Therefore, starting from version 1.6.0, `WeihanLi.Npoi` supports `ShadowProperty`, bringing the concept from EF into Excel export. Currently, `ShadowProperty` is read-only - reading returns the default value of the type, and it doesn't support `ChangeTracker` or modifications.

## Usage Example

Here's a simple usage example (from a user-submitted issue: <https://github.com/WeihanLi/WeihanLi.Npoi/issues/51>)

``` csharp
using System;
using System.Collections.Generic;
using System.IO;
using WeihanLi.Npoi;

namespace NpoiTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var settings = FluentSettings.For<TestEntity>();
            settings.Property(x => x.Name)
                .HasColumnIndex(0);
            // settings.Property(x => x.UserFields)
            //     .HasOutputFormatter((entity, value) => $"{value[0].Value},{value[2].Value}")
            //     .HasColumnTitle("Name,Employee ID")
            //     .HasColumnIndex(1);
            settings.Property(x=>x.UserFields).Ignored();
            settings.Property("Employee ID")
                .HasOutputFormatter((entity,val)=> $"{entity.UserFields[2].Value}")
                 ;
            settings.Property("Department")
                .HasOutputFormatter((entity,val)=> $"{entity.UserFields[1].Value}")
                 ;

            var data = new List<TestEntity>()
            {
                new TestEntity()
                {
                    Name = "xiaoming",
                    TotalScore = 100,
                    UserFields = new UserField[]
                    {
                        new UserField()
                        {
                            Name = "Name",
                            Value = "xaioming",
                        },
                        new UserField()
                        {
                            Name = "Department",
                            Value = "1212"
                        },
                        new UserField()
                        {
                            Name = "Employee ID",
                            Value = "121213131"
                        },
                    }
                }
            };
            data.ToExcelFile($@"{Directory.GetCurrentDirectory()}\output.xls");
            Console.WriteLine("complete.");
        }

        private class TestEntity
        {
            public string Name { get; set; }

            public UserField[] UserFields { get; set; }

            public int TotalScore { get; set; }
        }

        private class UserField
        {
            public string Fid { get; set; }
            public string Name { get; set; }
            public string Value { get; set; }
        }
    }
}
```

Export result:

![Shadow Property Example](../images/489462-20191213084226066-1767559517.png)

As you can see, we added two columns to the exported Excel that were not defined in the original Model. With this feature, we can more flexibly customize the content to be exported.


================================================
FILE: docs/articles/en/TemplateExport.md
================================================
# Export Excel Based on Template

## Introduction

The original export method is suitable for relatively simple exports where each data record corresponds to one row, and data columns have a high degree of customization. However, it couldn't handle cases where one data record corresponds to multiple rows. Therefore, template-based export was introduced in version 1.8.0.

## Usage Example

### Example Template

![Template Example](../images/489462-20200128142956273-1478084552.png)

The template can have three types of data:

- Global: Parameters that can be specified during export as global parameters. Default format: `$(Global:PropName)`
- Header: Display names for configured properties. Default is the property name. Default format: `$(Header:PropName)`
- Data: Property values of the corresponding data. Default format: `$(Data:PropName)`


Default template parameter format (customizable through `TemplateHelper.ConfigureTemplateOptions` method since version 1.8.2):

- Global parameter: `$(Global:{0})`
- Header parameter: `$(Header:{0})`
- Data parameter: `$(Data:{0})`
- Data Begin: `<Data>`
- Data End: `</Data>`



Template specifications:

The template needs to use Data Begin and Data End to configure the start and end of the data template to identify the start and end rows for each data record.



### Example Code

Example configuration:

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);

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(x => x.Enabled)
    .HasColumnInputFormatter(val => "Enabled".Equals(val))
    .HasColumnOutputFormatter(v => v ? "Enabled" : "Disabled");

setting.Property("HiddenProp")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
```

Template-based export example code:

``` csharp
var entities = new List<TestEntity>()
{
    new TestEntity()
    {
        PKID = 1,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting1",
        SettingValue = "Value1",
        DisplayName = "ddd1"
    },
    new TestEntity()
    {
        PKID=2,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting2",
        SettingValue = "Value2",
        Enabled = true
    },
};
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"
    }
);
```

### Export Result

![Export Result](../images/489462-20200128143038865-1452547986.png)


## More

For convenience, several extension methods have been added:

``` csharp
public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, string excelPath, int sheetIndex = 0, object extraData = null);

public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, string excelPath, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, string excelPath, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, Stream templateStream, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, ISheet templateSheet, object extraData = null);

```


## References

- <https://github.com/WeihanLi/WeihanLi.Npoi>
- <https://github.com/WeihanLi/WeihanLi.Npoi/blob/917e8fb798e9cbae52d121a7d593e37639870911/samples/DotNetCoreSample/Program.cs#L94>


================================================
FILE: docs/articles/intro.md
================================================
# WeihanLi.Npoi

## Intro

`WeihanLi.Npoi` is an extension for excel/csv import/export based on NPOI

## Recommend Articles

English:

- [Getting Started](./en/GetStarted.md)
- [InputOutputFormatter Usage](./en/InputOutputFormatter.md)
- [ShadowProperty Usage](./en/ShadowProperty.md)
- [Template Export](./en/TemplateExport.md)
- [Multi-Sheet Export](./en/MultiSheets.md)
- [Customize Styles](./en/CustomizeStyle.md)

中文:

- [基本示例](./zh/GetStarted.md)
- [InputOutputFormatter 使用](./zh/InputOutputFormatter.md)
- [ShadowProperty 使用](./zh/ShadowProperty.md)
- [根据模板导出](./zh/TemplateExport.md)
- [多 sheet 导出](./zh/MultiSheets.md)
- [自定义样式](./zh/CustomizeStyle.md)

## More

if you wanna add your articles here, welcome pr


================================================
FILE: docs/articles/toc.yml
================================================
- name: Introduction
  href: intro.md
- name: English Articles
  items:
    - name: Getting Started
      href: en/GetStarted.md
    - name: InputOutputFormatter
      href: en/InputOutputFormatter.md
    - name: ShadowProperty
      href: en/ShadowProperty.md
    - name: Template Export
      href: en/TemplateExport.md
    - name: Multi-Sheet Export
      href: en/MultiSheets.md
    - name: Customize Styles
      href: en/CustomizeStyle.md
- name: 中文文章
  items:
    - name: GetStarted
      href: zh/GetStarted.md
    - name: InputOutputFormatter
      href: zh/InputOutputFormatter.md
    - name: ShadowProperty
      href: zh/ShadowProperty.md
    - name: TemplateExport
      href: zh/TemplateExport.md
    - name: MultiSheets
      href: zh/MultiSheets.md
    - name: 自定义样式
      href: zh/CustomizeStyle.md


================================================
FILE: docs/articles/zh/CustomizeStyle.md
================================================
# 自定义 Excel 样式

## 简介

WeihanLi.Npoi 通过 sheet 配置中的 `RowAction` 和 `CellAction` 回调提供了强大的样式定制功能。你可以自定义字体、颜色、对齐方式、边框,并添加数据验证,以创建专业外观的 Excel 文件。

## 自动列宽

最简单的样式功能是启用自动列宽调整:

```csharp
var settings = FluentSettings.For<TestEntity>();
settings.HasSheetSetting(config =>
{
    config.AutoColumnWidthEnabled = true;
});
```

这会根据内容自动调整列宽,使你的电子表格更易读,无需手动调整宽度。

## 样式化标题行

使用 `RowAction` 自定义行的外观。一个常见的用例是样式化标题行:

```csharp
settings.HasSheetSetting(config =>
{
    config.StartRowIndex = 1;
    config.SheetName = "StyledSheet";
    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 = "Arial";
            font.IsBold = true;
            font.FontHeight = 220; // 11pt (字体高度以 1/20 磅为单位)
            font.Color = IndexedColors.White.Index;
            
            style.SetFont(font);
            
            // 设置背景颜色
            style.FillForegroundColor = IndexedColors.DarkBlue.Index;
            style.FillPattern = FillPattern.SolidForeground;
            
            // 将样式应用于行中的所有单元格
            row.Cells.ForEach(c => c.CellStyle = style);
        }
    };
});
```

### 字体属性

可用的字体属性包括:

- `FontName`: 字体族(例如:"宋体"、"微软雅黑"、"Arial")
- `FontHeight`: 字体大小,以 1/20 磅为单位(例如:200 = 10pt, 220 = 11pt)
- `IsBold`: 粗体文本
- `IsItalic`: 斜体文本
- `IsStrikeout`: 删除线文本
- `Underline`: 文本下划线样式
- `Color`: 使用 `IndexedColors` 设置字体颜色

### 单元格样式属性

主要的单元格样式属性:

- `Alignment`: 水平对齐(`Left`、`Center`、`Right`、`Justify`)
- `VerticalAlignment`: 垂直对齐(`Top`、`Center`、`Bottom`)
- `FillForegroundColor`: 背景颜色
- `FillPattern`: 填充模式(通常使用 `SolidForeground` 实现纯色)
- `BorderTop`、`BorderBottom`、`BorderLeft`、`BorderRight`: 边框样式
- `WrapText`: 启用文本换行

## 样式化单个单元格

使用 `CellAction` 根据单元格位置或内容自定义单个单元格:

```csharp
settings.HasSheetSetting(config =>
{
    config.CellAction = cell =>
    {
        // 样式化特定列
        if (cell.ColumnIndex == 0) // 第一列
        {
            var style = cell.Sheet.Workbook.CreateCellStyle();
            var font = cell.Sheet.Workbook.CreateFont();
            font.IsBold = true;
            style.SetFont(font);
            cell.CellStyle = style;
        }
        
        // 基于内容的条件样式
        if (cell.RowIndex > 0 && cell.ColumnIndex == 3) // 数据行,第 4 列
        {
            if (cell.NumericCellValue < 0) // 负数显示为红色
            {
                var style = cell.Sheet.Workbook.CreateCellStyle();
                var font = cell.Sheet.Workbook.CreateFont();
                font.Color = IndexedColors.Red.Index;
                style.SetFont(font);
                cell.CellStyle = style;
            }
        }
    };
});
```

## 数据验证

为单元格添加下拉列表和其他验证规则:

```csharp
settings.HasSheetSetting(config =>
{
    config.CellAction = cell =>
    {
        // 为匹配"状态"的标题单元格添加下拉验证
        if (cell.RowIndex == 0 && cell.StringCellValue == "状态")
        {
            var validationHelper = cell.Sheet.GetDataValidationHelper();
            
            // 定义允许的值
            var statusValues = new[] { "活跃", "停用", "待定" };
            var constraint = validationHelper.CreateExplicitListConstraint(statusValues);
            
            // 将验证应用于数据行(第 1-100 行,当前列)
            var addressList = new CellRangeAddressList(1, 100, cell.ColumnIndex, cell.ColumnIndex);
            var validation = validationHelper.CreateValidation(constraint, addressList);
            
            validation.ShowErrorBox = true;
            validation.CreateErrorBox("状态无效", "请从下拉列表中选择");
            validation.ShowPromptBox = true;
            validation.CreatePromptBox("状态选择", "从列表中选择一个状态");
            
            cell.Sheet.AddValidationData(validation);
        }
    };
});
```

### 验证类型

可用的不同验证类型:

```csharp
// 列表验证(下拉列表)
var constraint = validationHelper.CreateExplicitListConstraint(new[] { "选项1", "选项2" });

// 整数验证
var intConstraint = validationHelper.CreateIntegerConstraint(
    OperatorType.Between, "1", "100");

// 小数验证
var decimalConstraint = validationHelper.CreateDecimalConstraint(
    OperatorType.GreaterThan, "0", null);

// 日期验证
var dateConstraint = validationHelper.CreateDateConstraint(
    OperatorType.Between, "2024-01-01", "2024-12-31", "yyyy-MM-dd");

// 文本长度验证
var textConstraint = validationHelper.CreateTextLengthConstraint(
    OperatorType.LessThan, "100", null);
```

## 完整示例

这是一个结合多种样式功能的综合示例:

```csharp
public class StyledEntityProfile : IMappingProfile<StyledEntity>
{
    public void Configure(IExcelConfiguration<StyledEntity> configuration)
    {
        configuration.HasAuthor("您的名字")
            .HasTitle("样式化报表")
            .HasDescription("专业样式的 Excel 报表");

        configuration.HasSheetSetting(config =>
        {
            config.SheetName = "报表";
            config.StartRowIndex = 1;
            config.AutoColumnWidthEnabled = true;

            // 样式化标题行
            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 = "微软雅黑";
                    headerFont.IsBold = true;
                    headerFont.FontHeight = 240; // 12pt
                    headerStyle.SetFont(headerFont);
                    
                    // 添加边框
                    headerStyle.BorderBottom = BorderStyle.Thin;
                    headerStyle.BorderTop = BorderStyle.Thin;
                    headerStyle.BorderLeft = BorderStyle.Thin;
                    headerStyle.BorderRight = BorderStyle.Thin;
                    
                    row.Cells.ForEach(c => c.CellStyle = headerStyle);
                }
            };

            // 添加验证和条件格式
            config.CellAction = cell =>
            {
                // 为状态列添加验证
                if (cell.RowIndex == 0 && cell.StringCellValue == "状态")
                {
                    var validationHelper = cell.Sheet.GetDataValidationHelper();
                    var statusList = new[] { "已批准", "待定", "已拒绝" };
                    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);
                }
                
                // 用红色突出显示负数金额
                if (cell.RowIndex > 0 && cell.ColumnIndex == 2) // 金额列
                {
                    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 { } // 如果不是数值单元格则跳过
                }
            };
        });

        // 配置属性
        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");
    }
}
```

## 最佳实践

1. **重用样式**:创建样式一次并重用,而不是为每个单元格创建新样式,以提高性能并减小文件大小。

2. **性能考虑**:在处理大型数据集时应用样式时要注意性能。考虑仅样式化标题行或特定列。

3. **颜色一致性**:使用 `IndexedColors` 以在不同的 Excel 版本之间保持一致的颜色。

4. **字体大小**:记住字体高度以 1/20 磅为单位(将磅值乘以 20)。

5. **验证范围**:为数据验证设置适当的范围以覆盖预期的数据行。

## 参考

- [示例实现](https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/samples/DotNetCoreSample/Program.cs)
- [NPOI 文档](http://poi.apache.org/)


================================================
FILE: docs/articles/zh/GetStarted.md
================================================
# `WeihanLi.Npoi` 基础示例

## Intro

`WeihanLi.Npoi` 是基于 NPOI 扩展的 Excel 导入导出库,并提供了很多实用的扩展方法,也支持 CSV 的导入导出,

- 将 excel/csv 数据导入到 `DataTable` 或 `List<TEntity>`
- `IEnumerable<TEntity>` 或 `DataTable` 导出到 Excel,可以导出成 excel 文件或字节数组或者一个流
- `IEnumerable<TEntity>` 或 `DataTable` 导出到 csv 文件或者 csv 字节数组
- 通过 `Attribute` 或者 `FluentAPI`(借鉴了 [FluentExcel](https://github.com/Arch/FluentExcel/) 项目)

## BasicSample

``` csharp
internal class BaseModel
{
    public int Id { get; set; }
}

internal class Notice : BaseModel
{
    public string Title { get; set; }

    public string Content { get; set; }

    public DateTime PublishedAt { get; set; }

    public string Publisher { get; set; }
}
```

基本的导入导出:

``` csharp
// entities excel import/export
[Theory]
[InlineData(ExcelFormat.Xls)]
[InlineData(ExcelFormat.Xlsx)]
public void BasicImportExportTest(ExcelFormat excelFormat)
{
    var list = new List<Notice>();
    for (var i = 0; i < 10; i++)
    {
        list.Add(new Notice()
        {
            Id = i + 1,
            Content = $"content_{i}",
            Title = $"title_{i}",
            PublishedAt = DateTime.UtcNow.AddDays(-i),
            Publisher = $"publisher_{i}"
        });
    }
    list.Add(new Notice() { Title = "nnnn" });
    list.Add(null);
    var excelBytes = list.ToExcelBytes(excelFormat);

    var importedList = ExcelHelper.ToEntityList<Notice>(excelBytes, excelFormat);
    Assert.Equal(list.Count, importedList.Count);
    for (var i = 0; i < list.Count; i++)
    {
        if (list[i] is null)
        {
            Assert.Null(importedList[i]);
        }
        else
        {
            Assert.Equal(list[i].Id, importedList[i].Id);
            Assert.Equal(list[i].Title, importedList[i].Title);
            Assert.Equal(list[i].Content, importedList[i].Content);
            Assert.Equal(list[i].Publisher, importedList[i].Publisher);
            Assert.Equal(list[i].PublishedAt.ToTimeString(), importedList[i].PublishedAt.ToTimeString());
        }
    }
}

// DataTable Excel import/export
[Theory]
[InlineData(ExcelFormat.Xls)]
[InlineData(ExcelFormat.Xlsx)]
public void DataTableImportExportTest(ExcelFormat excelFormat)
{
    var dt = new DataTable();
    dt.Columns.AddRange(new[]
    {
        new DataColumn("Name"),
        new DataColumn("Age"),
        new DataColumn("Desc"),
    });
    for (var i = 0; i < 10; i++)
    {
        var row = dt.NewRow();
        row.ItemArray = new object[] { $"Test_{i}", i + 10, $"Desc_{i}" };
        dt.Rows.Add(row);
    }
    //
    var excelBytes = dt.ToExcelBytes(excelFormat);
    var importedData = ExcelHelper.ToDataTable(excelBytes, excelFormat);
    Assert.NotNull(importedData);
    Assert.Equal(dt.Rows.Count, importedData.Rows.Count);
    for (var i = 0; i < dt.Rows.Count; i++)
    {
        Assert.Equal(dt.Rows[i].ItemArray.Length, importedData.Rows[i].ItemArray.Length);
        for (var j = 0; j < dt.Rows[i].ItemArray.Length; j++)
        {
            Assert.Equal(dt.Rows[i].ItemArray[j], importedData.Rows[i].ItemArray[j]);
        }
    }
}

// entities csv import/export
[Fact]
public void BasicImportExportTest()
{
    var list = new List<Notice>();
    for (var i = 0; i < 10; i++)
    {
        list.Add(new Notice()
        {
            Id = i + 1,
            Content = $"content_{i}",
            Title = $"title_{i}",
            PublishedAt = DateTime.UtcNow.AddDays(-i),
            Publisher = $"publisher_{i}"
        });
    }
    list.Add(new Notice()
    {
        Id = 11,
        Content = $"content",
        Title = $"title",
        PublishedAt = DateTime.UtcNow.AddDays(1),
    });
    var csvBytes = list.ToCsvBytes();
    var importedList = CsvHelper.ToEntityList<Notice>(csvBytes);
    Assert.Equal(list.Count, importedList.Count);
    for (var i = 0; i < list.Count; i++)
    {
        Assert.Equal(list[i].Id, importedList[i].Id);
        Assert.Equal(list[i].Title ?? "", importedList[i].Title);
        Assert.Equal(list[i].Content ?? "", importedList[i].Content);
        Assert.Equal(list[i].Publisher ?? "", importedList[i].Publisher);
        Assert.Equal(list[i].PublishedAt.ToTimeString(), importedList[i].PublishedAt.ToTimeString());
    }
}
// DataTable csv import/export
[Fact]
public void DataTableImportExportTest()
{
    var dt = new DataTable();
    dt.Columns.AddRange(new[]
    {
        new DataColumn("Name"),
        new DataColumn("Age"),
        new DataColumn("Desc"),
    });
    for (var i = 0; i < 10; i++)
    {
        var row = dt.NewRow();
        row.ItemArray = new object[] { $"Test_{i}", i + 10, $"Desc_{i}" };
        dt.Rows.Add(row);
    }
    //
    var csvBytes = dt.ToCsvBytes();
    var importedData = CsvHelper.ToDataTable(csvBytes);
    Assert.NotNull(importedData);
    Assert.Equal(dt.Rows.Count, importedData.Rows.Count);
    for (var i = 0; i < dt.Rows.Count; i++)
    {
        Assert.Equal(dt.Rows[i].ItemArray.Length, importedData.Rows[i].ItemArray.Length);
        for (var j = 0; j < dt.Rows[i].ItemArray.Length; j++)
        {
            Assert.Equal(dt.Rows[i].ItemArray[j], importedData.Rows[i].ItemArray[j]);
        }
    }
}
```

## 自定义映射关系,配置

使用 Attribute 配置:

``` csharp
internal class Model
{
    [Column("酒店编号", Index = 0)]
    public string HotelId { get; set; }

    [Column("订单号", Index = 1)]
    public string OrderNo { get; set; }

    [Column("酒店名称", Index = 2)]
    public string HotelName { get; set; }

    [Column("客户名称", Index = 3)]
    public string CustomerName { get; set; }

    [Column(nameof(房型名称), Index = 4)]
    public string 房型名称 { get; set; }

    [Column(nameof(入住日期), Index = 5, Formatter = "yyyy/M/d")]
    public DateTime 入住日期 { get; set; }

    [Column(nameof(离店日期), Index = 6, Formatter = "yyyy/M/d")]
    public DateTime 离店日期 { get; set; }

    [Column(nameof(间夜), Index = 7)]
    public int 间夜 { get; set; }

    [Column(nameof(支付类型), Index = 8)]
    public string 支付类型 { get; set; }

    [Column(nameof(订单金额), Index = 9)]
    public decimal 订单金额 { get; set; }

    [Column(nameof(佣金率), Index = 10)]
    public decimal 佣金率 { get; set; }

    [Column(nameof(服务费), Index = 11)]
    public decimal 服务费 { get; set; }
}

[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; } = "{}";
}
```

使用 FluentAPI 配置(推荐,更灵活)

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true); // sheet 配置

// 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 => "启用".Equals(val))
    .HasColumnOutputFormatter(v => v ? "启用" : "禁用");

setting.Property("ShadowProperty")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored(); // ignore column
```


================================================
FILE: docs/articles/zh/InputOutputFormatter.md
================================================
# InputOutputFormatter 介绍

## Intro

WeihanLi.Npoi 引入了 `OutputFormatter`/`InputFormatter`/`ColumnInputFormatter`/`ColumnOutputFormatter`,极大程度上增强了导入导出的灵活性,只支持通过 FluentAPI 配置,来看下面的示例

## InputFormatter/OutputFormatter

示例 Model:

``` csharp
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; }
}
```

示例配置:

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);

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 => "启用".Equals(val))
    .HasColumnOutputFormatter(v => v ? "启用" : "禁用");

setting.Property("HiddenProp")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
```

测试代码:

``` csharp
var entities = new List<TestEntity>()
{
    new TestEntity()
    {
        PKID = 1,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting1",
        SettingValue = "Value1",
        DisplayName = "ddd1"
    },
    new TestEntity()
    {
        PKID=2,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting2",
        SettingValue = "Value2",
        Enabled = true
    },
};
var path = $@"{tempDirPath}\test.xlsx";
entities.ToExcelFile(path);
var entitiesT0 = ExcelHelper.ToEntityList<TestEntity>(path);
```

导出结果:

![](../images/489462-20200104112133779-1180097402.png)


导入结果:

![](../images/489462-20200104112017420-1450911242.png)

![](../images/489462-20200104112025927-873408781.png)


================================================
FILE: docs/articles/zh/MultiSheets.md
================================================
# 多 sheet 导出

## Intro

有时我们可能会希望在一个 excel 里导出多个 sheet 导出多个集合的数据,可以参考下面的示例代码:

## Sample

```c#
var collection1 = new[]
{
    new TestEntity1() { Id = 1, Title = "test1" },
    new TestEntity1() { Id = 2, Title = "test2" }
};
var collection2 = new[]
{
    new TestEntity2() { Id = 1, Title = "test1", Description = "description"},
    new TestEntity2() { Id = 2, Title = "test2" }
};
// 准备一个 workbook
var workbook = ExcelHelper.PrepareWorkbook(ExcelFormat.Xlsx);
// 导入 collection1 到第一个 sheet
workbook.ImportData(collection1);
// 导入 collection2 到第二个 sheet
workbook.ImportData(collection2, 1);
// 导出 workbook 到本地文件
workbook.WriteToFile("multi-sheets.xlsx");
```

如果需要自定义一些配置还是和之前是一样的,可以使用 attribute 的方式也可以使用 fluent API 的方式

```c#
[Sheet(SheetName = "TestSheet", SheetIndex = 0)]
file sealed class TestEntity1
{
    [Column("ID", Index = 0)]
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
}

file sealed class TestEntity2
{
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Description { get; set; }
}
```

Fluent API 配置如下:

```c#
var settings = FluentSettings.For<TestEntity2>();
settings.HasSheetSetting(sheet => sheet.SheetName = "TestEntity2", 1);
settings.Property(x => x.Id)
    .HasColumnIndex(0)
    .HasColumnOutputFormatter(v => v.ToString("#0000"))
    ;
settings.Property(x => x.Title)
    .HasColumnIndex(1)
    ;
settings.Property(x => x.Description)
    .HasColumnIndex(2)
    ;
```

导出结果如下:

![sheet0](../images/image-20241029231320957.png)

![sheet1](../images/image-20241029231519274.png)

## References

- <https://github.com/WeihanLi/SamplesInPractice/blob/main/NPOISample/MultiSheetsSample.cs>
- <https://github.com/WeihanLi/WeihanLi.Npoi/issues/157>


================================================
FILE: docs/articles/zh/ShadowProperty.md
================================================
# WeihanLi.Npoi 支持 `ShadowProperty` 了

## Intro

在 EF 里有个 `ShadowProperty` (阴影属性/影子属性)的概念,你可以通过 FluentAPI 的方式来定义一个不在 .NET model 里定义的属性,只能通过 EF 里的 `Change Tracker` 来操作这种属性。

在导出 Excel 的时候,可能希望导出的列并不是都定义好在我们的 model 中的,有的可能只是想增加一列导出某个属性中的嵌套属性之中的某一个属性值,或者我就是单纯的想多定义一列,而这个时候可能 model 是别的地方写死的,不方便改。

于是 `WeihanLi.Npoi` 从 1.6.0 版本开始支持 `ShadowProperty` ,将  EF 里的 `ShadowProperty` 引入到 excel 导出里,目前来说 `ShadowProperty` 是不可写的,读取的话也只是返回一个类型的默认值,不支持 `ChangeTracker`,不支持改。

## 使用示例

来看一个简单使用示例:(示例来源于网友提出的这个issue: <https://github.com/WeihanLi/WeihanLi.Npoi/issues/51>)

``` csharp
using System;
using System.Collections.Generic;
using System.IO;
using WeihanLi.Npoi;

namespace NpoiTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var settings = FluentSettings.For<TestEntity>();
            settings.Property(x => x.Name)
                .HasColumnIndex(0);
            // settings.Property(x => x.UserFields)
            //     .HasOutputFormatter((entity, value) => $"{value[0].Value},{value[2].Value}")
            //     .HasColumnTitle("姓名,工号")
            //     .HasColumnIndex(1);
            settings.Property(x=>x.UserFields).Ignored();
            settings.Property("工号")
                .HasOutputFormatter((entity,val)=> $"{entity.UserFields[2].Value}")
                 ;
            settings.Property("部门")
                .HasOutputFormatter((entity,val)=> $"{entity.UserFields[1].Value}")
                 ;

            var data = new List<TestEntity>()
            {
                new TestEntity()
                {
                    Name = "xiaoming",
                    TotalScore = 100,
                    UserFields = new UserField[]
                    {
                        new UserField()
                        {
                            Name = "姓名",
                            Value = "xaioming",
                        },
                        new UserField()
                        {
                            Name = "部门",
                            Value = "1212"
                        },
                        new UserField()
                        {
                            Name = "工号",
                            Value = "121213131"
                        },
                    }
                }
            };
            data.ToExcelFile($@"{Directory.GetCurrentDirectory()}\output.xls");
            Console.WriteLine("complete.");
        }

        private class TestEntity
        {
            public string Name { get; set; }

            public UserField[] UserFields { get; set; }

            public int TotalScore { get; set; }
        }

        private class UserField
        {
            public string Fid { get; set; }
            public string Name { get; set; }
            public string Value { get; set; }
        }
    }
}
```

导出效果如下:

![](../images/489462-20191213084226066-1767559517.png)

可以看到,我们为导出的 Excel 增加在原本的 Model 里没有定义的两列,借助于此,我们可以更灵活的定制要导出的内容


================================================
FILE: docs/articles/zh/TemplateExport.md
================================================
# 根据模板导出Excel

## Intro

原来的导出方式比较适用于比较简单的导出,每一条数据在一行,数据列虽然自定义程度比较高,如果要一条数据对应多行就做不到了,于是就想支持根据模板导出,在 1.8.0 版本中引入了根据模板导出的功能

## 使用示例

### 示例模板

![](../images/489462-20200128142956273-1478084552.png)

模板规划的可以有三种数据:

- Global:一个是导出的时候可以指定一些参数,作为 Global 参数,默认参数格式使用: `$(Global:PropName)` 的格式
- Header:配置的对应属性的显示名称,默认是属性名称,默认参数格式:`$(Header:PropName)`
- Data:对应数据的属性值,默认参数格式:`$(Data:PropName)`


默认模板参数格式(从 1.8.2 版本开始支持通过 `TemplateHelper.ConfigureTemplateOptions` 方法来自定义):

- Global 参数:`$(Global:{0})`
- Header 参数:`$(Header:{0})`
- Data 参数:`$(Data:{0})`
- Data Begin: `<Data>`
- Data End: `</Data>`



模板规范:

模板需要通过 Data Begin 和 Data End 来配置数据模板的开始和结束以识别每一个数据对应的开始行和结束行



### 示例代码

示例配置

``` csharp
var setting = FluentSettings.For<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
    .HasTitle("WeihanLi.Npoi test")
    .HasDescription("WeihanLi.Npoi test")
    .HasSubject("WeihanLi.Npoi test");

setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);

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(x => x.Enabled)
    .HasColumnInputFormatter(val => "启用".Equals(val))
    .HasColumnOutputFormatter(v => v ? "启用" : "禁用");

setting.Property("HiddenProp")
    .HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");

setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
```

根据模板导出示例代码:

``` csharp
var entities = new List<TestEntity>()
{
    new TestEntity()
    {
        PKID = 1,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting1",
        SettingValue = "Value1",
        DisplayName = "ddd1"
    },
    new TestEntity()
    {
        PKID=2,
        SettingId = Guid.NewGuid(),
        SettingName = "Setting2",
        SettingValue = "Value2",
        Enabled = true
    },
};
var csvFilePath = $@"{tempDirPath}\test.csv";
entities.ToExcelFileByTemplate(
    Path.Combine(ApplicationHelper.AppRoot, "Templates", "testTemplate.xlsx"),
    ApplicationHelper.MapPath("templateTestEntities.xlsx"),
    extraData: new
    {
        Author = "WeihanLi",
        Title = "导出结果"
    }
);
```

### 导出结果

![](../images/489462-20200128143038865-1452547986.png)


## More

为了方便使用,增加了一些方便的扩展方法:

``` csharp
public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, string excelPath, int sheetIndex = 0, object extraData = null);

public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, string excelPath, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, string excelPath, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, Stream templateStream, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, int sheetIndex = 0, object extraData = null);

public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, ISheet templateSheet, object extraData = null);

```


## Reference

- <https://github.com/WeihanLi/WeihanLi.Npoi>
- <https://github.com/WeihanLi/WeihanLi.Npoi/blob/917e8fb798e9cbae52d121a7d593e37639870911/samples/DotNetCoreSample/Program.cs#L94>


================================================
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
================================================
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="defaultPushSource" value="nuget" />
  </config>
  <packageSources>
    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
    <clear />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>

================================================
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
================================================
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>WeihanLi.Npoi.Benchmark.ExportExcelTest-20191108-071719</title>

<style type="text/css">
	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
	td, th { padding: 6px 13px; border: 1px solid #ddd; }
	tr { background-color: #fff; border-top: 1px solid #ccc; }
	tr:nth-child(even) { background: #f8f8f8; }
</style>
</head>
<body>
<pre><code>
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
</code></pre>
<pre><code>IterationCount=5  LaunchCount=1  WarmupCount=1  
</code></pre>

<table>
<thead><tr><th>                   Method</th><th>RowsCount</th><th> Mean</th><th>Error</th><th>StdDev</th><th>  Min</th><th>  Max</th><th>Median</th><th>Gen 0</th><th>Gen 1</th><th>Gen 2</th><th>Allocated</th>
</tr>
</thead><tbody><tr><td>ExportToCsvBytesTest</td><td>10000</td><td>22.77 ms</td><td>0.5667 ms</td><td>0.1472 ms</td><td>22.54 ms</td><td>22.95 ms</td><td>22.77 ms</td><td>2281.2500</td><td>937.5000</td><td>281.2500</td><td>12.12 MB</td>
</tr><tr><td>NpoiExportToXlsBytesTest</td><td>10000</td><td>219.87 ms</td><td>3.8409 ms</td><td>0.9975 ms</td><td>218.92 ms</td><td>221.40 ms</td><td>219.60 ms</td><td>6000.0000</td><td>2000.0000</td><td>1000.0000</td><td>43.99 MB</td>
</tr><tr><td>NpoiExportToXlsxBytesTest</td><td>10000</td><td>470.79 ms</td><td>9.3139 ms</td><td>2.4188 ms</td><td>467.01 ms</td><td>473.70 ms</td><td>471.26 ms</td><td>20000.0000</td><td>6000.0000</td><td>2000.0000</td><td>104.31 MB</td>
</tr><tr><td>EpplusExportToBytesTest</td><td>10000</td><td>203.82 ms</td><td>5.0193 ms</td><td>1.3035 ms</td><td>203.13 ms</td><td>206.15 ms</td><td>203.25 ms</td><td>11000.0000</td><td>4000.0000</td><td>1000.0000</td><td>56.66 MB</td>
</tr><tr><td>StructExportToCsvBytesTest</td><td>10000</td><td>21.46 ms</td><td>0.7542 ms</td><td>0.1959 ms</td><td>21.30 ms</td><td>21.73 ms</td><td>21.34 ms</td><td>2281.2500</td><td>937.5000</td><td>281.2500</td><td>12.12 MB</td>
</tr><tr><td>NpoiStructExportToXlsBytesTest</td><td>10000</td><td>212.54 ms</td><td>12.7005 ms</td><td>3.2983 ms</td><td>209.21 ms</td><td>216.65 ms</td><td>211.42 ms</td><td>7000.0000</td><td>3000.0000</td><td>1000.0000</td><td>44.37 MB</td>
</tr><tr><td>NpoiStructExportToXlsxBytesTest</td><td>10000</td><td>495.55 ms</td><td>45.1010 ms</td><td>11.7126 ms</td><td>482.73 ms</td><td>514.33 ms</td><td>492.62 ms</td><td>20000.0000</td><td>7000.0000</td><td>2000.0000</td><td>104.69 MB</td>
</tr><tr><td>EpplusStructExportToBytesTest</td><td>10000</td><td>208.60 ms</td><td>5.3520 ms</td><td>1.3899 ms</td><td>206.94 ms</td><td>210.32 ms</td><td>208.32 ms</td><td>11000.0000</td><td>4000.0000</td><td>1000.0000</td><td>56.66 MB</td>
</tr><tr><td>ExportToCsvBytesTest</td><td>30000</td><td>72.16 ms</td><td>3.2924 ms</td><td>0.8550 ms</td><td>71.34 ms</td><td>73.59 ms</td><td>71.86 ms</td><td>6000.0000</td><td>1571.4286</td><td>571.4286</td><td>36.47 MB</td>
</tr><tr><td>NpoiExportToXlsBytesTest</td><td>30000</td><td>839.63 ms</td><td>22.8596 ms</td><td>5.9366 ms</td><td>835.13 ms</td><td>849.85 ms</td><td>837.76 ms</td><td>20000.0000</td><td>8000.0000</td><td>2000.0000</td><td>124.18 MB</td>
</tr><tr><td>NpoiExportToXlsxBytesTest</td><td>30000</td><td>1,478.00 ms</td><td>48.6880 ms</td><td>12.6441 ms</td><td>1,457.50 ms</td><td>1,489.99 ms</td><td>1,480.52 ms</td><td>59000.0000</td><td>16000.0000</td><td>4000.0000</td><td>315.85 MB</td>
</tr><tr><td>EpplusExportToBytesTest</td><td>30000</td><td>624.67 ms</td><td>40.5093 ms</td><td>10.5201 ms</td><td>616.60 ms</td><td>642.67 ms</td><td>621.37 ms</td><td>31000.0000</td><td>10000.0000</td><td>3000.0000</td><td>172.73 MB</td>
</tr><tr><td>StructExportToCsvBytesTest</td><td>30000</td><td>63.51 ms</td><td>2.5019 ms</td><td>0.6497 ms</td><td>62.53 ms</td><td>64.25 ms</td><td>63.58 ms</td><td>5875.0000</td><td>1375.0000</td><td>375.0000</td><td>36.47 MB</td>
</tr><tr><td>NpoiStructExportToXlsBytesTest</td><td>30000</td><td>853.48 ms</td><td>33.3918 ms</td><td>8.6718 ms</td><td>839.53 ms</td><td>862.13 ms</td><td>856.08 ms</td><td>20000.0000</td><td>8000.0000</td><td>2000.0000</td><td>125.32 MB</td>
</tr><tr><td>NpoiStructExportToXlsxBytesTest</td><td>30000</td><td>1,516.05 ms</td><td>141.2409 ms</td><td>36.6798 ms</td><td>1,474.05 ms</td><td>1,553.23 ms</td><td>1,534.14 ms</td><td>59000.0000</td><td>16000.0000</td><td>4000.0000</td><td>317 MB</td>
</tr><tr><td>EpplusStructExportToBytesTest</td><td>30000</td><td>624.10 ms</td><td>18.2990 ms</td><td>4.7522 ms</td><td>616.20 ms</td><td>627.98 ms</td><td>624.45 ms</td><td>31000.0000</td><td>10000.0000</td><td>3000.0000</td><td>172.72 MB</td>
</tr><tr><td>ExportToCsvBytesTest</td><td>50000</td><td>113.06 ms</td><td>1.6585 ms</td><td>0.4307 ms</td><td>112.55 ms</td><td>113.55 ms</td><td>113.01 ms</td><td>10000.0000</td><td>2000.0000</td><td>800.0000</td><td>60.81 MB</td>
</tr><tr><td>NpoiExportToXlsBytesTest</td><td>50000</td><td>1,666.19 ms</td><td>43.1443 ms</td><td>11.2044 ms</td><td>1,651.36 ms</td><td>1,677.04 ms</td><td>1,669.51 ms</td><td>33000.0000</td><td>12000.0000</td><td>3000.0000</td><td>212.25 MB</td>
</tr><tr><td>NpoiExportToXlsxBytesTest</td><td>50000</td><td>2,562.64 ms</td><td>130.8702 ms</td><td>33.9866 ms</td><td>2,516.62 ms</td><td>2,595.77 ms</td><td>2,573.09 ms</td><td>96000.0000</td><td>24000.0000</td><td>4000.0000</td><td>532.54 MB</td>
</tr><tr><td>EpplusExportToBytesTest</td><td>50000</td><td>1,059.02 ms</td><td>76.3548 ms</td><td>19.8291 ms</td><td>1,041.61 ms</td><td>1,093.02 ms</td><td>1,052.11 ms</td><td>51000.0000</td><td>13000.0000</td><td>2000.0000</td><td>270.94 MB</td>
</tr><tr><td>StructExportToCsvBytesTest</td><td>50000</td><td>108.91 ms</td><td>4.0316 ms</td><td>1.0470 ms</td><td>107.28 ms</td><td>110.19 ms</td><td>108.95 ms</td><td>10000.0000</td><td>2000.0000</td><td>800.0000</td><td>60.81 MB</td>
</tr><tr><td>NpoiStructExportToXlsBytesTest</td><td>50000</td><td>1,675.32 ms</td><td>63.9457 ms</td><td>16.6065 ms</td><td>1,660.80 ms</td><td>1,703.80 ms</td><td>1,669.06 ms</td><td>33000.0000</td><td>12000.0000</td><td>3000.0000</td><td>214.15 MB</td>
</tr><tr><td>NpoiStructExportToXlsxBytesTest</td><td>50000</td><td>2,505.01 ms</td><td>231.4485 ms</td><td>60.1064 ms</td><td>2,443.93 ms</td><td>2,576.48 ms</td><td>2,494.21 ms</td><td>96000.0000</td><td>24000.0000</td><td>4000.0000</td><td>534.45 MB</td>
</tr><tr><td>EpplusStructExportToBytesTest</td><td>50000</td><td>1,031.01 ms</td><td>17.5706 ms</td><td>4.5630 ms</td><td>1,027.89 ms</td><td>1,038.94 ms</td><td>1,029.03 ms</td><td>51000.0000</td><td>13000.0000</td><td>2000.0000</td><td>270.93 MB</td>
</tr><tr><td>ExportToCsvBytesTest</td><td>65535</td><td>147.35 ms</td><td>1.3296 ms</td><td>0.3453 ms</td><td>147.03 ms</td><td>147.83 ms</td><td>147.16 ms</td><td>12750.0000</td><td>2000.0000</td><td>500.0000</td><td>79.73 MB</td>
</tr><tr><td>NpoiExportToXlsBytesTest</td><td>65535</td><td>2,456.24 ms</td><td>21.4291 ms</td><td>5.5651 ms</td><td>2,448.12 ms</td><td>2,462.39 ms</td><td>2,455.63 ms</td><td>43000.0000</td><td>15000.0000</td><td>3000.0000</td><td>277.42 MB</td>
</tr><tr><td>NpoiExportToXlsxBytesTest</td><td>65535</td><td>3,292.05 ms</td><td>120.2493 ms</td><td>31.2284 ms</td><td>3,257.61 ms</td><td>3,327.38 ms</td><td>3,280.70 ms</td><td>127000.0000</td><td>30000.0000</td><td>5000.0000</td><td>685.91 MB</td>
</tr><tr><td>EpplusExportToBytesTest</td><td>65535</td><td>1,365.16 ms</td><td>27.3326 ms</td><td>7.0982 ms</td><td>1,355.48 ms</td><td>1,374.40 ms</td><td>1,363.77 ms</td><td>68000.0000</td><td>17000.0000</td><td>3000.0000</td><td>343.35 MB</td>
</tr><tr><td>StructExportToCsvBytesTest</td><td>65535</td><td>141.21 ms</td><td>6.6211 ms</td><td>1.7195 ms</td><td>139.06 ms</td><td>143.00 ms</td><td>141.42 ms</td><td>12750.0000</td><td>2000.0000</td><td>500.0000</td><td>79.73 MB</td>
</tr><tr><td>NpoiStructExportToXlsBytesTest</td><td>65535</td><td>2,505.47 ms</td><td>83.5632 ms</td><td>21.7011 ms</td><td>2,483.53 ms</td><td>2,536.38 ms</td><td>2,504.97 ms</td><td>43000.0000</td><td>15000.0000</td><td>3000.0000</td><td>279.92 MB</td>
</tr><tr><td>NpoiStructExportToXlsxBytesTest</td><td>65535</td><td>3,235.57 ms</td><td>116.3763 ms</td><td>30.2226 ms</td><td>3,205.37 ms</td><td>3,284.36 ms</td><td>3,230.79 ms</td><td>127000.0000</td><td>30000.0000</td><td>5000.0000</td><td>688.39 MB</td>
</tr><tr><td>EpplusStructExportToBytesTest</td><td>65535</td><td>1,349.52 ms</td><td>8.8304 ms</td><td>2.2932 ms</td><td>1,346.47 ms</td><td>1,352.90 ms</td><td>1,349.45 ms</td><td>67000.0000</td><td>16000.0000</td><td>3000.0000</td><td>343.35 MB</td>
</tr></tbody></table>
</body>
</html>


================================================
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
================================================
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>WeihanLi.Npoi.Benchmark.ImportExcelTest-20191108-072305</title>

<style type="text/css">
	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
	td, th { padding: 6px 13px; border: 1px solid #ddd; }
	tr { background-color: #fff; border-top: 1px solid #ccc; }
	tr:nth-child(even) { background: #f8f8f8; }
</style>
</head>
<body>
<pre><code>
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
</code></pre>
<pre><code>IterationCount=5  LaunchCount=1  WarmupCount=1  
</code></pre>

<table>
<thead><tr><th>           Method</th><th>RowsCount</th><th>Mean</th><th>Error</th><th>StdDev</th><th> Min</th><th> Max</th><th>Median</th><th>Gen 0</th><th>Gen 1</th><th>Gen 2</th><th>Allocated</th>
</tr>
</thead><tbody><tr><td>ImportFromCsvBytesTest</td><td>10000</td><td>171.2 ms</td><td>2.904 ms</td><td>0.7541 ms</td><td>170.0 ms</td><td>172.0 ms</td><td>171.2 ms</td><td>9333.3333</td><td>2000.0000</td><td>333.3333</td><td>36.44 MB</td>
</tr><tr><td>ImportFromXlsBytesTest</td><td>10000</td><td>353.8 ms</td><td>10.170 ms</td><td>2.6412 ms</td><td>351.8 ms</td><td>358.4 ms</td><td>352.9 ms</td><td>15000.0000</td><td>6000.0000</td><td>2000.0000</td><td>64.71 MB</td>
</tr><tr><td>ImportFromXlsxBytesTest</td><td>10000</td><td>758.2 ms</td><td>10.212 ms</td><td>2.6520 ms</td><td>755.6 ms</td><td>762.3 ms</td><td>757.8 ms</td><td>25000.0000</td><td>11000.0000</td><td>3000.0000</td><td>110.87 MB</td>
</tr><tr><td>ImportFromCsvBytesTest</td><td>30000</td><td>511.5 ms</td><td>17.159 ms</td><td>4.4562 ms</td><td>504.0 ms</td><td>514.9 ms</td><td>512.7 ms</td><td>31000.0000</td><td>7000.0000</td><td>1000.0000</td><td>109.1 MB</td>
</tr><tr><td>ImportFromXlsBytesTest</td><td>30000</td><td>1,050.8 ms</td><td>33.740 ms</td><td>8.7622 ms</td><td>1,040.2 ms</td><td>1,064.3 ms</td><td>1,049.8 ms</td><td>47000.0000</td><td>18000.0000</td><td>3000.0000</td><td>186.28 MB</td>
</tr><tr><td>ImportFromXlsxBytesTest</td><td>30000</td><td>2,358.6 ms</td><td>284.891 ms</td><td>73.9854 ms</td><td>2,228.2 ms</td><td>2,405.3 ms</td><td>2,378.8 ms</td><td>67000.0000</td><td>23000.0000</td><td>4000.0000</td><td>331.5 MB</td>
</tr><tr><td>ImportFromCsvBytesTest</td><td>50000</td><td>860.7 ms</td><td>11.026 ms</td><td>2.8634 ms</td><td>857.3 ms</td><td>865.1 ms</td><td>860.0 ms</td><td>50000.0000</td><td>12000.0000</td><td>1000.0000</td><td>182 MB</td>
</tr><tr><td>ImportFromXlsBytesTest</td><td>50000</td><td>1,703.0 ms</td><td>23.050 ms</td><td>5.9861 ms</td><td>1,695.9 ms</td><td>1,709.7 ms</td><td>1,703.3 ms</td><td>76000.0000</td><td>28000.0000</td><td>2000.0000</td><td>315.85 MB</td>
</tr><tr><td>ImportFromXlsxBytesTest</td><td>50000</td><td>3,869.8 ms</td><td>141.111 ms</td><td>36.6460 ms</td><td>3,817.0 ms</td><td>3,909.6 ms</td><td>3,872.4 ms</td><td>110000.0000</td><td>36000.0000</td><td>3000.0000</td><td>552.76 MB</td>
</tr><tr><td>ImportFromCsvBytesTest</td><td>65535</td><td>1,144.7 ms</td><td>65.693 ms</td><td>17.0602 ms</td><td>1,121.2 ms</td><td>1,162.6 ms</td><td>1,149.4 ms</td><td>65000.0000</td><td>16000.0000</td><td>1000.0000</td><td>238.24 MB</td>
</tr><tr><td>ImportFromXlsBytesTest</td><td>65535</td><td>2,324.6 ms</td><td>23.299 ms</td><td>6.0507 ms</td><td>2,318.4 ms</td><td>2,333.9 ms</td><td>2,323.8 ms</td><td>99000.0000</td><td>35000.0000</td><td>3000.0000</td><td>413.07 MB</td>
</tr><tr><td>ImportFromXlsxBytesTest</td><td>65535</td><td>5,011.3 ms</td><td>108.362 ms</td><td>28.1414 ms</td><td>4,977.1 ms</td><td>5,054.4 ms</td><td>5,012.6 ms</td><td>145000.0000</td><td>48000.0000</td><td>3000.0000</td><td>723.66 MB</td>
</tr></tbody></table>
</body>
</html>


================================================
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
================================================
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>WeihanLi.Npoi.Benchmark.WorkbookBasicTest-20191108-065532</title>

<style type="text/css">
	table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
	td, th { padding: 6px 13px; border: 1px solid #ddd; }
	tr { background-color: #fff; border-top: 1px solid #ccc; }
	tr:nth-child(even) { background: #f8f8f8; }
</style>
</head>
<body>
<pre><code>
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
</code></pre>
<pre><code>IterationCount=5  LaunchCount=1  WarmupCount=1  
</code></pre>

<table>
<thead><tr><th>        Method</th><th>RowsCount</th><th>Mean</th><th>Error</th><th>StdDev</th><th> Min</th><th> Max</th><th>Median</th><th>Ratio</th><th>RatioSD</th><th>Gen 0</th><th>Gen 1</th><th>Gen 2</th><th>Allocated</th>
</tr>
</thead><tbody><tr><td>NpoiXlsWorkbookInit</td><td>10000</td><td>324.7 ms</td><td>1.583 ms</td><td>0.4110 ms</td><td>324.3 ms</td><td>325.4 ms</td><td>324.6 ms</td><td>1.00</td><td>0.00</td><td>10000.0000</td><td>5000.0000</td><td>2000.0000</td><td>78.6 MB</td>
</tr><tr><td>NpoiXlsxWorkbookInit</td><td>10000</td><td>1,369.0 ms</td><td>73.747 ms</td><td>19.1517 ms</td><td>1,341.3 ms</td><td>1,384.4 ms</td><td>1,381.1 ms</td><td>4.22</td><td>0.06</td><td>57000.0000</td><td>14000.0000</td><td>4000.0000</td><td>306.45 MB</td>
</tr><tr><td>EpplusWorkbookInit</td><td>10000</td><td>552.9 ms</td><td>12.740 ms</td><td>3.3085 ms</td><td>549.7 ms</td><td>557.7 ms</td><td>552.4 ms</td><td>1.70</td><td>0.01</td><td>18000.0000</td><td>7000.0000</td><td>3000.0000</td><td>121.05 MB</td>
</tr><tr><td>NpoiXlsWorkbookInit</td><td>30000</td><td>1,222.4 ms</td><td>33.717 ms</td><td>8.7562 ms</td><td>1,209.0 ms</td><td>1,233.1 ms</td><td>1,222.5 ms</td><td>1.00</td><td>0.00</td><td>29000.0000</td><td>11000.0000</td><td>3000.0000</td><td>235.03 MB</td>
</tr><tr><td>NpoiXlsxWorkbookInit</td><td>30000</td><td>4,226.2 ms</td><td>299.833 ms</td><td>77.8658 ms</td><td>4,109.5 ms</td><td>4,308.6 ms</td><td>4,257.2 ms</td><td>3.46</td><td>0.08</td><td>174000.0000</td><td>34000.0000</td><td>6000.0000</td><td>913.9 MB</td>
</tr><tr><td>EpplusWorkbookInit</td><td>30000</td><td>1,695.4 ms</td><td>31.751 ms</td><td>8.2457 ms</td><td>1,686.3 ms</td><td>1,706.5 ms</td><td>1,694.2 ms</td><td>1.39</td><td>0.02</td><td>48000.0000</td><td>17000.0000</td><td>5000.0000</td><td>358.51 MB</td>
</tr><tr><td>NpoiXlsWorkbookInit</td><td>50000</td><td>2,323.5 ms</td><td>236.041 ms</td><td>61.2990 ms</td><td>2,286.0 ms</td><td>2,431.9 ms</td><td>2,294.2 ms</td><td>1.00</td><td>0.00</td><td>47000.0000</td><td>18000.0000</td><td>4000.0000</td><td>417.1 MB</td>
</tr><tr><td>NpoiXlsxWorkbookInit</td><td>50000</td><td>7,055.2 ms</td><td>279.256 ms</td><td>72.5218 ms</td><td>6,982.8 ms</td><td>7,150.2 ms</td><td>7,027.2 ms</td><td>3.04</td><td>0.10</td><td>288000.0000</td><td>51000.0000</td><td>6000.0000</td><td>1545.32 MB</td>
</tr><tr><td>EpplusWorkbookInit</td><td>50000</td><td>2,806.9 ms</td><td>56.266 ms</td><td>14.6121 ms</td><td>2,792.9 ms</td><td>2,829.1 ms</td><td>2,804.6 ms</td><td>1.21</td><td>0.03</td><td>79000.0000</td><td>27000.0000</td><td>7000.0000</td><td>578.46 MB</td>
</tr><tr><td>NpoiXlsWorkbookInit</td><td>65535</td><td>3,646.8 ms</td><td>131.129 ms</td><td>34.0537 ms</td><td>3,603.0 ms</td><td>3,696.3 ms</td><td>3,642.5 ms</td><td>1.00</td><td>0.00</td><td>61000.0000</td><td>21000.0000</td><td>4000.0000</td><td>504.46 MB</td>
</tr><tr><td>NpoiXlsxWorkbookInit</td><td>65535</td><td>9,295.6 ms</td><td>486.761 ms</td><td>126.4104 ms</td><td>9,163.3 ms</td><td>9,468.6 ms</td><td>9,330.5 ms</td><td>2.55</td><td>0.04</td><td>390000.0000</td><td>67000.0000</td><td>8000.0000</td><td>2048.14 MB</td>
</tr><tr><td>EpplusWorkbookInit</td><td>65535</td><td>3,721.6 ms</td><td>124.945 ms</td><td>32.4478 ms</td><td>3,680.7 ms</td><td>3,766.8 ms</td><td>3,714.1 ms</td><td>1.02</td><td>0.01</td><td>102000.0000</td><td>35000.0000</td><td>8000.0000</td><td>747.85 MB</td>
</tr></tbody></table>
</body>
</html>


================================================
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<TestEntity> testData = new(51200);
    private readonly List<TestStruct> 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<TestEntity> testData = new(51200);
    private byte[] xlsBytes = Array.Empty<byte>(), xlsxBytes = Array.Empty<byte>(), csvBytes = Array.Empty<byte>();

    [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<TestEntity>(csvBytes);
        return list.Count;
    }

    [Benchmark]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public int ImportFromXlsBytesTest()
    {
        var list = ExcelHelper.ToEntityList<TestEntity>(xlsBytes, ExcelFormat.Xls);
        return list.Count;
    }

    [Benchmark]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public int ImportFromXlsxBytesTest()
    {
        var list = ExcelHelper.ToEntityList<TestEntity>(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<WorkbookBasicTest>();
        BenchmarkRunner.Run<ExportExcelTest>();
        BenchmarkRunner.Run<ImportExcelTest>();
    }
}


================================================
FILE: perf/WeihanLi.Npoi.Benchmark/WeihanLi.Npoi.Benchmark.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\src\WeihanLi.Npoi\WeihanLi.Npoi.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="BenchmarkDotNet" />
    <PackageReference Include="EPPlus.Core.Extensions" />
  </ItemGroup>

</Project>


================================================
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]
    [Metho
Download .txt
gitextract_te4pkn3w/

├── .codacy.yml
├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── stale.yml
│   └── workflows/
│       ├── docfx.yml
│       ├── dotnet-format-pr-validation.yml
│       ├── dotnet-format.yml
│       ├── dotnet.yml
│       └── release.yml
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE
├── README.md
├── WeihanLi.Npoi.sln.DotSettings
├── WeihanLi.Npoi.slnx
├── azure-pipelines.yml
├── build/
│   ├── common.props
│   ├── getReleaseVersion.ps1
│   ├── sign.props
│   ├── version.props
│   └── weihanli.snk
├── build.cs
├── docs/
│   ├── ReleaseNotes.md
│   ├── api/
│   │   ├── .gitignore
│   │   └── index.md
│   ├── articles/
│   │   ├── en/
│   │   │   ├── CustomizeStyle.md
│   │   │   ├── GetStarted.md
│   │   │   ├── InputOutputFormatter.md
│   │   │   ├── MultiSheets.md
│   │   │   ├── ShadowProperty.md
│   │   │   └── TemplateExport.md
│   │   ├── intro.md
│   │   ├── toc.yml
│   │   └── zh/
│   │       ├── CustomizeStyle.md
│   │       ├── GetStarted.md
│   │       ├── InputOutputFormatter.md
│   │       ├── MultiSheets.md
│   │       ├── ShadowProperty.md
│   │       └── TemplateExport.md
│   ├── docfx.json
│   └── toc.yml
├── global.json
├── nuget.config
├── perf/
│   └── WeihanLi.Npoi.Benchmark/
│       ├── BenchmarkDotNet.Artifacts/
│       │   └── results/
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report.csv
│       │       ├── WeihanLi.Npoi.Benchmark.ExportExcelTest-report.html
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report.csv
│       │       ├── WeihanLi.Npoi.Benchmark.ImportExcelTest-report.html
│       │       ├── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report-github.md
│       │       ├── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.csv
│       │       └── WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.html
│       ├── ExportExcelTest.cs
│       ├── ImportExcelTest.cs
│       ├── Program.cs
│       ├── WeihanLi.Npoi.Benchmark.csproj
│       └── WorkbookBasicTest.cs
├── samples/
│   ├── Directory.Build.props
│   ├── DotNetCoreSample/
│   │   ├── DotNetCoreSample.csproj
│   │   ├── ImportImageTestModel.cs
│   │   ├── IssueSamples.cs
│   │   ├── ProductPriceMapping.cs
│   │   ├── Program.cs
│   │   ├── Templates/
│   │   │   └── testTemplate.xlsx
│   │   └── TestModel.cs
│   └── run-file-samples/
│       ├── issue-169.cs
│       └── style-customization-sample.cs
├── src/
│   ├── Directory.Build.props
│   └── WeihanLi.Npoi/
│       ├── Abstract/
│       │   ├── ICell.cs
│       │   ├── IRow.cs
│       │   ├── ISheet.cs
│       │   ├── IWorkbook.cs
│       │   └── NPOIWorkbook.cs
│       ├── Attributes/
│       │   ├── ColumnAttribute.cs
│       │   ├── FilterAttribute.cs
│       │   ├── FreezeAttribute.cs
│       │   └── SheetAttribute.cs
│       ├── CellPosition.cs
│       ├── Compat.cs
│       ├── ConfigurationExtensions.cs
│       ├── Configurations/
│       │   ├── CsvOptions.cs
│       │   ├── ExcelConfiguration.cs
│       │   ├── IExcelConfiguration.cs
│       │   ├── IPropertyConfiguration.cs
│       │   └── PropertyConfiguration.cs
│       ├── CsvHelper.cs
│       ├── ExcelFormat.cs
│       ├── ExcelHelper.cs
│       ├── FakePropertyInfo.cs
│       ├── FluentSettings.cs
│       ├── IMappingProfile.cs
│       ├── InternalCache.cs
│       ├── InternalConstants.cs
│       ├── InternalExtensions.cs
│       ├── InternalHelper.cs
│       ├── NpoiCollection.cs
│       ├── NpoiExtensions.cs
│       ├── NpoiHelper.cs
│       ├── NpoiTemplateHelper.cs
│       ├── Resource.Designer.cs
│       ├── Resource.resx
│       ├── Settings/
│       │   ├── ExcelSetting.cs
│       │   ├── FilterSetting.cs
│       │   ├── FreezeSetting.cs
│       │   └── SheetSetting.cs
│       ├── TemplateHelper.cs
│       └── WeihanLi.Npoi.csproj
└── test/
    └── WeihanLi.Npoi.Test/
        ├── CsvTest.cs
        ├── ExcelFormatData.cs
        ├── ExcelTest.cs
        ├── Extensions.cs
        ├── MappingProfiles/
        │   └── NoticeProfile.cs
        ├── Models/
        │   ├── Job.cs
        │   ├── Notice.cs
        │   └── OrderTestModels.cs
        ├── Startup.cs
        ├── TestData/
        │   ├── EmptyColumns/
        │   │   ├── emptyColumns.csv
        │   │   ├── emptyColumns.xls
        │   │   └── emptyColumns.xlsx
        │   ├── EmptyRows/
        │   │   ├── emptyRows.xls
        │   │   └── emptyRows.xlsx
        │   └── NonStringColumns/
        │       ├── nonStringColumns.csv
        │       ├── nonStringColumns.xls
        │       └── nonStringColumns.xlsx
        └── WeihanLi.Npoi.Test.csproj
Download .txt
SYMBOL INDEX (477 symbols across 57 files)

FILE: perf/WeihanLi.Npoi.Benchmark/ExportExcelTest.cs
  class ExportExcelTest (line 11) | [SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
    class TestEntity (line 16) | private class TestEntity
    type TestStruct (line 40) | private struct TestStruct
    method GlobalSetup (line 70) | [GlobalSetup]
    method GlobalCleanup (line 91) | [GlobalCleanup]
    method ExportToCsvBytesTest (line 98) | [Benchmark]
    method NpoiExportToXlsBytesTest (line 105) | [Benchmark]
    method NpoiExportToXlsxBytesTest (line 112) | [Benchmark]
    method EpplusExportToBytesTest (line 119) | [Benchmark]
    method StructExportToCsvBytesTest (line 126) | [Benchmark]
    method NpoiStructExportToXlsBytesTest (line 133) | [Benchmark]
    method NpoiStructExportToXlsxBytesTest (line 140) | [Benchmark]
    method EpplusStructExportToBytesTest (line 147) | [Benchmark]

FILE: perf/WeihanLi.Npoi.Benchmark/ImportExcelTest.cs
  class ImportExcelTest (line 9) | [SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
    class TestEntity (line 14) | private class TestEntity
    method GlobalSetup (line 37) | [GlobalSetup]
    method GlobalCleanup (line 55) | [GlobalCleanup]
    method ImportFromCsvBytesTest (line 62) | [Benchmark]
    method ImportFromXlsBytesTest (line 70) | [Benchmark]
    method ImportFromXlsxBytesTest (line 78) | [Benchmark]

FILE: perf/WeihanLi.Npoi.Benchmark/Program.cs
  class Program (line 8) | public class Program
    method Main (line 10) | public static void Main(string[] args)

FILE: perf/WeihanLi.Npoi.Benchmark/WorkbookBasicTest.cs
  class WorkbookBasicTest (line 10) | [SimpleJob(launchCount: 1, warmupCount: 1, iterationCount: 5)]
    method NpoiXlsWorkbookInit (line 20) | [Benchmark(Baseline = true)]
    method NpoiXlsxWorkbookInit (line 40) | [Benchmark]
    method EpplusWorkbookInit (line 61) | [Benchmark]

FILE: samples/DotNetCoreSample/ImportImageTestModel.cs
  class ImportImageTestModel (line 6) | internal class ImportImageTestModel

FILE: samples/DotNetCoreSample/IssueSamples.cs
  class IssueSamples (line 6) | public static partial class IssueSamples
    method Issue169Sample (line 8) | public static void Issue169Sample()
  class Issue169Dto (line 25) | [Sheet(SheetIndex = 0, StartRowIndex = 6)]

FILE: samples/DotNetCoreSample/ProductPriceMapping.cs
  class ProductPriceMapping (line 8) | internal class ProductPriceMapping

FILE: samples/DotNetCoreSample/Program.cs
  class TestEntityExcelMappingProfile (line 244) | class TestEntityExcelMappingProfile : IMappingProfile<TestEntity>
    method Configure (line 246) | public void Configure(IExcelConfiguration<TestEntity> setting)
  class BaseEntity (line 338) | internal abstract class BaseEntity
  class TestEntity (line 343) | internal class TestEntity : BaseEntity
  type EntityType (line 365) | public enum EntityType
  class TestEntity2 (line 371) | [Sheet(SheetIndex = 0, SheetName = "TestSheet", AutoColumnWidthEnabled =...
  class ExcelExportDTO (line 387) | public class ExcelExportDTO
  class SurveyImportDto (line 399) | internal sealed class SurveyImportDto

FILE: samples/DotNetCoreSample/TestModel.cs
  class ppDto (line 6) | [Sheet(SheetIndex = 0, SheetName = "Abc", StartRowIndex = 1, EndRowIndex...

FILE: samples/run-file-samples/issue-169.cs
  class MaterielDetailDto (line 14) | [Sheet(SheetIndex = 0, StartRowIndex = 6)]

FILE: samples/run-file-samples/style-customization-sample.cs
  class StyledEntity (line 17) | public class StyledEntity
  class StyledEntityProfile (line 26) | public class StyledEntityProfile : IMappingProfile<StyledEntity>
    method Configure (line 28) | public void Configure(IExcelConfiguration<StyledEntity> configuration)

FILE: src/WeihanLi.Npoi/Abstract/ICell.cs
  type ICell (line 6) | internal interface ICell
  type CellType (line 13) | internal enum CellType

FILE: src/WeihanLi.Npoi/Abstract/IRow.cs
  type IRow (line 6) | internal interface IRow
    method GetCell (line 30) | ICell? GetCell(int cellIndex);
    method CreateCell (line 40) | ICell CreateCell(int cellIndex);

FILE: src/WeihanLi.Npoi/Abstract/ISheet.cs
  type ISheet (line 6) | internal interface ISheet
    method GetRow (line 20) | IRow? GetRow(int rowIndex);
    method CreateRow (line 22) | IRow CreateRow(int rowIndex);
    method SetColumnWidth (line 24) | void SetColumnWidth(int columnIndex, int width);
    method AutoSizeColumn (line 26) | void AutoSizeColumn(int columnIndex);
    method CreateFreezePane (line 28) | void CreateFreezePane(int colSplit, int rowSplit, int leftMostCol, int...
    method SetAutoFilter (line 30) | void SetAutoFilter(int firstRowIndex, int lastRowIndex, int firstColum...
    method ShiftRows (line 32) | void ShiftRows(int startRow, int endRow, int n);
    method CopyRow (line 34) | IRow CopyRow(int sourceIndex, int targetIndex);
    method RemoveRow (line 36) | void RemoveRow(IRow row);

FILE: src/WeihanLi.Npoi/Abstract/IWorkbook.cs
  type IWorkbook (line 6) | internal interface IWorkbook
    method GetSheet (line 10) | ISheet? GetSheet(int sheetIndex);
    method CreateSheet (line 12) | ISheet CreateSheet(string sheetName);
    method ToBytes (line 14) | byte[] ToBytes();

FILE: src/WeihanLi.Npoi/Abstract/NPOIWorkbook.cs
  class NPOIWorkbook (line 12) | internal sealed class NPOIWorkbook : IWorkbook
    method NPOIWorkbook (line 20) | public NPOIWorkbook(NModel.IWorkbook workbook) => _workbook = workbook;
    method GetSheet (line 30) | public ISheet GetSheet(int sheetIndex) => new NPOISheet(_workbook.GetS...
    method CreateSheet (line 35) | public ISheet CreateSheet(string sheetName) => new NPOISheet(_workbook...
    method ToBytes (line 40) | public byte[] ToBytes() => _workbook.ToExcelBytes();
  class NPOISheet (line 46) | internal sealed class NPOISheet : ISheet
    method NPOISheet (line 53) | public NPOISheet(NModel.ISheet sheet) => _sheet = sheet;
    method GetRow (line 68) | public IRow? GetRow(int rowIndex)
    method CreateRow (line 82) | public IRow CreateRow(int rowIndex) => new NPOIRow(_sheet.CreateRow(ro...
    method SetColumnWidth (line 87) | public void SetColumnWidth(int columnIndex, int width) => _sheet.SetCo...
    method AutoSizeColumn (line 92) | public void AutoSizeColumn(int columnIndex) => _sheet.AutoSizeColumn(c...
    method CreateFreezePane (line 97) | public void CreateFreezePane(int colSplit, int rowSplit, int leftMostC...
    method SetAutoFilter (line 103) | public void SetAutoFilter(int firstRowIndex, int lastRowIndex, int fir...
    method ShiftRows (line 109) | public void ShiftRows(int startRow, int endRow, int n) => _sheet.Shift...
    method CopyRow (line 114) | public IRow CopyRow(int sourceIndex, int targetIndex) => new NPOIRow(_...
    method RemoveRow (line 119) | public void RemoveRow(IRow row) => _sheet.RemoveRow(row.UnderlyingValu...
  class NPOIRow (line 125) | internal sealed class NPOIRow : IRow
    method NPOIRow (line 132) | public NPOIRow(NModel.IRow row) => _row = row;
    method GetCell (line 152) | public ICell? GetCell(int cellIndex)
    method CreateCell (line 166) | public ICell CreateCell(int cellIndex) => new NPOICell(_row.CreateCell...
  class NPOICell (line 177) | internal sealed class NPOICell : ICell
    method NPOICell (line 184) | public NPOICell(NModel.ICell cell) => _cell = cell;

FILE: src/WeihanLi.Npoi/Attributes/ColumnAttribute.cs
  class ColumnAttribute (line 11) | [AttributeUsage(AttributeTargets.Property)]
    method ColumnAttribute (line 17) | public ColumnAttribute() => PropertyConfiguration = new PropertyConfig...
    method ColumnAttribute (line 23) | public ColumnAttribute(int index) => PropertyConfiguration = new Prope...
    method ColumnAttribute (line 29) | public ColumnAttribute(string title) => PropertyConfiguration = new Pr...

FILE: src/WeihanLi.Npoi/Attributes/FilterAttribute.cs
  class FilterAttribute (line 11) | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    method FilterAttribute (line 17) | public FilterAttribute(int firstColumn) : this(firstColumn, null)
    method FilterAttribute (line 26) | public FilterAttribute(int firstColumn, int? lastColumn) =>

FILE: src/WeihanLi.Npoi/Attributes/FreezeAttribute.cs
  class FreezeAttribute (line 11) | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    method FreezeAttribute (line 17) | public FreezeAttribute(int colSplit, int rowSplit) : this(colSplit, ro...
    method FreezeAttribute (line 28) | public FreezeAttribute(int colSplit, int rowSplit, int leftmostColumn,...

FILE: src/WeihanLi.Npoi/Attributes/SheetAttribute.cs
  class SheetAttribute (line 11) | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    method SheetAttribute (line 21) | public SheetAttribute() => SheetSetting = new SheetSetting();

FILE: src/WeihanLi.Npoi/CellPosition.cs
  type CellPosition (line 11) | public readonly record struct CellPosition(int Row, int Column);

FILE: src/WeihanLi.Npoi/Compat.cs
  class IsExternalInit (line 7) | internal sealed class IsExternalInit;

FILE: src/WeihanLi.Npoi/ConfigurationExtensions.cs
  class ConfigurationExtensions (line 12) | public static class ConfigurationExtensions
    method HasSheetConfiguration (line 21) | public static IExcelConfiguration HasSheetConfiguration(this IExcelCon...
    method HasSheetConfiguration (line 32) | public static IExcelConfiguration HasSheetConfiguration(this IExcelCon...
    method HasSheetConfiguration (line 47) | public static IExcelConfiguration HasSheetConfiguration(this IExcelCon...
    method HasSheetConfiguration (line 64) | public static IExcelConfiguration HasSheetConfiguration(this IExcelCon...
    method HasAuthor (line 80) | public static IExcelConfiguration HasAuthor(this IExcelConfiguration c...
    method HasTitle (line 89) | public static IExcelConfiguration HasTitle(this IExcelConfiguration co...
    method HasDescription (line 98) | public static IExcelConfiguration HasDescription(this IExcelConfigurat...
    method HasSubject (line 107) | public static IExcelConfiguration HasSubject(this IExcelConfiguration ...
    method HasCompany (line 116) | public static IExcelConfiguration HasCompany(this IExcelConfiguration ...
    method HasCategory (line 125) | public static IExcelConfiguration HasCategory(this IExcelConfiguration...
    method WithValidator (line 135) | public static IExcelConfiguration<TEntity> WithValidator<TEntity>(this...
    method Property (line 148) | public static IPropertyConfiguration<TEntity, string> Property<TEntity>(
    method HasColumnOutputFormatter (line 160) | public static IPropertyConfiguration<TEntity, TProperty> HasColumnOutp...

FILE: src/WeihanLi.Npoi/Configurations/CsvOptions.cs
  class CsvOptions (line 11) | public sealed class CsvOptions
    method CsvOptions (line 51) | public CsvOptions()

FILE: src/WeihanLi.Npoi/Configurations/ExcelConfiguration.cs
  class ExcelConfiguration (line 13) | internal abstract class ExcelConfiguration : IExcelConfiguration
    method HasExcelSetting (line 51) | public IExcelConfiguration HasExcelSetting(Action<ExcelSetting> config...
    method HasSheetSetting (line 69) | public IExcelConfiguration HasSheetSetting(Action<SheetSetting> config...
    method HasFreezePane (line 98) | public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit)
    method HasFreezePane (line 107) | public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, i...
    method HasFilter (line 120) | public IExcelConfiguration HasFilter(int firstColumn) => HasFilter(fir...
    method HasFilter (line 125) | public IExcelConfiguration HasFilter(int firstColumn, int? lastColumn)
    method WithValidator (line 154) | public IExcelConfiguration<TEntity> WithValidator(IValidator? validator)
    method WithDataFilter (line 163) | public IExcelConfiguration<TEntity> WithDataFilter(Func<TEntity?, bool...
    method WithPostImportAction (line 169) | public IExcelConfiguration<TEntity> WithPostImportAction(Action<TEntit...
    method WithPropertyComparer (line 178) | public IExcelConfiguration<TEntity> WithPropertyComparer(IComparer<Pro...
    method Property (line 191) | public IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(
    method Property (line 210) | public IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(...
  class ExcelConfiguration (line 134) | internal sealed class ExcelConfiguration<TEntity> : ExcelConfiguration, ...
    method HasExcelSetting (line 51) | public IExcelConfiguration HasExcelSetting(Action<ExcelSetting> config...
    method HasSheetSetting (line 69) | public IExcelConfiguration HasSheetSetting(Action<SheetSetting> config...
    method HasFreezePane (line 98) | public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit)
    method HasFreezePane (line 107) | public IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, i...
    method HasFilter (line 120) | public IExcelConfiguration HasFilter(int firstColumn) => HasFilter(fir...
    method HasFilter (line 125) | public IExcelConfiguration HasFilter(int firstColumn, int? lastColumn)
    method WithValidator (line 154) | public IExcelConfiguration<TEntity> WithValidator(IValidator? validator)
    method WithDataFilter (line 163) | public IExcelConfiguration<TEntity> WithDataFilter(Func<TEntity?, bool...
    method WithPostImportAction (line 169) | public IExcelConfiguration<TEntity> WithPostImportAction(Action<TEntit...
    method WithPropertyComparer (line 178) | public IExcelConfiguration<TEntity> WithPropertyComparer(IComparer<Pro...
    method Property (line 191) | public IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(
    method Property (line 210) | public IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(...

FILE: src/WeihanLi.Npoi/Configurations/IExcelConfiguration.cs
  type IExcelConfiguration (line 14) | public interface IExcelConfiguration
    method HasSheetSetting (line 22) | IExcelConfiguration HasSheetSetting(Action<SheetSetting> configAction,...
    method HasExcelSetting (line 29) | IExcelConfiguration HasExcelSetting(Action<ExcelSetting> configAction);
    method HasFreezePane (line 38) | IExcelConfiguration HasFreezePane(int colSplit, int rowSplit);
    method HasFreezePane (line 49) | IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, int left...
    method HasFilter (line 56) | IExcelConfiguration HasFilter(int firstColumn);
    method HasFilter (line 64) | IExcelConfiguration HasFilter(int firstColumn, int? lastColumn);
    method WithValidator (line 78) | IExcelConfiguration<TEntity> WithValidator(IValidator? validator);
    method WithDataFilter (line 85) | IExcelConfiguration<TEntity> WithDataFilter(Func<TEntity?, bool>? data...
    method WithPostImportAction (line 92) | IExcelConfiguration<TEntity> WithPostImportAction(Action<TEntity?, int...
    method WithPropertyComparer (line 99) | IExcelConfiguration<TEntity> WithPropertyComparer(IComparer<PropertyIn...
    method Property (line 107) | IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(
    method Property (line 116) | IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(string ...
  type IExcelConfiguration (line 71) | public interface IExcelConfiguration<TEntity> : IExcelConfiguration
    method HasSheetSetting (line 22) | IExcelConfiguration HasSheetSetting(Action<SheetSetting> configAction,...
    method HasExcelSetting (line 29) | IExcelConfiguration HasExcelSetting(Action<ExcelSetting> configAction);
    method HasFreezePane (line 38) | IExcelConfiguration HasFreezePane(int colSplit, int rowSplit);
    method HasFreezePane (line 49) | IExcelConfiguration HasFreezePane(int colSplit, int rowSplit, int left...
    method HasFilter (line 56) | IExcelConfiguration HasFilter(int firstColumn);
    method HasFilter (line 64) | IExcelConfiguration HasFilter(int firstColumn, int? lastColumn);
    method WithValidator (line 78) | IExcelConfiguration<TEntity> WithValidator(IValidator? validator);
    method WithDataFilter (line 85) | IExcelConfiguration<TEntity> WithDataFilter(Func<TEntity?, bool>? data...
    method WithPostImportAction (line 92) | IExcelConfiguration<TEntity> WithPostImportAction(Action<TEntity?, int...
    method WithPropertyComparer (line 99) | IExcelConfiguration<TEntity> WithPropertyComparer(IComparer<PropertyIn...
    method Property (line 107) | IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(
    method Property (line 116) | IPropertyConfiguration<TEntity, TProperty> Property<TProperty>(string ...

FILE: src/WeihanLi.Npoi/Configurations/IPropertyConfiguration.cs
  type IPropertyConfiguration (line 11) | public interface IPropertyConfiguration;
    method HasColumnIndex (line 25) | IPropertyConfiguration<TEntity, TProperty> HasColumnIndex(int index);
    method HasColumnWidth (line 32) | IPropertyConfiguration<TEntity, TProperty> HasColumnWidth(int width);
    method HasColumnTitle (line 39) | IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(string title);
    method HasColumnFormatter (line 46) | IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(string? ...
    method Ignored (line 52) | IPropertyConfiguration<TEntity, TProperty> Ignored(bool ignored = true);
    method HasCellReader (line 60) | IPropertyConfiguration<TEntity, TProperty> HasCellReader(
    method HasColumnInputFormatter (line 68) | IPropertyConfiguration<TEntity, TProperty> HasColumnInputFormatter(Fun...
    method HasOutputFormatter (line 75) | IPropertyConfiguration<TEntity, TProperty> HasOutputFormatter(
    method HasInputFormatter (line 83) | IPropertyConfiguration<TEntity, TProperty> HasInputFormatter(
  type IPropertyConfiguration (line 18) | public interface IPropertyConfiguration<out TEntity, TProperty> : IPrope...
    method HasColumnIndex (line 25) | IPropertyConfiguration<TEntity, TProperty> HasColumnIndex(int index);
    method HasColumnWidth (line 32) | IPropertyConfiguration<TEntity, TProperty> HasColumnWidth(int width);
    method HasColumnTitle (line 39) | IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(string title);
    method HasColumnFormatter (line 46) | IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(string? ...
    method Ignored (line 52) | IPropertyConfiguration<TEntity, TProperty> Ignored(bool ignored = true);
    method HasCellReader (line 60) | IPropertyConfiguration<TEntity, TProperty> HasCellReader(
    method HasColumnInputFormatter (line 68) | IPropertyConfiguration<TEntity, TProperty> HasColumnInputFormatter(Fun...
    method HasOutputFormatter (line 75) | IPropertyConfiguration<TEntity, TProperty> HasOutputFormatter(
    method HasInputFormatter (line 83) | IPropertyConfiguration<TEntity, TProperty> HasInputFormatter(

FILE: src/WeihanLi.Npoi/Configurations/PropertyConfiguration.cs
  class PropertyConfiguration (line 10) | internal class PropertyConfiguration : IPropertyConfiguration
    method PropertyConfiguration (line 52) | public PropertyConfiguration(PropertyInfo propertyInfo)
    method HasColumnIndex (line 62) | public IPropertyConfiguration<TEntity, TProperty> HasColumnIndex(int i...
    method HasColumnTitle (line 75) | public IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(strin...
    method HasColumnWidth (line 84) | public IPropertyConfiguration<TEntity, TProperty> HasColumnWidth(int w...
    method HasColumnFormatter (line 93) | public IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(s...
    method Ignored (line 102) | public IPropertyConfiguration<TEntity, TProperty> Ignored(bool ignored...
    method HasCellReader (line 111) | public IPropertyConfiguration<TEntity, TProperty> HasCellReader(Func<I...
    method HasOutputFormatter (line 120) | public IPropertyConfiguration<TEntity, TProperty> HasOutputFormatter(
    method HasInputFormatter (line 130) | public IPropertyConfiguration<TEntity, TProperty> HasInputFormatter(
    method HasColumnInputFormatter (line 140) | public IPropertyConfiguration<TEntity, TProperty> HasColumnInputFormat...
  class PropertyConfiguration (line 43) | internal sealed class PropertyConfiguration<TEntity, TProperty> : Proper...
    method PropertyConfiguration (line 52) | public PropertyConfiguration(PropertyInfo propertyInfo)
    method HasColumnIndex (line 62) | public IPropertyConfiguration<TEntity, TProperty> HasColumnIndex(int i...
    method HasColumnTitle (line 75) | public IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(strin...
    method HasColumnWidth (line 84) | public IPropertyConfiguration<TEntity, TProperty> HasColumnWidth(int w...
    method HasColumnFormatter (line 93) | public IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(s...
    method Ignored (line 102) | public IPropertyConfiguration<TEntity, TProperty> Ignored(bool ignored...
    method HasCellReader (line 111) | public IPropertyConfiguration<TEntity, TProperty> HasCellReader(Func<I...
    method HasOutputFormatter (line 120) | public IPropertyConfiguration<TEntity, TProperty> HasOutputFormatter(
    method HasInputFormatter (line 130) | public IPropertyConfiguration<TEntity, TProperty> HasInputFormatter(
    method HasColumnInputFormatter (line 140) | public IPropertyConfiguration<TEntity, TProperty> HasColumnInputFormat...

FILE: src/WeihanLi.Npoi/CsvHelper.cs
  class CsvHelper (line 18) | public static class CsvHelper
    method ToCsvFile (line 38) | public static bool ToCsvFile(this DataTable dt, string filePath) => To...
    method ToCsvFile (line 47) | public static bool ToCsvFile(this DataTable dataTable, string filePath...
    method ToCsvFile (line 62) | public static bool ToCsvFile(this DataTable dataTable, string filePath...
    method ToCsvBytes (line 93) | public static byte[] ToCsvBytes(this DataTable dt) => ToCsvBytes(dt, t...
    method ToCsvBytes (line 101) | public static byte[] ToCsvBytes(this DataTable dataTable, bool include...
    method ToCsvBytes (line 110) | public static byte[] ToCsvBytes(this DataTable dataTable, CsvOptions c...
    method ToDataTable (line 118) | public static DataTable ToDataTable(byte[] csvBytes)
    method ToDataTable (line 127) | public static DataTable ToDataTable(byte[] csvBytes, CsvOptions csvOpt...
    method ToDataTable (line 143) | public static DataTable ToDataTable(Stream stream) => ToDataTable(stre...
    method ToDataTable (line 152) | public static DataTable ToDataTable(Stream stream, CsvOptions csvOptions)
    method ToDataTable (line 206) | public static DataTable ToDataTable(string filePath)
    method ToEntityList (line 227) | public static List<TEntity?> ToEntityList<TEntity>(string filePath)
    method ToEntityList (line 238) | public static List<TEntity?> ToEntityList<TEntity>(string filePath, Cs...
    method ToEntities (line 259) | public static IEnumerable<TEntity?> ToEntities<TEntity>(string filePat...
    method ToEntityList (line 280) | public static List<TEntity?> ToEntityList<TEntity>(byte[] csvBytes)
    method ToEntityList (line 290) | public static List<TEntity?> ToEntityList<TEntity>(byte[] csvBytes, Cs...
    method ToEntities (line 304) | public static IEnumerable<TEntity?> ToEntities<TEntity>(byte[] csvByte...
    method ToEntityList (line 320) | public static List<TEntity?> ToEntityList<TEntity>(Stream csvStream)
    method ToEntityList (line 330) | public static List<TEntity?> ToEntityList<TEntity>(Stream csvStream, C...
    method ToEntities (line 344) | public static IEnumerable<TEntity?> ToEntities<TEntity>(Stream csvStre...
    method GetEntityList (line 376) | public static List<TEntity?> GetEntityList<TEntity>(string csvText, Cs...
    method GetEntities (line 386) | public static IEnumerable<TEntity?> GetEntities<TEntity>(string csvTex...
    method GetEntityList (line 416) | public static List<TEntity?> GetEntityList<TEntity>(IEnumerable<string...
    method GetEntities (line 428) | public static IEnumerable<TEntity?> GetEntities<TEntity>(IEnumerable<s...
    method ParseLine (line 602) | public static IReadOnlyList<string> ParseLine(string line) => ParseLin...
    method ParseLine (line 612) | public static IReadOnlyList<string> ParseLine(string line, CsvOptions ...
    method ToCsvFile (line 695) | public static bool ToCsvFile<TEntity>(this IEnumerable<TEntity> entiti...
    method ToCsvFile (line 706) | public static bool ToCsvFile<TEntity>(this IEnumerable<TEntity> entiti...
    method ToCsvFile (line 723) | public static bool ToCsvFile<TEntity>(this IEnumerable<TEntity> entiti...
    method ToCsvFileAsync (line 759) | public static async Task<bool> ToCsvFileAsync<TEntity>(this IEnumerabl...
    method ToCsvBytes (line 793) | public static byte[] ToCsvBytes<TEntity>(this IEnumerable<TEntity> ent...
    method ToCsvBytes (line 802) | public static byte[] ToCsvBytes<TEntity>(this IEnumerable<TEntity> ent...
    method ToCsvBytes (line 812) | public static byte[] ToCsvBytes<TEntity>(this IEnumerable<TEntity> ent...
    method GetCsvText (line 822) | public static string GetCsvText<TEntity>(this IEnumerable<TEntity> ent...
    method GetCsvText (line 837) | public static string GetCsvText<TEntity>(this IEnumerable<TEntity> ent...
    method GetCsvLines (line 850) | public static IEnumerable<string> GetCsvLines<TEntity>(this IEnumerabl...
    method GetCsvText (line 934) | public static string GetCsvText(this DataTable? dataTable, bool includ...
    method GetCsvText (line 950) | public static string GetCsvText(this DataTable? dataTable, CsvOptions ...

FILE: src/WeihanLi.Npoi/ExcelFormat.cs
  type ExcelFormat (line 9) | public enum ExcelFormat : byte

FILE: src/WeihanLi.Npoi/ExcelHelper.cs
  class ExcelHelper (line 20) | public static class ExcelHelper
    method ValidateExcelFilePath (line 49) | private static bool ValidateExcelFilePath(string excelPath, out string...
    method LoadExcel (line 78) | public static IWorkbook LoadExcel(string excelPath)
    method LoadExcel (line 96) | public static IWorkbook LoadExcel(byte[] excelBytes) => LoadExcel(exce...
    method LoadExcel (line 104) | public static IWorkbook LoadExcel(byte[] excelBytes, ExcelFormat excel...
    method LoadExcel (line 120) | public static IWorkbook LoadExcel(Stream excelStream) => LoadExcel(exc...
    method LoadExcel (line 128) | public static IWorkbook LoadExcel(Stream excelStream, ExcelFormat exce...
    method PrepareWorkbook (line 147) | public static IWorkbook PrepareWorkbook(string excelPath) => PrepareWo...
    method PrepareWorkbook (line 155) | public static IWorkbook PrepareWorkbook(string excelPath, ExcelSetting...
    method PrepareWorkbook (line 171) | public static IWorkbook PrepareWorkbook(ExcelFormat excelFormat, Excel...
    method PrepareWorkbook (line 178) | public static IWorkbook PrepareWorkbook() => PrepareWorkbook(true);
    method PrepareWorkbook (line 185) | public static IWorkbook PrepareWorkbook(ExcelFormat excelFormat) =>
    method PrepareWorkbook (line 193) | public static IWorkbook PrepareWorkbook(bool isXlsx) => PrepareWorkboo...
    method PrepareWorkbook (line 201) | public static IWorkbook PrepareWorkbook(bool isXlsx, ExcelSetting? exc...
    method ToEntityList (line 252) | public static List<TEntity?> ToEntityList<TEntity>(byte[] excelBytes) ...
    method ToEntityList (line 262) | public static List<TEntity?> ToEntityList<TEntity>(byte[] excelBytes, ...
    method ToEntityList (line 273) | public static List<TEntity?> ToEntityList<TEntity>(byte[] excelBytes, ...
    method ToEntityList (line 284) | public static List<TEntity?> ToEntityList<TEntity>(byte[] excelBytes, ...
    method ToEntities (line 299) | public static IEnumerable<TEntity?> ToEntities<TEntity>(byte[] excelBy...
    method ToEntityListWithValidationResult (line 318) | public static (List<TEntity?> EntityList, Dictionary<int, ValidationRe...
    method ToEntityList (line 336) | public static List<TEntity?> ToEntityList<TEntity>(Stream excelStream)...
    method ToEntityList (line 346) | public static List<TEntity?> ToEntityList<TEntity>(Stream excelStream,...
    method ToEntityList (line 357) | public static List<TEntity?> ToEntityList<TEntity>(Stream excelStream,...
    method ToEntityList (line 369) | public static List<TEntity?> ToEntityList<TEntity>(Stream excelStream,...
    method ToEntities (line 384) | public static IEnumerable<TEntity?> ToEntities<TEntity>(Stream excelSt...
    method ToEntityListWithValidationResult (line 403) | public static (List<TEntity?> EntityList, Dictionary<int, ValidationRe...
    method ToEntityList (line 419) | public static List<TEntity?> ToEntityList<TEntity>(string excelPath) w...
    method ToEntityList (line 429) | public static List<TEntity?> ToEntityList<TEntity>(string excelPath, i...
    method ToEntities (line 442) | public static IEnumerable<TEntity?> ToEntities<TEntity>(string excelPa...
    method ToEntityListWithValidationResult (line 459) | public static (List<TEntity?> EntityList, Dictionary<int, ValidationRe...
    method ToDataTable (line 473) | public static DataTable ToDataTable<TEntity>(string excelPath) where T...
    method ToDataTable (line 483) | public static DataTable ToDataTable<TEntity>(string excelPath, int she...
    method ToDataTable (line 491) | public static DataTable ToDataTable(string excelPath) => ToDataTable(e...
    method ToDataTable (line 499) | public static DataTable ToDataTable(string excelPath, int sheetIndex) =>
    method ToDataTable (line 511) | public static DataTable ToDataTable(string excelPath, int sheetIndex, ...
    method ToDataTable (line 532) | public static DataTable ToDataTable(byte[] excelBytes, ExcelFormat exc...
    method ToDataTable (line 545) | public static DataTable ToDataTable(byte[] excelBytes, ExcelFormat exc...
    method ToDataTable (line 559) | public static DataTable ToDataTable(byte[] excelBytes, ExcelFormat exc...
    method ToDataSet (line 577) | public static DataSet ToDataSet(string excelPath) => ToDataSet(excelPa...
    method ToDataSet (line 585) | public static DataSet ToDataSet(string excelPath, int headerRowIndex)

FILE: src/WeihanLi.Npoi/FakePropertyInfo.cs
  class FakePropertyInfo (line 11) | internal sealed class FakePropertyInfo : PropertyInfo
    method FakePropertyInfo (line 16) | public FakePropertyInfo(Type entityType, Type propertyType, string pro...
    method GetGetMethod (line 37) | public override MethodInfo GetGetMethod(bool nonPublic) => _getValueFu...
    method GetSetMethod (line 39) | public override MethodInfo GetSetMethod(bool nonPublic) => null;
    method ToString (line 41) | public override string ToString() => $"{PropertyType.Name}, {Name}";
    method GetCustomAttributes (line 43) | public override object[] GetCustomAttributes(bool inherit) => throw ne...
    method GetCustomAttributes (line 45) | public override object[] GetCustomAttributes(Type attributeType, bool ...
    method IsDefined (line 48) | public override bool IsDefined(Type attributeType, bool inherit) => th...
    method GetAccessors (line 50) | public override MethodInfo[] GetAccessors(bool nonPublic) => throw new...
    method GetIndexParameters (line 52) | public override ParameterInfo[] GetIndexParameters() => throw new NotS...
    method GetValue (line 54) | public override object GetValue(object obj, BindingFlags invokeAttr, B...
    method SetValue (line 57) | public override void SetValue(object obj, object value, BindingFlags i...

FILE: src/WeihanLi.Npoi/FluentSettings.cs
  class FluentSettings (line 15) | public static class FluentSettings
    method For (line 25) | public static IExcelConfiguration<TEntity> For<TEntity>() =>
    method LoadMappingProfiles (line 32) | public static void LoadMappingProfiles(params Assembly[] assemblies)
    method LoadMappingProfiles (line 47) | public static void LoadMappingProfiles(params Type[] types)
    method LoadMappingProfile (line 64) | public static void LoadMappingProfile<TEntity, TMappingProfile>()
    method LoadMappingProfile (line 77) | public static void LoadMappingProfile<TEntity, TMappingProfile>(TMappi...
    method LoadMappingProfile (line 87) | public static void LoadMappingProfile<TMappingProfile>() where TMappin...
    method LoadMappingProfile (line 94) | private static void LoadMappingProfile<TMappingProfile>(TMappingProfil...

FILE: src/WeihanLi.Npoi/IMappingProfile.cs
  type IMappingProfile (line 11) | public interface IMappingProfile;
    method Configure (line 23) | void Configure(IExcelConfiguration<T> configuration);
  type IMappingProfile (line 17) | public interface IMappingProfile<T> : IMappingProfile
    method Configure (line 23) | void Configure(IExcelConfiguration<T> configuration);

FILE: src/WeihanLi.Npoi/InternalCache.cs
  class InternalCache (line 10) | internal static class InternalCache

FILE: src/WeihanLi.Npoi/InternalConstants.cs
  class InternalConstants (line 6) | internal static class InternalConstants

FILE: src/WeihanLi.Npoi/InternalExtensions.cs
  class InternalExtensions (line 17) | internal static class InternalExtensions
    method ParseParamInfo (line 24) | public static IDictionary<string, object?> ParseParamInfo(this object?...
    method GetCommonValidator (line 36) | public static IValidator GetCommonValidator<T>(this IValidator<T> vali...
    method GetCellValue (line 55) | public static object? GetCellValue(this ICell? cell, Type propertyType...
    method GetCellValue (line 71) | public static T? GetCellValue<T>(this ICell? cell) => (cell?.Value).To...
    method SetCellValue (line 78) | public static void SetCellValue(this ICell? cell, object? value) => ce...
    method SetCellValue (line 86) | public static void SetCellValue(this ICell cell, object? value, string...
    method GetPropertySettingByPropertyName (line 136) | internal static PropertyConfiguration? GetPropertySettingByPropertyName(
    method GetPropertySetting (line 146) | internal static PropertyConfiguration? GetPropertySetting(
    class CustomValidator (line 151) | private sealed class CustomValidator(Func<object?, ValidationResult> f...
      method Validate (line 160) | public ValidationResult Validate(object? value)

FILE: src/WeihanLi.Npoi/InternalHelper.cs
  class InternalHelper (line 11) | internal static class InternalHelper
    method EnsureFileIsNotReadOnly (line 17) | public static void EnsureFileIsNotReadOnly(string filePath)
    method GetExcelConfigurationMapping (line 33) | public static IExcelConfiguration GetExcelConfigurationMapping(Type en...
    method GetExcelConfigurationMapping (line 47) | public static ExcelConfiguration<TEntity> GetExcelConfigurationMapping...
    method CreateExcelConfiguration (line 56) | private static ExcelConfiguration CreateExcelConfiguration(Type type,
    method AdjustColumnIndex (line 115) | private static void AdjustColumnIndex<TEntity>(ExcelConfiguration<TEnt...
    method GetPropertyColumnDictionary (line 161) | public static Dictionary<PropertyInfo, PropertyConfiguration> GetPrope...
    method GetPropertyColumnDictionary (line 169) | public static Dictionary<PropertyInfo, PropertyConfiguration> GetPrope...
    method GetPropertiesForCsvHelper (line 183) | public static IReadOnlyList<PropertyInfo> GetPropertiesForCsvHelper<TE...
    method GetEncodedColumnName (line 199) | public static string GetEncodedColumnName(string columnName) =>
    method GetDecodeColumnName (line 207) | public static string GetDecodeColumnName(string columnName)

FILE: src/WeihanLi.Npoi/NpoiCollection.cs
  class NpoiRowCollection (line 13) | public sealed class NpoiRowCollection(ISheet sheet) : IReadOnlyCollectio...
    method GetEnumerator (line 25) | public IEnumerator<IRow> GetEnumerator()
    method GetEnumerator (line 33) | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  class NpoiCellCollection (line 39) | public sealed class NpoiCellCollection(IRow row) : IReadOnlyCollection<I...
    method GetEnumerator (line 51) | public IEnumerator<ICell> GetEnumerator()
    method GetEnumerator (line 59) | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

FILE: src/WeihanLi.Npoi/NpoiExtensions.cs
  class NpoiExtensions (line 23) | public static class NpoiExtensions
    method ToEntityList (line 31) | public static List<TEntity?> ToEntityList<TEntity>(this IWorkbook work...
    method ToEntityList (line 41) | public static List<TEntity?> ToEntityList<TEntity>(this IWorkbook work...
    method ToEntities (line 54) | public static IEnumerable<TEntity?> ToEntities<TEntity>(this IWorkbook...
    method ToEntityList (line 75) | public static List<TEntity?> ToEntityList<TEntity>(this ISheet sheet) ...
    method ToEntityList (line 85) | public static List<TEntity?> ToEntityList<TEntity>(this ISheet sheet, ...
    method ToEntities (line 95) | public static IEnumerable<TEntity?> ToEntities<TEntity>(this ISheet sh...
    method ToEntityListWithValidationResult (line 106) | public static (List<TEntity?> EntityList, Dictionary<int, ValidationRe...
    method ToDataTable (line 137) | public static DataTable ToDataTable(this IWorkbook workbook, bool remo...
    method ToDataSet (line 148) | public static DataSet ToDataSet(this IWorkbook workbook, bool removeEm...
    method ToDataSet (line 159) | public static DataSet ToDataSet(this IWorkbook workbook, int headerRow...
    method ToDataTable (line 182) | public static DataTable ToDataTable(this IWorkbook workbook, int sheet...
    method ToDataTable (line 203) | public static DataTable ToDataTable(this ISheet sheet, bool removeEmpt...
    method ToDataTable (line 214) | public static DataTable ToDataTable(this ISheet sheet, int headerRowIn...
    method ImportData (line 308) | public static int ImportData<TEntity>(this IWorkbook workbook, IEnumer...
    method ImportData (line 319) | public static int ImportData<TEntity>(this IWorkbook workbook, IEnumer...
    method CreateSheets (line 354) | private static void CreateSheets<TEntity>(this IWorkbook workbook, int...
    method ImportData (line 376) | public static ISheet ImportData<TEntity>(this ISheet sheet, IEnumerabl...
    method ImportData (line 386) | public static ISheet ImportData<TEntity>(this ISheet sheet, IEnumerabl...
    method ImportData (line 395) | public static int ImportData<TEntity>(this IWorkbook workbook, DataTab...
    method ImportData (line 406) | public static int ImportData<TEntity>(this IWorkbook workbook, DataTab...
    method ImportData (line 441) | public static ISheet ImportData<TEntity>(this ISheet sheet, DataTable ...
    method ImportData (line 451) | public static ISheet ImportData<TEntity>(this ISheet sheet, DataTable ...
    method ToExcelFile (line 460) | public static void ToExcelFile<TEntity>(this IList<TEntity> entityList,
    method ToExcelFile (line 482) | public static void ToExcelFile<TEntity>(this IEnumerable<TEntity> enti...
    method ToExcelFile (line 492) | public static void ToExcelFile<TEntity>(this IEnumerable<TEntity> enti...
    method ToExcelStream (line 510) | public static void ToExcelStream<TEntity>(this IEnumerable<TEntity> en...
    method ToExcelStream (line 521) | public static void ToExcelStream<TEntity>(this IEnumerable<TEntity> en...
    method ToExcelStream (line 540) | public static void ToExcelStream<TEntity>(this IEnumerable<TEntity> en...
    method ToExcelStream (line 550) | public static void ToExcelStream<TEntity>(this IList<TEntity> entityList,
    method ToExcelBytes (line 564) | public static byte[] ToExcelBytes<TEntity>(this IEnumerable<TEntity> e...
    method ToExcelBytes (line 573) | public static byte[] ToExcelBytes<TEntity>(this IEnumerable<TEntity> e...
    method ToExcelBytes (line 583) | public static byte[] ToExcelBytes<TEntity>(this IEnumerable<TEntity> e...
    method ToExcelBytes (line 605) | public static byte[] ToExcelBytes<TEntity>(this IList<TEntity> entityL...
    method GetWorkbookWithAutoSplitSheet (line 624) | public static IWorkbook GetWorkbookWithAutoSplitSheet<TEntity>(this IL...
    method GetWorkbookWithAutoSplitSheet (line 663) | public static IWorkbook GetWorkbookWithAutoSplitSheet(this DataTable d...
    method ToExcelFile (line 720) | public static void ToExcelFile(this DataTable dataTable, string excelP...
    method ImportData (line 728) | public static void ImportData(this ISheet sheet, DataTable? dataTable)
    method ToExcelFile (line 764) | public static void ToExcelFile(this DataTable dataTable, string excelP...
    method ToExcelStream (line 780) | public static void ToExcelStream(this DataTable dataTable, Stream stre...
    method ToExcelStream (line 790) | public static void ToExcelStream(this DataTable dataTable, Stream stre...
    method ToExcelStream (line 801) | public static void ToExcelStream(this DataTable dataTable, Stream stre...
    method ToExcelBytes (line 814) | public static byte[] ToExcelBytes(this DataTable dataTable) => ToExcel...
    method ToExcelBytes (line 821) | public static byte[] ToExcelBytes(this DataTable dataTable, ExcelForma...
    method ToExcelBytes (line 830) | public static byte[] ToExcelBytes(this DataTable dataTable, ExcelForma...
    method SetCellValue (line 843) | public static void SetCellValue(this ICell cell, object? value) => cel...
    method SetCellValue (line 851) | public static void SetCellValue(this ICell cell, object? value, string...
    method GetCellValue (line 908) | public static object? GetCellValue(this ICell? cell, Type propertyType,
    method GetCellValue (line 1016) | public static T GetCellValue<T>(this ICell? cell, IFormulaEvaluator? f...
    method GetRowCollection (line 1024) | public static NpoiRowCollection GetRowCollection(this ISheet sheet) =>...
    method GetCellCollection (line 1031) | public static NpoiCellCollection GetCellCollection(this IRow row) => n...
    method GetFormulaEvaluator (line 1038) | public static IFormulaEvaluator GetFormulaEvaluator(this IWorkbook wor...
    method GetPicturesAndPosition (line 1056) | public static Dictionary<CellPosition, IPictureData> GetPicturesAndPos...
    method TryAddPicture (line 1100) | public static bool TryAddPicture(this ISheet sheet, int row, int col, ...
    method TryAddPicture (line 1112) | public static bool TryAddPicture(this ISheet sheet, int row, int col, ...
    method WriteToFile (line 1144) | public static void WriteToFile(this IWorkbook workbook, string filePat...
    method WriteToFile (line 1152) | public static void WriteToFile(this IWorkbook workbook, string filePat...
    method ToExcelBytes (line 1182) | public static byte[] ToExcelBytes(this IWorkbook workbook) => ToExcelB...
    method ToExcelBytes (line 1190) | public static byte[] ToExcelBytes(this IWorkbook workbook, bool closeW...
    method ToExcelFileByTemplate (line 1218) | public static void ToExcelFileByTemplate<TEntity>(this IEnumerable<TEn...
    method ToExcelFileByTemplate (line 1240) | public static void ToExcelFileByTemplate<TEntity>(this IEnumerable<TEn...
    method ToExcelFileByTemplate (line 1261) | public static void ToExcelFileByTemplate<TEntity>(this IEnumerable<TEn...
    method ToExcelBytesByTemplate (line 1288) | public static byte[] ToExcelBytesByTemplate<TEntity>(this IEnumerable<...
    method ToExcelBytesByTemplate (line 1302) | public static byte[] ToExcelBytesByTemplate<TEntity>(this IEnumerable<...
    method ToExcelBytesByTemplate (line 1322) | public static byte[] ToExcelBytesByTemplate<TEntity>(this IEnumerable<...
    method ToExcelBytesByTemplate (line 1340) | public static byte[] ToExcelBytesByTemplate<TEntity>(this IEnumerable<...
    method ToExcelBytesByTemplate (line 1366) | public static byte[] ToExcelBytesByTemplate<TEntity>(this IEnumerable<...

FILE: src/WeihanLi.Npoi/NpoiHelper.cs
  method GetSheetSetting (line 19) | private static SheetSetting GetSheetSetting(IDictionary<int, SheetSettin...

FILE: src/WeihanLi.Npoi/NpoiTemplateHelper.cs
  class NpoiTemplateHelper (line 11) | internal static class NpoiTemplateHelper
    method EntityListToSheetByTemplate (line 26) | public static ISheet EntityListToSheetByTemplate<TEntity>(

FILE: src/WeihanLi.Npoi/Resource.Designer.cs
  class Resource (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resource (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: src/WeihanLi.Npoi/Settings/ExcelSetting.cs
  class ExcelSetting (line 9) | public sealed class ExcelSetting

FILE: src/WeihanLi.Npoi/Settings/FilterSetting.cs
  class FilterSetting (line 6) | internal sealed class FilterSetting
    method FilterSetting (line 13) | public FilterSetting(int firstColumn, int? lastColumn)

FILE: src/WeihanLi.Npoi/Settings/FreezeSetting.cs
  class FreezeSetting (line 6) | internal sealed class FreezeSetting
    method FreezeSetting (line 11) | public FreezeSetting(int colSplit, int rowSplit) : this(colSplit, rowS...
    method FreezeSetting (line 22) | public FreezeSetting(int colSplit, int rowSplit, int leftmostColumn, i...

FILE: src/WeihanLi.Npoi/Settings/SheetSetting.cs
  class SheetSetting (line 12) | public sealed class SheetSetting

FILE: src/WeihanLi.Npoi/TemplateHelper.cs
  class TemplateOptions (line 12) | public sealed class TemplateOptions
  class TemplateHelper (line 108) | public static class TemplateHelper
    method ConfigureTemplateOptions (line 114) | public static void ConfigureTemplateOptions(Action<TemplateOptions> op...

FILE: test/WeihanLi.Npoi.Test/CsvTest.cs
  class CsvTest (line 13) | public class CsvTest
    method CsvTest (line 15) | public CsvTest()
    method BasicImportExportTest (line 20) | [Fact]
    method ImportWithNotSpecificColumnIndex (line 62) | [Fact]
    method DataTableImportExportTest (line 104) | [Fact]
    method DataTableWithFirstLineEmpty (line 131) | [Theory]
    method DataTableImportExportTestWithNonStringColumns (line 174) | [Theory]
    method ParseCsvLineTest (line 216) | [Theory]
    method GetCsvTextTest_BasicType (line 241) | [Fact]
    method GetCsvLines_BasicType (line 252) | [Theory]
    method CsvFileTest (line 270) | [Theory]
    method GetCsvLines_Entity (line 290) | [Theory]
    method GetCsvTextTest_Entity (line 308) | [Fact]
    method CsvStringListTest (line 324) | [Fact]
    method DuplicateColumnTest (line 338) | [Fact]
    method CsvOptionTest_CustomSeparatorCharacter (line 354) | [Fact]
    method CsvToListEncodingTest (line 374) | [Fact]
    method CsvToDataTableEncodingTest (line 388) | [Fact]
    method CsvToListEncodingTest_NotTheSameEncoding (line 402) | [Fact]
    method TrimQuotes (line 416) | private static string TrimQuotes(string? str)
    type TestModel (line 432) | private sealed record TestModel

FILE: test/WeihanLi.Npoi.Test/ExcelFormatData.cs
  class ExcelFormatData (line 8) | public sealed class ExcelFormatData : TheoryData<ExcelFormat>
    method ExcelFormatData (line 10) | public ExcelFormatData()

FILE: test/WeihanLi.Npoi.Test/ExcelTest.cs
  class ExcelTest (line 22) | public class ExcelTest
    method BasicImportExportTest (line 24) | [Theory]
    method BasicImportExportTestWithEmptyValue (line 70) | [Theory]
    method BasicImportExportWithoutHeaderTest (line 116) | [Theory]
    method ImportWithNotSpecificColumnIndex (line 167) | [Theory]
    method ShadowPropertyTest (line 219) | [Theory]
    method IgnoreInheritPropertyTest (line 259) | [Theory]
    method ColumnInputFormatterTest (line 307) | [Theory]
    method InputOutputColumnFormatterTest (line 346) | [Theory]
    method DataValidationTest (line 388) | [Theory]
    method DataTableImportExportTest (line 434) | [Theory]
    method DataTableImportExportWithEmptyValueTest (line 466) | [Theory]
    method ExcelImportWithFormula (line 504) | [Theory]
    class ExcelFormulaTestModel (line 531) | private class ExcelFormulaTestModel
    method ExcelImportWithCellFilter (line 539) | [Theory]
    method ExcelImportWithCellFilterAttributeTest (line 583) | [Theory]
    class CellFilterAttributeTest (line 607) | [Sheet(SheetName = "test", AutoColumnWidthEnabled = true, StartColumnI...
    method EntityListAutoSplitSheetsTest (line 620) | [Theory]
    method DataTableAutoSplitSheetsTest (line 643) | [Theory]
    method DataTableImportExportTestWithFirstColumnsEmpty (line 668) | [Theory]
    method DataTableImportExportTestWithNonStringColumns (line 701) | [Theory]
    method DataTableImportExportTestWithoutEmptyRowsAndAdditionalColumns (line 731) | [Theory]
    method ImageImportExportTest (line 763) | [Theory]
    method ImageImportExportPictureDataTest (line 786) | [Theory]
    method DataTableDefaultValueTest (line 811) | [Fact]
    method SheetNameTest_ToExcelFile (line 828) | [Theory]
    method SheetNameTest_ToExcelBytes (line 863) | [Theory]
    method DuplicateColumnTest (line 894) | [Theory]
    method ValidatorTest (line 936) | [Theory]
    method ValidatorTest_CustomValidator (line 959) | [Theory]
    method CellReaderTest (line 986) | [Theory]
    method PostImportActionTest (line 1012) | [Theory]
    method CellTypeTest (line 1036) | [Theory]
    method HeaderCellTypeTest (line 1067) | [Theory]
    method ChineseDateFormatterTest (line 1093) | [Theory]
    method PropertyOrderTest (line 1115) | [Fact]
    method PropertyOrderTest2 (line 1155) | [Fact]
    method PropertyOrderTest3 (line 1195) | [Fact]
    method PropertyOrderTest4_CustomOrdering (line 1236) | [Fact]
    class CellFormatTestModel (line 1277) | private sealed class CellFormatTestModel
    type CellReaderTestModel (line 1284) | private sealed record CellReaderTestModel
    type PostImportActionTestModel (line 1290) | private sealed record PostImportActionTestModel
    class ImageTest (line 1298) | private sealed class ImageTest
    class ImageTestPicData (line 1305) | private sealed class ImageTestPicData
  class PropertyNameBasedPropertyComparer (line 1313) | file sealed class PropertyNameBasedPropertyComparer : IComparer<Property...
    method Compare (line 1315) | public int Compare(PropertyInfo? x, PropertyInfo? y)
  class ChineseDateFormatter (line 1327) | file sealed class ChineseDateFormatter
    class ChineDateTestModel (line 1329) | public sealed class ChineDateTestModel
    method FormatInput (line 1334) | public static DateTime FormatInput(string? input)
    method FormatOutput (line 1343) | public static string FormatOutput(DateTime input)
  class DateTimeUtils (line 1350) | file static class DateTimeUtils
    method TransStrToDateTime (line 1358) | public static bool TransStrToDateTime(string? str, out DateTime dt)
    method IsDateTime (line 1420) | public static bool IsDateTime(string str)
    method GetYear (line 1475) | public static int GetYear(string str)
    method GetMonth (line 1526) | public static int GetMonth(string str)
    method NumToChinese (line 1579) | public static string NumToChinese(string x)
    method CharToNumber (line 1639) | public static long CharToNumber(char c)
    method CharToUnit (line 1659) | public static long CharToUnit(char c)
    method ParseCnToInt (line 1676) | public static long ParseCnToInt(string cnum)

FILE: test/WeihanLi.Npoi.Test/Extensions.cs
  class Extensions (line 9) | public static class Extensions
    method AddNewRow (line 11) | public static DataRow AddNewRow(this DataTable datatable, object[]? ro...
    method AssertEquals (line 22) | public static void AssertEquals(this DataTable actual, DataTable expec...

FILE: test/WeihanLi.Npoi.Test/MappingProfiles/NoticeProfile.cs
  class NoticeProfile (line 10) | public sealed class NoticeProfile : IMappingProfile<Notice>
    method Configure (line 12) | public void Configure(IExcelConfiguration<Notice> noticeSetting)

FILE: test/WeihanLi.Npoi.Test/Models/Job.cs
  type Job (line 8) | public sealed record Job

FILE: test/WeihanLi.Npoi.Test/Models/Notice.cs
  class BaseModel (line 6) | public class BaseModel
  class Notice (line 11) | public class Notice : BaseModel

FILE: test/WeihanLi.Npoi.Test/Models/OrderTestModels.cs
  class OrderTestModel1 (line 8) | public class OrderTestModel1
  class OrderTestModel2 (line 17) | public class OrderTestModel2
  class OrderTestModel3 (line 28) | public class OrderTestModel3
  class OrderTestModel4 (line 39) | public class OrderTestModel4

FILE: test/WeihanLi.Npoi.Test/Startup.cs
  class Startup (line 8) | public class Startup
    method Configure (line 10) | public void Configure()
Condensed preview — 132 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (578K chars).
[
  {
    "path": ".codacy.yml",
    "chars": 37,
    "preview": "exclude_paths:\n  - samples/\n  - test/"
  },
  {
    "path": ".devcontainer/Dockerfile",
    "chars": 168,
    "preview": "FROM mcr.microsoft.com/dotnet/sdk:10.0\nRUN apt-get update \\ \n    && apt-get install -y libgdiplus libc6-dev \\ \n    && ln"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 252,
    "preview": "{\n    \"name\": \"CodeSpace\",\n    \"dockerFile\": \"Dockerfile\",\n    \"customizations\": {\n        \"vscode\": {\n            \"exte"
  },
  {
    "path": ".editorconfig",
    "chars": 3461,
    "preview": "# EditorConfig is awesome:http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Don't use tabs for indent"
  },
  {
    "path": ".gitattributes",
    "chars": 2556,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 559,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/stale.yml",
    "chars": 685,
    "preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 30\n# Number of days of inactivity before a "
  },
  {
    "path": ".github/workflows/docfx.yml",
    "chars": 1762,
    "preview": "name: docfx\non:\n  push:\n    branches:\n      - \"main\"\n      - \"master\"\n      - \"dev\"\n\n# Sets permissions of the GITHUB_TO"
  },
  {
    "path": ".github/workflows/dotnet-format-pr-validation.yml",
    "chars": 369,
    "preview": "name: dotnet-format-validation\n\non: [pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: act"
  },
  {
    "path": ".github/workflows/dotnet-format.yml",
    "chars": 1068,
    "preview": "name: dotnet-format\n\non:\n  push:\n    branches: [ dev ]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses:"
  },
  {
    "path": ".github/workflows/dotnet.yml",
    "chars": 1383,
    "preview": "name: default\n\non: [push, pull_request]\n\njobs:\n  mac-build:\n    runs-on: macos-latest\n    steps:\n    - uses: actions/che"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 720,
    "preview": "name: Release\non:\n  push:\n    branches: [ master ]\njobs:\n  build:\n    name: Release\n    runs-on: windows-latest\n    step"
  },
  {
    "path": ".gitignore",
    "chars": 4846,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
  },
  {
    "path": ".travis.yml",
    "chars": 362,
    "preview": "language: csharp\n\n# runtime config\nmono: none\ndotnet: 5.0.100\ndist: bionic\n\n# branch build config\nbranches:\n    only:   "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3352,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "Directory.Build.props",
    "chars": 439,
    "preview": "<Project>\n  <Import Project=\"./build/version.props\"/>\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n "
  },
  {
    "path": "Directory.Packages.props",
    "chars": 933,
    "preview": "<Project>\n  <PropertyGroup>\n    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>\n    <!-- https://l"
  },
  {
    "path": "LICENSE",
    "chars": 11304,
    "preview": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licens"
  },
  {
    "path": "README.md",
    "chars": 13923,
    "preview": "# WeihanLi.Npoi\n\n[![WeihanLi.Npoi](https://img.shields.io/nuget/v/WeihanLi.Npoi)](https://www.nuget.org/packages/WeihanL"
  },
  {
    "path": "WeihanLi.Npoi.sln.DotSettings",
    "chars": 397,
    "preview": "<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namesp"
  },
  {
    "path": "WeihanLi.Npoi.slnx",
    "chars": 742,
    "preview": "<Solution>\n  <Folder Name=\"/perf/\">\n    <Project Path=\"perf/WeihanLi.Npoi.Benchmark/WeihanLi.Npoi.Benchmark.csproj\" />\n "
  },
  {
    "path": "azure-pipelines.yml",
    "chars": 491,
    "preview": "trigger:\n  branches:\n    include:\n    - '*' # must quote since \"*\" is a YAML reserved character; we want a string\n  path"
  },
  {
    "path": "build/common.props",
    "chars": 1177,
    "preview": "<Project>\n  <PropertyGroup>        \n    <TargetFramework>netstandard2.0</TargetFramework>  \n    <Title>WeihanLi.Npoi</Ti"
  },
  {
    "path": "build/getReleaseVersion.ps1",
    "chars": 351,
    "preview": "$versionPath=$PSScriptRoot+\"/version.props\"\r\n$versionXml=([xml](Get-Content $versionPath))\r\n$versionProperty=$versionXml"
  },
  {
    "path": "build/sign.props",
    "chars": 299,
    "preview": "<Project>\n  <PropertyGroup Condition=\"'$(OS)' == 'Windows_NT' AND '$(Configuration)' == 'Release'\">\n    <SignAssembly>Tr"
  },
  {
    "path": "build/version.props",
    "chars": 313,
    "preview": "<Project>\n  <PropertyGroup>\n    <VersionMajor>3</VersionMajor>\n    <VersionMinor>3</VersionMinor>\n    <VersionPatch>0</V"
  },
  {
    "path": "build.cs",
    "chars": 716,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\n#:package WeihanLi.Common\n\nusin"
  },
  {
    "path": "docs/ReleaseNotes.md",
    "chars": 8874,
    "preview": "# WeihanLi.Npoi Release Notes\n\n## [3.3.0](https://www.nuget.org/packages/WeihanLi.Npoi/3.3.0)\n\n- Support `HasPostImportA"
  },
  {
    "path": "docs/api/.gitignore",
    "chars": 64,
    "preview": "###############\n#  temp file  #\n###############\n*.yml\n.manifest\n"
  },
  {
    "path": "docs/api/index.md",
    "chars": 117,
    "preview": "# PLACEHOLDER\n\nTODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*!\n"
  },
  {
    "path": "docs/articles/en/CustomizeStyle.md",
    "chars": 10486,
    "preview": "# Customize Excel Styles\n\n## Introduction\n\nWeihanLi.Npoi provides powerful styling capabilities through the `RowAction` "
  },
  {
    "path": "docs/articles/en/GetStarted.md",
    "chars": 8545,
    "preview": "# `WeihanLi.Npoi` Getting Started\n\n## Introduction\n\n`WeihanLi.Npoi` is an Excel import/export library based on NPOI that"
  },
  {
    "path": "docs/articles/en/InputOutputFormatter.md",
    "chars": 3283,
    "preview": "# InputOutputFormatter Introduction\n\n## Introduction\n\nWeihanLi.Npoi introduces `OutputFormatter`/`InputFormatter`/`Colum"
  },
  {
    "path": "docs/articles/en/MultiSheets.md",
    "chars": 1986,
    "preview": "# Multi-Sheet Export\n\n## Introduction\n\nSometimes we may want to export multiple collections of data in multiple sheets w"
  },
  {
    "path": "docs/articles/en/ShadowProperty.md",
    "chars": 3629,
    "preview": "# WeihanLi.Npoi Now Supports `ShadowProperty`\n\n## Introduction\n\nIn Entity Framework, there's a concept called `ShadowPro"
  },
  {
    "path": "docs/articles/en/TemplateExport.md",
    "chars": 5212,
    "preview": "# Export Excel Based on Template\n\n## Introduction\n\nThe original export method is suitable for relatively simple exports "
  },
  {
    "path": "docs/articles/intro.md",
    "chars": 720,
    "preview": "# WeihanLi.Npoi\n\n## Intro\n\n`WeihanLi.Npoi` is an extension for excel/csv import/export based on NPOI\n\n## Recommend Artic"
  },
  {
    "path": "docs/articles/toc.yml",
    "chars": 816,
    "preview": "- name: Introduction\n  href: intro.md\n- name: English Articles\n  items:\n    - name: Getting Started\n      href: en/GetSt"
  },
  {
    "path": "docs/articles/zh/CustomizeStyle.md",
    "chars": 8606,
    "preview": "# 自定义 Excel 样式\n\n## 简介\n\nWeihanLi.Npoi 通过 sheet 配置中的 `RowAction` 和 `CellAction` 回调提供了强大的样式定制功能。你可以自定义字体、颜色、对齐方式、边框,并添加数据验证"
  },
  {
    "path": "docs/articles/zh/GetStarted.md",
    "chars": 8111,
    "preview": "# `WeihanLi.Npoi` 基础示例\n\n## Intro\n\n`WeihanLi.Npoi` 是基于 NPOI 扩展的 Excel 导入导出库,并提供了很多实用的扩展方法,也支持 CSV 的导入导出,\n\n- 将 excel/csv 数"
  },
  {
    "path": "docs/articles/zh/InputOutputFormatter.md",
    "chars": 3036,
    "preview": "# InputOutputFormatter 介绍\n\n## Intro\n\nWeihanLi.Npoi 引入了 `OutputFormatter`/`InputFormatter`/`ColumnInputFormatter`/`Column"
  },
  {
    "path": "docs/articles/zh/MultiSheets.md",
    "chars": 1762,
    "preview": "# 多 sheet 导出\n\n## Intro\n\n有时我们可能会希望在一个 excel 里导出多个 sheet 导出多个集合的数据,可以参考下面的示例代码:\n\n## Sample\n\n```c#\nvar collection1 = new[]\n"
  },
  {
    "path": "docs/articles/zh/ShadowProperty.md",
    "chars": 2992,
    "preview": "# WeihanLi.Npoi 支持 `ShadowProperty` 了\n\n## Intro\n\n在 EF 里有个 `ShadowProperty` (阴影属性/影子属性)的概念,你可以通过 FluentAPI 的方式来定义一个不在 .NE"
  },
  {
    "path": "docs/articles/zh/TemplateExport.md",
    "chars": 4421,
    "preview": "# 根据模板导出Excel\n\n## Intro\n\n原来的导出方式比较适用于比较简单的导出,每一条数据在一行,数据列虽然自定义程度比较高,如果要一条数据对应多行就做不到了,于是就想支持根据模板导出,在 1.8.0 版本中引入了根据模板导出的功"
  },
  {
    "path": "docs/docfx.json",
    "chars": 674,
    "preview": "{\n  \"metadata\": [\n    {\n      \"src\": [\n        {\n          \"src\": \"../src\",\n          \"files\": [\n            \"**/*.cspro"
  },
  {
    "path": "docs/toc.yml",
    "chars": 245,
    "preview": "- name: Home\n  href: index.md\n- name: API Documentation\n  href: api/\n- name: Release Notes\n  href: ReleaseNotes.md\n- nam"
  },
  {
    "path": "global.json",
    "chars": 133,
    "preview": "{\n  \"sdk\": {\n    \"rollForward\": \"major\",\n    \"version\": \"10.0.100\"\n  },\n  \"test\": {\n    \"runner\": \"Microsoft.Testing.Pla"
  },
  {
    "path": "nuget.config",
    "chars": 352,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <config>\n    <add key=\"defaultPushSource\" value=\"nuget\" />\n  </"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report-github.md",
    "chars": 6774,
    "preview": "``` ini\n\nBenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362\nIntel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical an"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report.csv",
    "chars": 13725,
    "preview": "Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,Outl"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ExportExcelTest-report.html",
    "chars": 8930,
    "preview": "<!DOCTYPE html>\n<html lang='en'>\n<head>\n<meta charset='utf-8' />\n<title>WeihanLi.Npoi.Benchmark.ExportExcelTest-20191108"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report-github.md",
    "chars": 2952,
    "preview": "``` ini\n\nBenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362\nIntel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical an"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report.csv",
    "chars": 5482,
    "preview": "Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,Outl"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.ImportExcelTest-report.html",
    "chars": 3972,
    "preview": "<!DOCTYPE html>\n<html lang='en'>\n<head>\n<meta charset='utf-8' />\n<title>WeihanLi.Npoi.Benchmark.ImportExcelTest-20191108"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report-github.md",
    "chars": 3780,
    "preview": "``` ini\n\nBenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362\nIntel Core i5-3470 CPU 3.20GHz (Ivy Bridge), 1 CPU, 4 logical an"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.csv",
    "chars": 5642,
    "preview": "Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,Outl"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/BenchmarkDotNet.Artifacts/results/WeihanLi.Npoi.Benchmark.WorkbookBasicTest-report.html",
    "chars": 4315,
    "preview": "<!DOCTYPE html>\n<html lang='en'>\n<head>\n<meta charset='utf-8' />\n<title>WeihanLi.Npoi.Benchmark.WorkbookBasicTest-201911"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/ExportExcelTest.cs",
    "chars": 3899,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing BenchmarkDotNet.Attribute"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/ImportExcelTest.cs",
    "chars": 2212,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing BenchmarkDotNet.Attribute"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/Program.cs",
    "chars": 386,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing BenchmarkDotNet.Running;\n"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/WeihanLi.Npoi.Benchmark.csproj",
    "chars": 366,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n"
  },
  {
    "path": "perf/WeihanLi.Npoi.Benchmark/WorkbookBasicTest.cs",
    "chars": 2063,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing BenchmarkDotNet.Attribute"
  },
  {
    "path": "samples/Directory.Build.props",
    "chars": 729,
    "preview": "<Project>\n  <!-- See https://aka.ms/dotnet/msbuild/customize for more details on customizing your build -->\n  <Import Pr"
  },
  {
    "path": "samples/DotNetCoreSample/DotNetCoreSample.csproj",
    "chars": 267,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n"
  },
  {
    "path": "samples/DotNetCoreSample/ImportImageTestModel.cs",
    "chars": 267,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace DotNetCoreSample;\n\nin"
  },
  {
    "path": "samples/DotNetCoreSample/IssueSamples.cs",
    "chars": 4276,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Extensions;\n\npub"
  },
  {
    "path": "samples/DotNetCoreSample/ProductPriceMapping.cs",
    "chars": 486,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\n\n// ReSharper disable Inconsist"
  },
  {
    "path": "samples/DotNetCoreSample/Program.cs",
    "chars": 13594,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "samples/DotNetCoreSample/TestModel.cs",
    "chars": 2445,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace DotNetCoreSample;\n\n[S"
  },
  {
    "path": "samples/run-file-samples/issue-169.cs",
    "chars": 4096,
    "preview": "var filePath = @\"C:\\Users\\Weiha\\Downloads\\test\\2.xlsx\";\nvar workbook = ExcelHelper.LoadExcel(\n    File.OpenRead(filePat"
  },
  {
    "path": "samples/run-file-samples/style-customization-sample.cs",
    "chars": 4896,
    "preview": "using NPOI.SS.UserModel;\nusing NPOI.SS.Util;\n\nFluentSettings.LoadMappingProfile<StyledEntity, StyledEntityProfile>();\n\n"
  },
  {
    "path": "src/Directory.Build.props",
    "chars": 1727,
    "preview": "<Project>\n  <Import Project=\"$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))"
  },
  {
    "path": "src/WeihanLi.Npoi/Abstract/ICell.cs",
    "chars": 378,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Abstrac"
  },
  {
    "path": "src/WeihanLi.Npoi/Abstract/IRow.cs",
    "chars": 1108,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Abstrac"
  },
  {
    "path": "src/WeihanLi.Npoi/Abstract/ISheet.cs",
    "chars": 923,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Abstrac"
  },
  {
    "path": "src/WeihanLi.Npoi/Abstract/IWorkbook.cs",
    "chars": 290,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Abstrac"
  },
  {
    "path": "src/WeihanLi.Npoi/Abstract/NPOIWorkbook.cs",
    "chars": 7039,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.Util;\nusing NMode"
  },
  {
    "path": "src/WeihanLi.Npoi/Attributes/ColumnAttribute.cs",
    "chars": 2382,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Configurati"
  },
  {
    "path": "src/WeihanLi.Npoi/Attributes/FilterAttribute.cs",
    "chars": 1247,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Settings;\n\n"
  },
  {
    "path": "src/WeihanLi.Npoi/Attributes/FreezeAttribute.cs",
    "chars": 1685,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Settings;\n\n"
  },
  {
    "path": "src/WeihanLi.Npoi/Attributes/SheetAttribute.cs",
    "chars": 3390,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Settings;\n\n"
  },
  {
    "path": "src/WeihanLi.Npoi/CellPosition.cs",
    "chars": 363,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi;\n\n/// <"
  },
  {
    "path": "src/WeihanLi.Npoi/Compat.cs",
    "chars": 234,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n#if NETSTANDARD\n// ReSharper dis"
  },
  {
    "path": "src/WeihanLi.Npoi/ConfigurationExtensions.cs",
    "chars": 8077,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Common.Services;"
  },
  {
    "path": "src/WeihanLi.Npoi/Configurations/CsvOptions.cs",
    "chars": 2097,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Text;\n\nnamespace W"
  },
  {
    "path": "src/WeihanLi.Npoi/Configurations/ExcelConfiguration.cs",
    "chars": 8039,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Linq.Expressions;\n"
  },
  {
    "path": "src/WeihanLi.Npoi/Configurations/IExcelConfiguration.cs",
    "chars": 4958,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Linq.Expressions;\n"
  },
  {
    "path": "src/WeihanLi.Npoi/Configurations/IPropertyConfiguration.cs",
    "chars": 2717,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\n\nnames"
  },
  {
    "path": "src/WeihanLi.Npoi/Configurations/PropertyConfiguration.cs",
    "chars": 4233,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/CsvHelper.cs",
    "chars": 42958,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Data;\nusing System"
  },
  {
    "path": "src/WeihanLi.Npoi/ExcelFormat.cs",
    "chars": 344,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi;\n\n/// <"
  },
  {
    "path": "src/WeihanLi.Npoi/ExcelHelper.cs",
    "chars": 23976,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.HPSF;\nusing NPOI.HSS"
  },
  {
    "path": "src/WeihanLi.Npoi/FakePropertyInfo.cs",
    "chars": 2174,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Globalization;\nusi"
  },
  {
    "path": "src/WeihanLi.Npoi/FluentSettings.cs",
    "chars": 4188,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Reflection;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/IMappingProfile.cs",
    "chars": 726,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Configurati"
  },
  {
    "path": "src/WeihanLi.Npoi/InternalCache.cs",
    "chars": 1365,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Collections.Concur"
  },
  {
    "path": "src/WeihanLi.Npoi/InternalConstants.cs",
    "chars": 2244,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi;\n\ninter"
  },
  {
    "path": "src/WeihanLi.Npoi/InternalExtensions.cs",
    "chars": 5810,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/InternalHelper.cs",
    "chars": 8840,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Reflection;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/NpoiCollection.cs",
    "chars": 1626,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/NpoiExtensions.cs",
    "chars": 51529,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.HSSF.UserModel;\nusin"
  },
  {
    "path": "src/WeihanLi.Npoi/NpoiHelper.cs",
    "chars": 16976,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/NpoiTemplateHelper.cs",
    "chars": 7795,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/Resource.Designer.cs",
    "chars": 4318,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "src/WeihanLi.Npoi/Resource.resx",
    "chars": 6251,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "src/WeihanLi.Npoi/Settings/ExcelSetting.cs",
    "chars": 933,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Setting"
  },
  {
    "path": "src/WeihanLi.Npoi/Settings/FilterSetting.cs",
    "chars": 764,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Setting"
  },
  {
    "path": "src/WeihanLi.Npoi/Settings/FreezeSetting.cs",
    "chars": 1432,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Setting"
  },
  {
    "path": "src/WeihanLi.Npoi/Settings/SheetSetting.cs",
    "chars": 2311,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.SS.UserModel;\nusing "
  },
  {
    "path": "src/WeihanLi.Npoi/TemplateHelper.cs",
    "chars": 2672,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Common;\nusing We"
  },
  {
    "path": "src/WeihanLi.Npoi/WeihanLi.Npoi.csproj",
    "chars": 723,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"../../build/common.props\" />\n\n  <ItemGroup>\n    <PackageReference I"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/CsvTest.cs",
    "chars": 14421,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Data;\nusing System"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/ExcelFormatData.cs",
    "chars": 302,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing Xunit;\n\nnamespace WeihanL"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/ExcelTest.cs",
    "chars": 59520,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing NPOI.HSSF.UserModel;\nusin"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/Extensions.cs",
    "chars": 1548,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.Data;\nusing Xunit;"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/MappingProfiles/NoticeProfile.cs",
    "chars": 1122,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Extensions;\nusin"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/Models/Job.cs",
    "chars": 299,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing System.ComponentModel.Dat"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/Models/Notice.cs",
    "chars": 395,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nnamespace WeihanLi.Npoi.Test.Mo"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/Models/OrderTestModels.cs",
    "chars": 863,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Attributes;"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/Startup.cs",
    "chars": 443,
    "preview": "// Copyright (c) Weihan Li. All rights reserved.\n// Licensed under the Apache license.\n\nusing WeihanLi.Npoi.Test.Mappin"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/TestData/EmptyColumns/emptyColumns.csv",
    "chars": 34,
    "preview": "A,B,C,D\n,,3,4\n,2,3,\n1,2,,\n1,2,3,4\n"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/TestData/NonStringColumns/nonStringColumns.csv",
    "chars": 32,
    "preview": "A,1000,TRUE,15/08/2021\n1,2,3,4\n"
  },
  {
    "path": "test/WeihanLi.Npoi.Test/WeihanLi.Npoi.Test.csproj",
    "chars": 1047,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <IsTestProject>true</IsTestProject>\n    <OutputType>exe</Output"
  }
]

// ... and 8 more files (download for full content)

About this extraction

This page contains the full source code of the WeihanLi/WeihanLi.Npoi GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 132 files (531.0 KB), approximately 139.5k tokens, and a symbol index with 477 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!