继续在寻找比较快的xlsx写入库,从https://github.com/TinyXlsx/TinyXlsx/ 看到它的测试结果,比c++的openXLSX快几倍,就想试用一下,仔细一看,它是个c#项目,需要.NET 8.0。
于是上微软网站下载了.NET 8.0 SDK,解压缩到c:\d\net8\目录
又下载了TinyXlsx项目源代码, 解压缩到c:\d\TinyXlsx-main\目录。
设置搜索路径并编译
set path=%path%;c:\d\net8
cd \d\tinyxlsx-maindotnet build TinyXlsx.sln --configuration Release
编译成功,但不知怎么执行,进入编译生成目标文件目录找exe文件,只找到testhost.exe,但是执行报错
cd C:\d\TinyXlsx-main\Tests\bin\Release\net8.0C:\d\TinyXlsx-main\Tests\bin\Release\net8.0>testhost
A fatal error occurred. The required library hostfxr.dll could not be found.
If this is a self-contained application, that library should exist in [C:\d\TinyXlsx-main\Tests\bin\Release\net8.0\].
If this is a framework-dependent application, install the runtime in the global location [C:\Program Files\dotnet] or use the DOTNET_ROOT environment variable to specify the runtime location or register the runtime location in [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x64\InstallLocation].The .NET Core runtime can be found at:- https://aka.ms/dotnet-core-applaunch?missing_runtime=true&arch=x64&rid=win10-x64
按照提示,又设置了环境变量DOTNET_ROOT,还是不对,只好请教DeepSeek
C:\d\TinyXlsx-main\Tests\bin\Release\net8.0>set DOTNET_ROOT=c:\d\net8C:\d\TinyXlsx-main\Tests\bin\Release\net8.0>testhost
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'c:\d\net8'.
Failed to run as a self-contained app.- The application was run as a self-contained app because 'C:\d\TinyXlsx-main\Tests\bin\Release\net8.0\testhost.runtimeconfig.json' was not found.- If this should be a framework-dependent app, add the 'C:\d\TinyXlsx-main\Tests\bin\Release\net8.0\testhost.runtimeconfig.json' file and specify the appropriate framework.
他说:
这个错误是因为你的应用程序缺少运行时配置文件,并且没有正确设置 .NET 运行时的路径。以下是解决方案:
方法一:使用 dotnet 命令运行(推荐)
不要直接运行 testhost.exe
,而是使用 dotnet
命令:
cd C:\d\TinyXlsx-main\Tests\bin\Release\net8.0
dotnet testhost.dll
方法二:发布为自包含应用程序
重新构建项目,指定为自包含发布:
cd C:\d\TinyXlsx-main
dotnet publish Tests.csproj --configuration Release --runtime win-x64 --self-contained true
然后运行发布目录中的可执行文件:
cd C:\d\TinyXlsx-main\Tests\bin\Release\net8.0\win-x64\publish
testhost.exe
方法三:修复环境变量设置
你设置的 DOTNET_ROOT
路径不正确,应该指向包含 hostfxr.dll
的目录:
set DOTNET_ROOT=C:\d\net8
set PATH=%DOTNET_ROOT%;%PATH%
然后重新运行。
方法四:检查并修复运行时配置文件
确保 testhost.runtimeconfig.json
文件存在且内容正确。如果缺失,可以创建该文件:
{"runtimeOptions": {"tfm": "net8.0","framework": {"name": "Microsoft.NETCore.App","version": "8.0.0"}}
}
方法五:重新安装或修复 .NET SDK
如果以上方法都不行,可能需要重新安装 .NET SDK:
- 下载最新的 .NET 8 SDK
- 运行安装程序
- 确保环境变量正确设置
最简单的解决方案
直接使用这个命令:
cd C:\d\TinyXlsx-main
dotnet test
这会自动运行测试项目,无需手动处理运行时配置问题。
建议使用方法一或直接使用 dotnet test
命令,这是最标准的运行 .NET 测试方式。
我实验了一下,dotnet test
命令可以执行成功,如下所示
cd C:\d\TinyXlsx-mainC:\d\TinyXlsx-main>dotnet test正在确定要还原的项目…所有项目均是最新的,无法还原。TinyXlsx -> C:\d\TinyXlsx-main\TinyXlsx\bin\Debug\net8.0\TinyXlsx.dllTests -> C:\d\TinyXlsx-main\Tests\bin\Debug\net8.0\Tests.dll
C:\d\TinyXlsx-main\Tests\bin\Debug\net8.0\Tests.dll (.NETCoreApp,Version=v8.0)的测试运行
VSTest 版本 17.11.1 (x64)正在启动测试执行,请稍候...
总共 1 个测试文件与指定模式相匹配。已通过! - 失败: 0,通过: 33,已跳过: 0,总计: 33,持续时间: 2 s - Tests.dll (net8.0)
其他命令仍然有错,看生成的文件名后缀,都是dll,可能是动态链接库,需要一个exe文件来调用,才能执行。
从TinyXlsx项目github主页剪切了如下代码,继续问DeepSeek怎么才能执行。
using TinyXlsx;using var workbook = new Workbook("fileName.xlsx");
var worksheet = workbook.BeginSheet();for (var i = 1; i <= 100; i++)
{worksheet.BeginRow().WriteCellValue(true).WriteCellValue(123456).WriteCellValue(123.456m).WriteCellValue(123.456).WriteCellValue(DateTime.Now).WriteCellValue(DateTime.Now, "yyyy/MM/dd").WriteCellValue("Text")
}
workbook.Close();
他的回答
你可以创建一个简单的控制台应用程序来运行这个代码生成 Excel 文件。以下是步骤:
方法一:创建控制台应用程序
- 创建新的控制台项目:
dotnet new console -n ExcelGenerator
cd ExcelGenerator
- 添加 TinyXlsx 包引用:
dotnet add package TinyXlsx
- 修改 Program.cs 文件:
using TinyXlsx;class Program
{static void Main(string[] args){using var workbook = new Workbook("fileName.xlsx");var worksheet = workbook.BeginSheet();for (var i = 1; i <= 100; i++){worksheet.BeginRow().WriteCellValue(true).WriteCellValue(123456).WriteCellValue(123.456m).WriteCellValue(123.456).WriteCellValue(DateTime.Now).WriteCellValue(DateTime.Now, "yyyy/MM/dd").WriteCellValue("Text");}workbook.Close();Console.WriteLine("Excel 文件生成完成!");}
}
- 编译并运行:
dotnet run
方法二:直接在现有项目中运行
如果你已经有项目,可以:
- 在 Program.cs 中添加代码:
using TinyXlsx;// 你的代码
using var workbook = new Workbook("fileName.xlsx");
var worksheet = workbook.BeginSheet();for (var i = 1; i <= 100; i++)
{worksheet.BeginRow().WriteCellValue(true).WriteCellValue(123456).WriteCellValue(123.456m).WriteCellValue(123.456).WriteCellValue(DateTime.Now).WriteCellValue(DateTime.Now, "yyyy/MM/dd").WriteCellValue("Text");
}
workbook.Close();
- 运行项目:
dotnet run
方法三:使用单元测试(如果你有测试项目)
在测试项目中创建一个测试方法:
[Test]
public void GenerateExcelFile()
{using var workbook = new Workbook("testFile.xlsx");var worksheet = workbook.BeginSheet();for (var i = 1; i <= 100; i++){worksheet.BeginRow().WriteCellValue(true).WriteCellValue(123456).WriteCellValue(123.456m).WriteCellValue(123.456).WriteCellValue(DateTime.Now).WriteCellValue(DateTime.Now, "yyyy/MM/dd").WriteCellValue("Text");}workbook.Close();Assert.That(File.Exists("testFile.xlsx"), Is.True);
}
然后运行测试:
dotnet test
运行结果
成功运行后,你会在项目目录下找到生成的 fileName.xlsx
文件。文件内容包含:
- 100 行数据
- 每行包含:布尔值、整数、小数、浮点数、日期时间、格式化日期、文本
注意: 确保你有写入当前目录的权限,或者指定完整的文件路径,如:"C:\\temp\\fileName.xlsx"
我用方法一执行dotnet run成功,在当前目录下生成了testFile.xlsx,内容也正确。从编译生成的目标文件执行,也成功了。注意其实并不需要我提前下载tinyxlsx源代码,dotnet add package TinyXlsx
命令会自动从存储库下载。
C:\d>dotnet new console -n wxlsx
已成功创建模板“控制台应用”。正在处理创建后操作...
正在还原 C:\d\wxlsx\wxlsx.csproj:正在确定要还原的项目…已还原 C:\d\wxlsx\wxlsx.csproj (用时 51 毫秒)。
已成功还原。C:\d>cd wxlsxC:\d\wxlsx>dotnet add package TinyXlsx正在确定要还原的项目…Writing C:\Users\lt\AppData\Local\Temp\tmpnhly1b.tmp
info : X.509 证书链验证将使用 .NET 选择的默认信任存储进行代码签名。
info : X.509 证书链验证将使用 .NET 选择的默认信任存储进行时间戳。
info : 正在将包“TinyXlsx”的 PackageReference 添加到项目“C:\d\wxlsx\wxlsx.csproj”。
info : GET https://api.nuget.org/v3/registration5-gz-semver2/tinyxlsx/index.json
info : OK https://api.nuget.org/v3/registration5-gz-semver2/tinyxlsx/index.json 194 毫秒
info : 正在还原 C:\d\wxlsx\wxlsx.csproj 的包...
info : GET https://api.nuget.org/v3-flatcontainer/tinyxlsx/index.json
info : OK https://api.nuget.org/v3-flatcontainer/tinyxlsx/index.json 303 毫秒
info : GET https://api.nuget.org/v3-flatcontainer/tinyxlsx/0.2.0/tinyxlsx.0.2.0.nupkg
info : OK https://api.nuget.org/v3-flatcontainer/tinyxlsx/0.2.0/tinyxlsx.0.2.0.nupkg 316 毫秒
info : 已使用内容哈希 r8vOZYoY7y/pw5Jf6/4b2Lq1+b/STX0KdX6HKcnuSdv+cHmDFADsifgEV65QNiFhgvI6f4+iAGXfc/Y4NkHZQQ== 从 https://api.nuget.org/v3/index.json 到 C:\Users\lt\.nuget\packages\tinyxlsx\0.2.0 安装 TinyXlsx 0.2.0。
info : GET https://api.nuget.org/v3/vulnerabilities/index.json
info : OK https://api.nuget.org/v3/vulnerabilities/index.json 185 毫秒
info : GET https://api.nuget.org/v3/vulnerabilities/vulnerability.base.json
info : GET https://api.nuget.org/v3/vulnerabilities/vulnerability.update.json
info : OK https://api.nuget.org/v3/vulnerabilities/vulnerability.base.json 278 毫秒
info : OK https://api.nuget.org/v3/vulnerabilities/vulnerability.update.json 515 毫秒
info : 包“TinyXlsx”与项目“C:\d\wxlsx\wxlsx.csproj”中指定的所有框架均兼容。
info : 包“TinyXlsx”(版本为 0.2.0)的 PackageReference 已添加到文件“C:\d\wxlsx\wxlsx.csproj”。
info : 将资产文件写入磁盘。路径: C:\d\wxlsx\obj\project.assets.json
log : 已还原 C:\d\wxlsx\wxlsx.csproj (用时 2.25 秒)。C:\d\wxlsx>dotnet run
Excel 文件生成完成!C:\d\wxlsx>cd C:\d\wxlsx\bin\Debug\net8.0C:\d\wxlsx\bin\Debug\net8.0>wxlsx
Excel 文件生成完成!
为了测试写xlsx文件的效率,让他每行随机生成不同的数字、日期、字符串,结果如下
using TinyXlsx;
using System;class Program
{static void Main(string[] args){var random = new Random();using var workbook = new Workbook("fileName.xlsx");var worksheet = workbook.BeginSheet();for (var i = 1; i <= 100; i++){// 生成随机数据var randomBool = random.Next(2) == 1;var randomInt = random.Next(1000000);var randomDecimal = (decimal)(random.NextDouble() * 1000);var randomDouble = random.NextDouble() * 1000;var randomDate = DateTime.Now.AddDays(random.Next(-365, 365));var randomText = $"Text_{random.Next(1000)}_{Guid.NewGuid().ToString().Substring(0, 8)}";worksheet.BeginRow().WriteCellValue(randomBool).WriteCellValue(randomInt).WriteCellValue(randomDecimal).WriteCellValue(randomDouble).WriteCellValue(randomDate).WriteCellValue(randomDate, "yyyy/MM/dd").WriteCellValue(randomText);}workbook.Close();Console.WriteLine("Excel 文件生成完成!");}
}
我把循环上限改为1000000,用前面的编译本地文件命令生成的文件执行。
C:\d\wxlsx>dotnet publish wxlsx.csproj --configuration Release --runtime win-x64 --self-contained true正在确定要还原的项目…所有项目均是最新的,无法还原。wxlsx -> C:\d\wxlsx\bin\Release\net8.0\win-x64\wxlsx.dllwxlsx -> C:\d\wxlsx\bin\Release\net8.0\win-x64\publish\C:\d\wxlsx>..\timer64 C:\d\wxlsx\bin\Release\net8.0\win-x64\publish\wxlsx
Excel 文件生成完成!Kernel Time = 0.171 = 6%
User Time = 2.328 = 92%
Process Time = 2.500 = 99% Virtual Memory = 17 MB
Global Time = 2.506 = 100% Physical Memory = 37 MB
2秒钟生成了100万行7列的xlsx文件,大小是76MB,用压缩工具检查,它包含共享字符串sharedStrings.xml文件,但其中没有条目,每个字符串都内联保存在sheet1.xml中。
补记
继续下载了.NET 8.0 SDK Linux版, 在WSL中体验,结果操作与windows版几乎完全一致,而且比Windows版更好的是,在下载成功页面提供了详细配置命令。以下是操作步骤
:/mnt/c/d# mkdir dotnet
:/mnt/c/d# cd dotnet
:/mnt/c/d/dotnet# tar xf ../dotnet-sdk-8.0.413-linux-x64.tar.gz
:/mnt/c/d/dotnet# export DOTNET_ROOT=/mnt/c/d/dotnet
:/mnt/c/d/dotnet# export PATH=$PATH:/mnt/c/d/dotnet:/mnt/c/d# dotnet new console -n lxlsx
:/mnt/c/d# cd lxlsx
:/mnt/c/d/lxlsx# dotnet add package TinyXlsx修改Program.cs并保存:/mnt/c/d/lxlsx# dotnet publish lxlsx.csproj --configuration Release --runtime linux-x64 --self-contained trueDetermining projects to restore...Restored /mnt/c/d/lxlsx/lxlsx.csproj (in 5.9 sec).lxlsx -> /mnt/c/d/lxlsx/bin/Release/net8.0/linux-x64/lxlsx.dlllxlsx -> /mnt/c/d/lxlsx/bin/Release/net8.0/linux-x64/publish/
:/mnt/c/d/lxlsx# time /mnt/c/d/lxlsx/bin/Release/net8.0/linux-x64/publish/lxlsx
Excel 文件生成完成!real 0m5.609s
user 0m3.271s
sys 0m0.458s
生成时间略长,生成的文件也略大,约83MB。