第02章-环境搭建与项目配置

第二章:环境搭建与项目配置

2.1 开发环境准备

2.1.1 .NET版本要求

NPOI支持多个.NET版本,根据你的项目需求选择合适的版本:

.NET版本 NPOI支持情况 推荐程度
.NET Framework 4.0+ ✅ 支持 遗留项目
.NET Framework 4.6.2+ ✅ 支持 推荐
.NET Core 2.1+ ✅ 支持 推荐
.NET 5.0 ✅ 支持 推荐
.NET 6.0 ✅ 支持 强烈推荐
.NET 7.0 ✅ 支持 强烈推荐
.NET 8.0 ✅ 支持 强烈推荐

2.1.2 IDE选择

推荐使用以下IDE进行NPOI开发:

  • Visual Studio 2022:功能最完整的.NET开发IDE
  • Visual Studio Code:轻量级,配合C#扩展使用
  • JetBrains Rider:跨平台的.NET IDE

2.1.3 系统要求

  • Windows 10/11、Windows Server 2016+
  • macOS 10.15+
  • Linux(Ubuntu 18.04+、CentOS 7+等)

2.2 NuGet包安装

2.2.1 通过Visual Studio安装

  1. 右键点击项目 → 选择"管理NuGet包"
  2. 搜索"NPOI"
  3. 选择合适的包并安装

2.2.2 通过Package Manager Console安装

# 安装最新版NPOI(包含所有功能)
Install-Package NPOI

# 或者安装特定版本
Install-Package NPOI -Version 2.7.1

2.2.3 通过.NET CLI安装

# 安装NPOI
dotnet add package NPOI

# 安装特定版本
dotnet add package NPOI --version 2.7.1

2.2.4 通过PackageReference手动添加

编辑项目文件(.csproj),添加以下内容:

<ItemGroup>
    <PackageReference Include="NPOI" Version="2.7.1" />
</ItemGroup>

2.3 NPOI包结构说明

2.3.1 主包依赖关系

NPOI (主包)
├── NPOI.Core           # 核心库
├── NPOI.OOXML          # Office Open XML格式支持
├── NPOI.OpenXml4Net    # OpenXML基础设施
└── 其他依赖包

2.3.2 按需安装指南

如果你只需要特定功能,可以只安装相应的包:

# 仅Excel处理(.xlsx)
Install-Package NPOI.OOXML

# 仅Excel处理(.xls)
Install-Package NPOI.Core

# 完整功能
Install-Package NPOI

2.3.3 版本选择建议

项目类型 推荐版本 说明
新项目 最新稳定版(2.7.x) 功能最完整
生产环境 2.6.2或2.7.1 稳定可靠
遗留项目升级 与原版本兼容的最新版 避免breaking changes

2.4 项目配置示例

2.4.1 控制台应用项目

创建一个.NET 8控制台应用:

dotnet new console -n NpoiDemo
cd NpoiDemo
dotnet add package NPOI

项目文件(NpoiDemo.csproj):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NPOI" Version="2.7.1" />
  </ItemGroup>

</Project>

2.4.2 ASP.NET Core Web API项目

dotnet new webapi -n NpoiWebApi
cd NpoiWebApi
dotnet add package NPOI

2.4.3 类库项目

dotnet new classlib -n NpoiLibrary
cd NpoiLibrary
dotnet add package NPOI

2.5 常用命名空间导入

2.5.1 Excel操作常用命名空间

// 核心接口
using NPOI.SS.UserModel;

// Excel 2007+格式(.xlsx)
using NPOI.XSSF.UserModel;

// Excel 97-2003格式(.xls)
using NPOI.HSSF.UserModel;

// 大文件流式写入
using NPOI.XSSF.Streaming;

// 工具类
using NPOI.SS.Util;

2.5.2 Word操作常用命名空间

// Word 2007+格式(.docx)
using NPOI.XWPF.UserModel;

// Word 97-2003格式(.doc)
using NPOI.HWPF.UserModel;

2.5.3 PowerPoint操作常用命名空间

// PowerPoint 2007+格式(.pptx)
using NPOI.XSLF.UserModel;

// PowerPoint 97-2003格式(.ppt)
using NPOI.HSLF.UserModel;

2.5.4 全局using配置

在项目中添加GlobalUsings.cs文件,统一管理命名空间:

// GlobalUsings.cs
global using NPOI.SS.UserModel;
global using NPOI.XSSF.UserModel;
global using NPOI.HSSF.UserModel;
global using NPOI.XWPF.UserModel;
global using NPOI.SS.Util;
global using System.IO;

2.6 基础帮助类封装

2.6.1 Excel工厂类

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

