12 KiB
title | sidebar_label | description | pagination_prev | pagination_next |
---|---|---|---|---|
Sheets in .NET with Jint | C# + Jint | Process structured data in C#. Seamlessly integrate spreadsheets into your program by pairing Jint and SheetJS. Handle the most complex Excel files without breaking a sweat. | demos/bigdata/index | solutions/input |
import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock';
Jint1 is a JavaScript interpreter for .NET Standard and .NET Core. It has
built-in support for binary data with .NET byte[]
and ES6 Uint8Array
.
SheetJS is a JavaScript library for reading and writing data from spreadsheets.
This demo uses Jint and SheetJS to read and write spreadsheets. We'll explore how to load SheetJS in the Jint engine, exchange binary data with a C# program, and process spreadsheets and structured data.
The "Integration Example" section includes a complete command-line tool for reading arbitrary workbooks and writing data to XLSB (Excel 2007+ Binary Format) workbooks.
:::warning Telemetry
The dotnet
command embeds telemetry.
The DOTNET_CLI_TELEMETRY_OPTOUT
environment variable should be set to 1
.
"Platform Configuration" includes instructions for setting the environment variable on supported platforms.
:::
Integration Details
:::note pass
Most of the integration functions are not documented. This explanation is based
on version 3.0.0-beta-2051
.
:::
The SheetJS Standalone scripts can be parsed and evaluated in a Jint engine instance.
Initialize Jint
A Jint.Engine
object can be created in one line:
var engine = new Jint.Engine();
Jint does not expose the NodeJS global
but does provide globalThis
. Using
Jint.Engine#Evaluate
, a global
global variable can be created:
The JS code is
global = globalThis;
engine.Evaluate("global = globalThis");
Load SheetJS Scripts
The main library can be loaded by reading the scripts from the file system with
System.IO.File.ReadAllText
and evaluating in the Jint engine instance:
/* read and evaluate the shim script */
string src = System.IO.File.ReadAllText("shim.min.js");
engine.Evaluate(src);
/* read and evaluate the main library */
engine.Evaluate(System.IO.File.ReadAllText("xlsx.full.min.js"));
To confirm the library is loaded, XLSX.version
can be inspected:
Console.WriteLine("SheetJS version {0}", engine.Evaluate("XLSX.version"));
:::info pass
The Jint Evaluate
method returns a generic Jint.Native.JsValue
object.
When the JS expression returns a string, the JsValue
object is an instance of
Jint.Native.JsString
. C# ToString
will return the underlying string
value.
:::
Reading Files
In C#, System.IO.File.ReadAllBytes
reads file data into a byte[]
byte array:
string filename = "pres.xlsx";
byte[] buf = File.ReadAllBytes(filename);
Jint natively supports Uint8Array
construction from the byte array:
Jint.Native.JsValue u8 = engine.Realm.Intrinsics.Uint8Array.Construct(buf);
Jint.Engine#SetValue
will assign the Uint8Array
to a scope variable in JS:
engine.SetValue("buf", u8);
The buf
variable can be parsed from JS with the SheetJS read
method2:
The JS code is
var wb = XLSX.read(buf);
engine.Evaluate("var wb = XLSX.read(buf);");
wb
is a SheetJS workbook object. The "SheetJS Data Model" section
describes the object structure and the "API Reference" section
describes various helper functions.
Writing Files
The SheetJS write
method3 can write workbooks. The option type: "buffer"
instructs the library to generate Uint8Array
objects.
The JS code for exporting to the XLSB format is:
var u8 = XLSX.write(wb, {bookType: 'xlsb', type: 'buffer'});
The file format can be changed with the bookType
option4
Jint.Native.JsValue xlsb = engine.Evaluate("XLSX.write(wb, {bookType: 'xlsb', type: 'buffer'})");
xlsb
represents a Uint8Array
. xlsb.AsUint8Array()
returns the bytes as a
byte[]
array which can be exported with System.IO.File.WriteAllBytes
:
byte[] outfile = xlsb.AsUint8Array();
System.IO.File.WriteAllBytes("SheetJSJint.xlsb", outfile);
Integration Example
:::note
This demo was tested in the following deployments:
Architecture | Jint Version | Date |
---|---|---|
darwin-x64 |
3.0.0-beta-2051 |
2023-09-16 |
win10-x64 |
3.0.0-beta-2051 |
2023-09-16 |
:::
- Install .NET5
Platform Configuration
- Set the
DOTNET_CLI_TELEMETRY_OPTOUT
environment variable to1
.
How to disable telemetry (click to hide)
Add the following line to .profile
, .bashrc
and .zshrc
:
export DOTNET_CLI_TELEMETRY_OPTOUT=1
Close and restart the Terminal to load the changes.
Type env
in the search bar and select "Edit the system environment variables".
In the new window, click the "Environment Variables..." button.
In the new window, look for the "System variables" section and click "New..."
Set the "Variable name" to DOTNET_CLI_TELEMETRY_OPTOUT
and the value to 1
.
Click "OK" in each window (3 windows) and restart your computer.
- Open a new Terminal window in macOS or PowerShell window in Windows.
Base Project
- Create a new folder
SheetJSJint
and a new project using thedotnet
tool:
rm -rf SheetJSJint
mkdir SheetJSJint
cd SheetJSJint
dotnet new console --framework net6.0
dotnet run
- Add Jint using the NuGet tool:
dotnet nuget add source https://www.myget.org/F/jint/api/v3/index.json
dotnet add package Jint --version 3.0.0-beta-2051
To verify Jint is installed, replace Program.cs
with the following:
var engine = new Jint.Engine();
Console.WriteLine("Hello {0}", engine.Evaluate("'Sheet' + 'JS'"));
After saving, run the program:
dotnet run
The terminal should display Hello SheetJS
Add SheetJS
- Download the standalone script, shim and test file:
- xlsx.full.min.js
- shim.min.js
- pres.xlsx
{\ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js curl -LO https://sheetjs.com/pres.xlsx
}
- Replace
Program.cs
with the following:
var engine = new Jint.Engine();
engine.Evaluate("global = globalThis;");
engine.Evaluate(File.ReadAllText("shim.min.js"));
engine.Evaluate(File.ReadAllText("xlsx.full.min.js"));
Console.WriteLine("SheetJS version {0}", engine.Evaluate("XLSX.version"));
After saving, run the program:
dotnet run
The terminal should display SheetJS version {current}
Read and Write Files
- Replace
Program.cs
with the following:
using Jint;
/* Initialize Jint */
var engine = new Jint.Engine();
engine.Evaluate("global = globalThis;");
/* Load SheetJS Scripts */
engine.Evaluate(File.ReadAllText("shim.min.js"));
engine.Evaluate(File.ReadAllText("xlsx.full.min.js"));
Console.WriteLine("SheetJS version {0}", engine.Evaluate("XLSX.version"));
/* Read and Parse File */
byte[] filedata = File.ReadAllBytes(args[0]);
Jint.Native.JsValue u8 = engine.Realm.Intrinsics.Uint8Array.Construct(filedata);
engine.SetValue("buf", u8);
engine.Evaluate("var wb = XLSX.read(buf);");
/* Print CSV of first worksheet*/
engine.Evaluate("var ws = wb.Sheets[wb.SheetNames[0]];");
Jint.Native.JsValue csv = engine.Evaluate("XLSX.utils.sheet_to_csv(ws)");
Console.Write(csv);
/* Generate XLSB file and save to SheetJSJint.xlsb */
Jint.Native.JsValue xlsb = engine.Evaluate("XLSX.write(wb, {bookType: 'xlsb', type: 'buffer'})");
File.WriteAllBytes("SheetJSJint.xlsb", xlsb.AsUint8Array());
After saving, run the program and pass the test file name as an argument:
dotnet run pres.xlsx
If successful, the program will print the contents of the first sheet as CSV
rows. It will also create SheetJSJint.xlsb
which can be opened in Excel or
another spreadsheet editor.
:::caution pass
If the using Jint;
directive is omitted, the build will fail:
'JsValue' does not contain a definition for 'AsUint8Array' and no accessible extension method 'AsUint8Array' accepting a first argument of type 'JsValue' could be found
:::
Standalone Application
- Find the runtime identifier (RID) for your platform6. The RID values for tested platforms are listed below:
Platform | RID |
---|---|
Intel Mac | osx-x64 |
Windows 10 (x64) | win10-x64 |
- Build the standalone application. Replace
$RID
with the real value in:
dotnet publish -c Release -r $RID --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=true
Tested platforms (click to hide)
For Intel Mac, the RID is osx-x64
and the command is
dotnet publish -c Release -r osx-x64 --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=true
For Windows 10 x64, the RID is win10-x64
and the command is:
dotnet publish -c Release -r win10-x64 --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=true
- Copy the generated executable to the project directory.
The build from step 9 is placed in bin\Release\net6.0\$RID\publish
and the
binary name will be SheetJSJint
or SheetJSJint.exe
depending on OS.
Tested platforms (click to hide)
For Intel Mac, the RID is osx-x64
and the command is:
cp bin/Release/net6.0/osx-x64/publish/SheetJSJint .
For Windows 10 x64, the RID is win10-x64
and the command is:
copy .\bin\Release\net6.0\win10-x64\publish\SheetJSJint.exe .
- Run the generated command.
./SheetJSJint pres.xlsx
.\SheetJSJint pres.xlsx
-
The Jint project recommends the "MyGet" service. According to the developers, the "NuGet" package is "occasionally published". ↩︎
-
See "Supported Output Formats" in "Writing Files" for details on
bookType
↩︎ -
At the time of writing, https://dotnet.microsoft.com/en-us/download is the official endpoint. ↩︎
-
See ".NET RID Catalog" in the .NET documentation ↩︎