/// <summary>
/// Excel工作簿工厂类
/// </summary>
public static class ExcelWorkbookFactory
{
    /// <summary>
    /// 创建新的工作簿
    /// </summary>
    /// <param name="fileExtension">文件扩展名(.xls或.xlsx)</param>
    /// <returns>工作簿实例</returns>
    public static IWorkbook Create(string fileExtension)
    {
        return fileExtension.ToLower() switch
        {
            ".xlsx" => new XSSFWorkbook(),
            ".xls" => new HSSFWorkbook(),
            _ => throw new ArgumentException($"不支持的文件格式:{fileExtension}")
        };
    }

    /// <summary>
    /// 从文件流加载工作簿
    /// </summary>
    /// <param name="stream">文件流</param>
    /// <param name="fileExtension">文件扩展名</param>
    /// <returns>工作簿实例</returns>
    public static IWorkbook Open(Stream stream, string fileExtension)
    {
        return fileExtension.ToLower() switch
        {
            ".xlsx" => new XSSFWorkbook(stream),
            ".xls" => new HSSFWorkbook(stream),
            _ => throw new ArgumentException($"不支持的文件格式:{fileExtension}")
        };
    }

    /// <summary>
    /// 从文件路径加载工作簿
    /// </summary>
    /// <param name="filePath">文件路径</param>
    /// <returns>工作簿实例</returns>
    public static IWorkbook Open(string filePath)
    {
        string extension = Path.GetExtension(filePath);
        using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        return Open(fs, extension);
    }
}

2.6.2 单元格值读取辅助类

using NPOI.SS.UserModel;

/// <summary>
/// 单元格值辅助类
/// </summary>
public static class CellValueHelper
{
    /// <summary>
    /// 获取单元格字符串值
    /// </summary>
    public static string GetStringValue(ICell cell)
    {
        if (cell == null) return string.Empty;

        return cell.CellType switch
        {
            CellType.String => cell.StringCellValue,
            CellType.Numeric => DateUtil.IsCellDateFormatted(cell)
                ? cell.DateCellValue?.ToString("yyyy-MM-dd HH:mm:ss") ?? ""
                : cell.NumericCellValue.ToString(),
            CellType.Boolean => cell.BooleanCellValue.ToString(),
            CellType.Formula => GetFormulaCellValue(cell),
            CellType.Blank => string.Empty,
            _ => string.Empty
        };
    }

    /// <summary>
    /// 获取公式单元格的计算结果
    /// </summary>
    private static string GetFormulaCellValue(ICell cell)
    {
        return cell.CachedFormulaResultType switch
        {
            CellType.String => cell.StringCellValue,
            CellType.Numeric => cell.NumericCellValue.ToString(),
            CellType.Boolean => cell.BooleanCellValue.ToString(),
            _ => cell.CellFormula
        };
    }

    /// <summary>
    /// 获取单元格数值
    /// </summary>
    public static double? GetNumericValue(ICell cell)
    {
        if (cell == null) return null;

        return cell.CellType switch
        {
            CellType.Numeric => cell.NumericCellValue,
            CellType.String when double.TryParse(cell.StringCellValue, out double value) => value,
            CellType.Formula when cell.CachedFormulaResultType == CellType.Numeric => cell.NumericCellValue,
            _ => null
        };
    }

    /// <summary>
    /// 获取单元格日期值
    /// </summary>
    public static DateTime? GetDateValue(ICell cell)
    {
        if (cell == null) return null;

        if (cell.CellType == CellType.Numeric && DateUtil.IsCellDateFormatted(cell))
        {
            return cell.DateCellValue;
        }

        if (cell.CellType == CellType.String && 
            DateTime.TryParse(cell.StringCellValue, out DateTime date))
        {
            return date;
        }

        return null;
    }
}

2.6.3 Excel导入导出服务基类

using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

/// <summary>
/// Excel导入导出服务基类
/// </summary>
public abstract class ExcelServiceBase
{
    /// <summary>
    /// 将数据导出到Excel
    /// </summary>
    protected IWorkbook CreateWorkbook<T>(IEnumerable<T> data, string sheetName = "Sheet1")
        where T : class
    {
        var workbook = new XSSFWorkbook();
        var sheet = workbook.CreateSheet(sheetName);

        // 创建表头样式
        var headerStyle = CreateHeaderStyle(workbook);

        // 获取属性列表
        var properties = typeof(T).GetProperties();

        // 创建表头
        var headerRow = sheet.CreateRow(0);
        for (int i = 0; i < properties.Length; i++)
        {
            var cell = headerRow.CreateCell(i);
            cell.SetCellValue(properties[i].Name);
            cell.CellStyle = headerStyle;
        }

        // 创建数据行
        int rowIndex = 1;
        foreach (var item in data)
        {
            var row = sheet.CreateRow(rowIndex++);
            for (int i = 0; i < properties.Length; i++)
            {
                var cell = row.CreateCell(i);
                var value = properties[i].GetValue(item);
                SetCellValue(cell, value);
            }
        }

        // 自动调整列宽
        for (int i = 0; i < properties.Length; i++)
        {
            sheet.AutoSizeColumn(i);
        }

        return workbook;
    }

    /// <summary>
    /// 创建表头样式
    /// </summary>
    protected virtual ICellStyle CreateHeaderStyle(IWorkbook workbook)
    {
        var style = workbook.CreateCellStyle();
        var font = workbook.CreateFont();
        font.IsBold = true;
        style.SetFont(font);
        style.FillForegroundColor = IndexedColors.Grey25Percent.Index;
        style.FillPattern = FillPattern.SolidForeground;
        style.Alignment = HorizontalAlignment.Center;
        return style;
    }

    /// <summary>
    /// 设置单元格值
    /// </summary>
    protected virtual void SetCellValue(ICell cell, object? value)
    {
        if (value == null)
        {
            cell.SetCellValue(string.Empty);
            return;
        }

        switch (value)
        {
            case string s:
                cell.SetCellValue(s);
                break;
            case int i:
                cell.SetCellValue(i);
                break;
            case double d:
                cell.SetCellValue(d);
                break;
            case decimal dec:
                cell.SetCellValue((double)dec);
                break;
            case DateTime dt:
                cell.SetCellValue(dt);
                break;
            case bool b:
                cell.SetCellValue(b);
                break;
            default:
                cell.SetCellValue(value.ToString());
                break;
        }
    }
}

2.7 常见配置问题解决

2.7.1 字体问题(Linux环境)

在Linux服务器上运行NPOI时,可能遇到字体问题。解决方案:

# Ubuntu/Debian
sudo apt-get install fonts-wqy-zenhei fonts-wqy-microhei

# CentOS/RHEL
sudo yum install wqy-zenhei-fonts wqy-microhei-fonts

2.7.2 内存问题

处理大文件时可能遇到内存不足,在项目配置中添加:

<PropertyGroup>
    <ServerGarbageCollection>true</ServerGarbageCollection>
    <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>

2.7.3 编码问题

确保项目支持中文字符:

// 在程序入口处注册编码提供程序
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

2.7.4 依赖冲突解决

如果遇到依赖版本冲突,可以在项目文件中指定版本:

<ItemGroup>
    <PackageReference Include="NPOI" Version="2.7.1" />
    <PackageReference Include="SharpZipLib" Version="1.4.2" />
</ItemGroup>

2.8 验证安装

2.8.1 创建测试程序

using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.XWPF.UserModel;

// 测试Excel功能
Console.WriteLine("测试NPOI Excel功能...");
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Test");
IRow row = sheet.CreateRow(0);
row.CreateCell(0).SetCellValue("Hello NPOI!");

using (var fs = new FileStream("test.xlsx", FileMode.Create))
{
    workbook.Write(fs);
}
Console.WriteLine("✓ Excel测试通过");

// 测试Word功能
Console.WriteLine("测试NPOI Word功能...");
XWPFDocument doc = new XWPFDocument();
XWPFParagraph para = doc.CreateParagraph();
para.CreateRun().SetText("Hello NPOI Word!");

using (var fs = new FileStream("test.docx", FileMode.Create))
{
    doc.Write(fs);
}
Console.WriteLine("✓ Word测试通过");

Console.WriteLine("\nNPOI安装验证完成!");

2.8.2 运行测试

dotnet run

预期输出:

测试NPOI Excel功能...
✓ Excel测试通过
测试NPOI Word功能...
✓ Word测试通过

NPOI安装验证完成!

2.9 本章小结

本章详细介绍了NPOI的开发环境搭建和项目配置。通过本章学习,你应该能够:

  • 选择合适的.NET版本和IDE
  • 正确安装NPOI NuGet包
  • 了解NPOI包的结构和依赖关系
  • 配置不同类型的.NET项目使用NPOI
  • 封装基础的帮助类简化日常开发
  • 解决常见的配置和环境问题

在接下来的章节中,我们将开始深入学习NPOI操作Excel的各项功能,从工作簿和工作表的基础操作开始。


下一章预告:第三章将介绍Excel基础操作,包括工作簿的创建、打开、保存,以及工作表的增删改查操作。

posted @ 2025-12-29 10:47  我才是银古  阅读(2)  评论(0)    收藏  举报