Skip to main content

使用 Duktape 进行数据处理

Duktape 是一个用 C 编写的嵌入式 JS 引擎。它已被移植到许多奇异的体系结构和操作系统。

¥Duktape is an embeddable JS engine written in C. It has been ported to a number of exotic architectures and operating systems.

SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。

¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.

"完整示例" 部分包括一个完整的命令行工具,用于从电子表格读取数据并导出到 Excel XLSB 工作簿。"绑定" 涵盖其他生态系统的绑定。

¥The "Complete Example" section includes a complete command-line tool for reading data from spreadsheets and exporting to Excel XLSB workbooks. "Bindings" covers bindings for other ecosystems.

集成详情​

¥Integration Details

初始化 Duktape​

¥Initialize Duktape

Duktape 不提供 global 变量。它可以在一行中创建:

¥Duktape does not provide a global variable. It can be created in one line:

/* initialize */
duk_context *ctx = duk_create_heap_default();

/* duktape does not expose a standard "global" by default */
duk_eval_string_noresult(ctx, "var global = (function(){ return this; }).call(null);");

加载 SheetJS 脚本​

¥Load SheetJS Scripts

SheetJS 独立脚本 可以在 Duktape 上下文中进行解析和评估。

¥The SheetJS Standalone scripts can be parsed and evaluated in a Duktape context.

可以通过从文件系统读取脚本并在 Duktape 上下文中进行评估来加载垫片和主库:

¥The shim and main libraries can be loaded by reading the scripts from the file system and evaluating in the Duktape context:

/* simple wrapper to read the entire script file */
static duk_int_t eval_file(duk_context *ctx, const char *filename) {
size_t len;
/* read script from filesystem */
FILE *f = fopen(filename, "rb");
if(!f) { duk_push_undefined(ctx); perror("fopen"); return 1; }
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
char *buf = (char *)malloc(fsize * sizeof(char));
len = fread((void *) buf, 1, fsize, f);
fclose(f);
if(!buf) { duk_push_undefined(ctx); perror("fread"); return 1; }

/* load script into the context */
duk_push_lstring(ctx, (const char *)buf, (duk_size_t)len);
/* eval script */
duk_int_t retval = duk_peval(ctx);
/* cleanup */
duk_pop(ctx);
return retval;
}

// ...
duk_int_t res = 0;

if((res = eval_file(ctx, "shim.min.js")) != 0) { /* error handler */ }
if((res = eval_file(ctx, "xlsx.full.min.js")) != 0) { /* error handler */ }

要确认库已加载,可以检查 XLSX.version:

¥To confirm the library is loaded, XLSX.version can be inspected:

  /* get version string */
duk_eval_string(ctx, "XLSX.version");
printf("SheetJS library version %s\n", duk_get_string(ctx, -1));
duk_pop(ctx);

读取文件​

¥Reading Files

Duktape 本身支持 Buffer,但应在处理前进行切片。假设 buf 是一个 C 字节数组,长度为 len,此片段解析数据:

¥Duktape supports Buffer natively but should be sliced before processing. Assuming buf is a C byte array, with length len, this snippet parses data:

/* load C char array and save to a Buffer */
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, buf, len);
duk_put_global_string(ctx, "buf");

/* parse with SheetJS */
duk_eval_string_noresult(ctx, "workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");

workbook 将是 JS 环境中的一个变量,可以使用各种 SheetJS API 函数进行检查。

¥workbook will be a variable in the JS environment that can be inspected using the various SheetJS API functions.

写入文件​

¥Writing Files

duk_get_buffer_data 可以将 Buffer 对象数据拉入 C 代码中:

¥duk_get_buffer_data can pull Buffer object data into the C code:

/* write with SheetJS using type: "array" */
duk_eval_string(ctx, "XLSX.write(workbook, {type:'array', bookType:'xlsx'})");

/* pull result back to C */
duk_size_t sz;
char *buf = (char *)duk_get_buffer_data(ctx, -1, sz);

/* discard result in duktape */
duk_pop(ctx);

生成的 buf 可以用 fwrite 写入文件。

¥The resulting buf can be written to file with fwrite.

完整示例​

¥Complete Example

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本日期
darwin-x642.7.02025-03-31
darwin-arm2.7.02025-02-13
win11-x642.7.02025-04-28
win11-arm2.7.02025-02-23
linux-x642.7.02025-04-21
linux-arm2.7.02025-02-15

该程序解析文件并打印第一个工作表中的 CSV 数据。它还生成 XLSB 文件并写入文件系统。

¥This program parses a file and prints CSV data from the first worksheet. It also generates an XLSB file and writes to the filesystem.

流程图显示在示例步骤之后

¥The flow diagram is displayed after the example steps

Windows 构建需要带有 "使用 C++ 进行桌面开发" 的 Visual Studio。命令必须在 "原生工具命令提示符" 会话中运行。

¥The Windows build requires Visual Studio with "Desktop development with C++". Commands must be run in a "Native Tools Command Prompt" session.

  1. 创建项目文件夹:

    ¥Create a project folder:

mkdir sheetjs-duk
cd sheetjs-duk
  1. 下载并解压 Duktape:

    ¥Download and extract Duktape:

curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
mv duktape-2.7.0/src/*.{c,h} .
  1. 下载 SheetJS Standalone 脚本、shim 脚本和测试文件。将所有三个文件移动到项目目录:

    ¥Download the SheetJS Standalone script, shim script and test file. Move all three files to the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载 sheetjs.duk.c:

    ¥Download sheetjs.duk.c:

curl -LO https://xlsx.nodejs.cn/duk/sheetjs.duk.c
  1. 编译独立的 sheetjs.duk 二进制文件

    ¥Compile standalone sheetjs.duk binary

gcc -std=c99 -Wall -osheetjs.duk sheetjs.duk.c duktape.c -lm

GCC 可能会生成警告:

¥GCC may generate a warning:

duk_js_compiler.c:5628:13: warning: variable 'num_stmts' set but not used [-Wunused-but-set-variable]
duk_int_t num_stmts;
^

可以忽略此警告。

¥This warning can be ignored.

  1. 运行演示:

    ¥Run the demo:

./sheetjs.duk pres.numbers

如果程序成功,CSV 内容将打印到控制台并创建文件 sheetjsw.xlsb。该文件可以用 Excel 打开。

¥If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with Excel.

流程图​

¥Flow Diagram

绑定​

¥Bindings

许多语言都存在绑定。由于这些绑定需要 "native" 代码,因此它们可能无法在每个平台上工作。

¥Bindings exist for many languages. As these bindings require "native" code, they may not work on every platform.

Duktape 源代码发行版包含一个单独的 Makefile,用于构建共享库。该库可以加载到其他程序中。

¥The Duktape source distribution includes a separate Makefile for building a shared library. This library can be loaded in other programs.

Blingos​

Duktape 包含许多 "blingos"(类函数宏),这些宏不会包含在共享库中。必须手动扩展宏。

¥Duktape includes a number of "blingos" (function-like macros) which will not be included in the shared library. The macros must be manually expanded.

例如,duk_create_heap_default 定义如下:

¥For example, duk_create_heap_default is defined as follows:

#define duk_create_heap_default() \
duk_create_heap(NULL, NULL, NULL, NULL, NULL)

duk_create_heap_default blingo 不会在共享库中定义。相反,必须直接调用 duk_create_heap。使用 PHP FFI:

¥The duk_create_heap_default blingo will not be defined in the shared library. Instead, duk_create_heap must be called directly. Using PHP FFI:

/* create new FFI object */
$ffi = FFI::cdef(/* ... arguments */);

/* call duk_create_heap directly */
$context = $ffi->duk_create_heap(null, null, null, null, null);

空指针​

¥Null Pointers

在某些函数中必须使用 C NULL 指针。某些 FFI 实现具有与语言原生空值不同的特殊值。使用 Python,返回类型提示由 restype 属性指定:

¥The C NULL pointer must be used in some functions. Some FFI implementations have special values distinct from the language-native null value. Using Python, return type hints are specified with the restype property:

from ctypes import CDLL, c_void_p

duk = CDLL("libduktape.so")

duk.duk_create_heap.restype = c_void_p
context = duk.duk_create_heap(None, None, None, None, None)

PHP​

Duktape 库没有官方 PHP 绑定。相反,此演示使用 Duktape 共享库的原始 FFI 接口 [^1]。

¥There is no official PHP binding to the Duktape library. Instead, this demo uses the raw FFI interface[^1] to the Duktape shared library.

SheetJSDuk.php 演示脚本解析文件,打印第一个工作表中的 CSV 行,并创建 XLSB 工作簿。

¥The SheetJSDuk.php demo script parses a file, prints CSV rows from the first worksheet, and creates a XLSB workbook.

PHP 演示​

¥PHP Demo

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本PHP日期
darwin-x642.7.08.4.22025-03-31
darwin-arm2.7.08.4.42025-02-25
linux-x642.7.08.3.62025-04-21
linux-arm2.7.08.2.262025-02-15
  1. 确保 php 已安装并在系统路径上可用

    ¥Ensure php is installed and available on the system path

  2. 找到 php.ini 文件:

    ¥Find the php.ini file:

php --ini

以下输出来自最近的 darwin-x64 测试:

¥The following output is from the most recent darwin-x64 test:

Configuration File (php.ini) Path: /usr/local/etc/php/8.4
Loaded Configuration File: /usr/local/etc/php/8.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/8.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/8.4/conf.d/ext-opcache.ini
  1. 编辑 php.ini 配置文件。

    ¥Edit the php.ini configuration file.

配置中应出现以下行:

¥The following line should appear in the configuration:

php.ini (add to end)
extension=ffi

如果该行以 ; 为前缀,请删除分号。如果该行未出现在文件中,请将其添加到末尾。

¥If this line is prefixed with a ;, remove the semicolon. If this line does not appear in the file, add it to the end.

在 Linux 和 macOS 上,文件可能归 root 用户所有。如果使用普通用户账户写入文件失败,请使用 sudo 启动文本编辑器。

¥On Linux and macOS, the file may be owned by the root user. If writing the file fails with a normal user account, use sudo to launch the text editor.

  1. 构建 Duktape 共享库:

    ¥Build the Duktape shared library:

curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
cd duktape-2.7.0
make -f Makefile.sharedlibrary
cd ..
  1. 将共享库复制到当前文件夹。上次测试演示时,共享库文件名因平台而异:

    ¥Copy the shared library to the current folder. When the demo was last tested, the shared library file name differed by platform:

OSname
达尔文libduktape.207.20700.so
Linuxlibduktape.so.207.20700
cp duktape-*/libduktape.* .
  1. 下载 SheetJS Standalone 脚本、shim 脚本和测试文件。将所有三个文件移动到项目目录:

    ¥Download the SheetJS Standalone script, shim script and test file. Move all three files to the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载 SheetJSDuk.php:

    ¥Download SheetJSDuk.php:

curl -LO https://xlsx.nodejs.cn/duk/SheetJSDuk.php
  1. 编辑 SheetJSDuk.php 脚本。

    ¥Edit the SheetJSDuk.php script.

$sofile 变量声明库的路径:

¥The $sofile variable declares the path to the library:

SheetJSDuk.php (edit highlighted line)
<?php

$sofile = './libduktape.207.20700.so';

库的名称是 libduktape.207.20700.so:

¥The name of the library is libduktape.207.20700.so:

SheetJSDuk.php (change highlighted line)
$sofile = './libduktape.207.20700.so';
  1. 运行脚本:

    ¥Run the script:

php SheetJSDuk.php pres.numbers

如果程序成功,CSV 内容将打印到控制台并创建文件 sheetjsw.xlsb。该文件可以用 Excel 打开。

¥If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with Excel.

Python​

Duktape 库没有官方的 Python 绑定。相反,此演示使用 Duktape 共享库的原始 ctypes 接口 [^2]。

¥There is no official Python binding to the Duktape library. Instead, this demo uses the raw ctypes interface[^2] to the Duktape shared library.

Python 演示​

¥Python Demo

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本Python日期
darwin-x642.7.03.13.12025-03-31
darwin-arm2.7.03.12.32025-03-30
linux-x642.7.03.12.32025-04-21
linux-arm2.7.03.11.22025-02-15
  1. 确保 python3 已安装并且在系统路径上可用。

    ¥Ensure python3 is installed and available on the system path.

  2. 构建 Duktape 共享库:

    ¥Build the Duktape shared library:

curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
cd duktape-2.7.0
make -f Makefile.sharedlibrary
cd ..
  1. 将共享库复制到当前文件夹。上次测试演示时,共享库文件名因平台而异:

    ¥Copy the shared library to the current folder. When the demo was last tested, the shared library file name differed by platform:

OSname
达尔文libduktape.207.20700.so
Linuxlibduktape.so.207.20700
cp duktape-*/libduktape.* .
  1. 下载 SheetJS Standalone 脚本、shim 脚本和测试文件。将所有三个文件移动到项目目录:

    ¥Download the SheetJS Standalone script, shim script and test file. Move all three files to the project directory:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载 SheetJSDuk.py:

    ¥Download SheetJSDuk.py:

curl -LO https://xlsx.nodejs.cn/duk/SheetJSDuk.py
  1. 编辑 SheetJSDuk.py 脚本。

    ¥Edit the SheetJSDuk.py script.

lib 变量声明库的路径:

¥The lib variable declares the path to the library:

SheetJSDuk.py (edit highlighted line)
#!/usr/bin/env python3

lib = "libduktape.207.20700.so"

库的名称是 libduktape.207.20700.so:

¥The name of the library is libduktape.207.20700.so:

SheetJSDuk.py (change highlighted line)
lib = "libduktape.207.20700.so"
  1. 运行脚本:

    ¥Run the script:

python3 SheetJSDuk.py pres.numbers

如果程序成功,CSV 内容将打印到控制台并创建文件 sheetjsw.xlsb。该文件可以用 Excel 打开。

¥If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with Excel.

在某些测试中,命令失败并显示 OSError 消息:

¥In some tests, the command failed with an OSError message:

OSError: libduktape.so.207.20700: cannot open shared object file: No such file or directory

解决方法是将 ./ 明确添加到 SheetJSDuk.py 中的 lib 变量:

¥The fix is to explicitly add ./ to the lib variable in SheetJSDuk.py:

库的名称是 libduktape.207.20700.so:

¥The name of the library is libduktape.207.20700.so:

SheetJSDuk.py (change highlighted line)
lib = "./libduktape.207.20700.so"

Zig​

Zig 支持被认为是实验性的。

优秀的开源软件会随着用户测试和报告而不断成长。任何问题都应报告给 Zig 项目以进行进一步诊断。

¥Great open source software grows with user tests and reports. Any issues should be reported to the Zig project for further diagnosis.

Zig 编译​

¥Zig Compilation

主 Duktape 代码可以添加到 Zig 构建管道中。

¥The main Duktape code can be added to the Zig build pipeline.

以下说明已针对 Zig 0.14.0 进行了验证。

¥The following explanation was verified against Zig 0.14.0.

由于 Zig C 集成的限制,必须将 Duktape src 文件夹的路径添加到包含路径列表中:

¥Due to restrictions in the Zig C integration, the path to the Duktape src folder must be added to the include path list:

build.zig
    const exe = b.addExecutable(.{
// ...
});
// this line is required to make @cInclude("duktape.h") work
exe.addIncludePath(b.path("duktape-2.7.0/src"));

duktape.c 源文件必须添加到构建序列中。对于 Zig 版本 0.14.0,Duktape 必须使用标志 -std=c99 -fno-sanitize=undefined 进行编译,并链接到 libc 和 libm:

¥The duktape.c source file must be added to the build sequence. For Zig version 0.14.0, Duktape must be compiled with flags -std=c99 -fno-sanitize=undefined and linked against libc and libm:

build.zig
    const exe = b.addExecutable(.{
// ...
});
exe.addCSourceFile(.{:
.file = b.path("duktape-2.7.0/src/duktape.c"),
.flags = &.{ "-std=c99", "-fno-sanitize=undefined" }
});
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("m");

Zig 导入​

¥Zig Import

可以使用 @cImport 指令导入 duktape.h:

¥duktape.h can be imported using the @cImport directive:

main.zig
const duktape = @cImport({
@cInclude("duktape.h");
});

导入后,可以从 duktape 范围引用许多 API 函数。例如,C 接口中的 duk_peval_string 将可用于使用名称 duktape.duk_peval_string 的 Zig 代码。

¥Once imported, many API functions can be referenced from the duktape scope. For example, duk_peval_string in the C interface will be available to Zig code using the name duktape.duk_peval_string.

强烈建议使用 defer 并置分配和清理方法。例如,Duktape 上下文是使用 duk_create_heap 创建的,并使用 duk_destroy_heap 销毁的。后一个调用可以推迟:

¥It is strongly recommended to colocate allocations and cleanup methods using defer. For example, a Duktape context is created with duk_create_heap and destroyed with duk_destroy_heap. The latter call can be deferred:

Colocating cleanup methods with defer
    const ctx = duktape.duk_create_heap(null, null, null, null, null);
defer _ = duktape.duk_destroy_heap(ctx);

Zig 翻译器注意事项​

¥Zig Translator Caveats

Zig 转换器无法正确处理 blingo void 角色。例如,duk_eval_string_noresult 是 duktape.h 中定义的类函数宏:

¥The Zig translator does not properly handle blingo void casts. For example, duk_eval_string_noresult is a function-like macro defined in duktape.h:

duk_eval_string_noresult blingo
#define duk_eval_string_noresult(ctx,src)  \
((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))

编译器将抛出涉及 anyopaque (C void) 的错误:

¥The compiler will throw an error involving anyopaque (C void):

error: opaque return type 'anyopaque' not allowed

blingo 执行 void 强制转换以抑制某些 C 编译器警告。Zig 中的精神等价物是分配给 _。

¥The blingo performs a void cast to suppress certain C compiler warnings. The spiritual equivalent in Zig is to assign to _.

duk_eval_raw 方法和每个编译时常量在 duktape 范围内可用。手动翻译如下:

¥The duk_eval_raw method and each compile-time constant are available in the duktape scope. A manual translation is shown below:

duk_eval_string_noresult blingo in Zig
_ = duktape.duk_eval_raw(ctx, src, 0, 0 | duktape.DUK_COMPILE_EVAL | duktape.DUK_COMPILE_NOSOURCE | duktape.DUK_COMPILE_STRLEN | duktape.DUK_COMPILE_NORESULT | duktape.DUK_COMPILE_NOFILENAME);

Zig 演示​

¥Zig Demo

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本Zig日期
darwin-x642.7.00.14.02025-03-31
darwin-arm2.7.00.13.02025-02-13
win11-x642.7.00.14.02025-04-28
win11-arm2.7.00.13.02025-02-23
linux-x642.7.00.14.02025-04-21
linux-arm2.7.00.13.02025-02-15

在 Windows 上,由于 WSL 和 PowerShell 之间不兼容,某些命令必须在 WSL Bash 中运行。

¥On Windows, due to incompatibilities between WSL and PowerShell, some commands must be run in WSL Bash.

  1. 创建一个新的项目文件夹:

    ¥Create a new project folder:

mkdir sheetjs-zig
cd sheetjs-zig
  1. 从 https://ziglang.org/download/ 下载 Zig 压缩包并解压到项目文件夹。

    ¥Download the Zig tarball from https://ziglang.org/download/ and extract to the project folder.

对于 X64 Mac:

¥For X64 Mac:

curl -LO https://ziglang.org/download/0.14.0/zig-macos-x86_64-0.14.0.tar.xz
tar -xzf zig-macos-*.tar.xz

对于 ARM64 Mac:

¥For ARM64 Mac:

curl -LO https://ziglang.org/download/0.13.0/zig-macos-aarch64-0.13.0.tar.xz
tar -xzf zig-macos-*.tar.xz
  1. 初始化一个项目:

    ¥Initialize a project:

./zig-*/zig init
  1. 下载 Duktape 源代码并解压到当前目录中。在 Windows 上,命令应在 WSL 中运行:

    ¥Download the Duktape source and extract in the current directory. On Windows, the commands should be run within WSL:

curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
  1. 下载 SheetJS Standalone 脚本、shim 脚本和测试文件。将所有三个文件移至 src 子目录:

    ¥Download the SheetJS Standalone script, shim script and test file. Move all three files to the src subdirectory:

以下命令可以在 macOS 和 Linux 上的 shell 中运行。在 Windows 上,命令应在 WSL bash 中运行:

¥The following commands can be run within a shell on macOS and Linux. On Windows, the commands should be run within WSL bash:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://xlsx.nodejs.cn/pres.numbers
mv *.js src
  1. 将高亮的行添加到 exe 定义之后的 build.zig 中:

    ¥Add the highlighted lines to build.zig just after the exe definition:

build.zig (add highlighted lines)
    const exe = b.addExecutable(.{
.name = "sheetjs_zig",
.root_module = exe_mod,
});
exe.addCSourceFile(.{ .file = b.path("duktape-2.7.0/src/duktape.c"), .flags = &.{ "-std=c99", "-fno-sanitize=undefined" } });
exe.addIncludePath(b.path("duktape-2.7.0/src"));
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("m");
  1. 下载 main.zig 并替换 src/main.zig。应在 WSL bash 或 macOS 或 Linux 终端中运行以下命令:

    ¥Download main.zig and replace src/main.zig. The following command should be run in WSL bash or the macOS or Linux terminal:

curl -L -o src/main.zig https://xlsx.nodejs.cn/duk/main.zig
  1. 构建并运行程序:

    ¥Build and run the program:

./zig-*/zig build run -- pres.numbers

此步骤构建并运行程序。生成的程序将放置在 zig-out/bin/ 子目录中。

¥This step builds and runs the program. The generated program will be placed in the zig-out/bin/ subdirectory.

它应该显示一些元数据以及第一个工作表中的 CSV 行。它还会生成 sheetjs.zig.xlsx,可以使用 Excel 等电子表格编辑器打开它。

¥It should display some metadata along with CSV rows from the first worksheet. It will also generate sheetjs.zig.xlsx, which can be opened with a spreadsheet editor such as Excel.

Perl​

Duktape 的 Perl 绑定在 CPAN 上以 JavaScript::Duktape::XS 形式提供。

¥The Perl binding for Duktape is available as JavaScript::Duktape::XS on CPAN.

Perl 绑定没有原始 Buffer 操作,因此使用 Base64 字符串。

¥The Perl binding does not have raw Buffer ops, so Base64 strings are used.

Perl 演示​

¥Perl Demo

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本日期
darwin-x642.2.02025-03-31
darwin-arm2.2.02025-03-30
linux-x642.2.02025-04-21
linux-arm2.2.02025-02-15
  1. 确保 perl 和 cpan 已安装并在系统路径上可用。

    ¥Ensure perl and cpan are installed and available on the system path.

在 Arch Linux 和 HoloOS(Steam Deck)上,crypt.h 可能缺失。必须明确安装 libxcrypt 包:

¥On Arch Linux and HoloOS (Steam Deck), crypt.h may be missing. The libxcrypt package must be explicitly installed:

sudo pacman -S libxcrypt
  1. 安装 JavaScript::Duktape::XS 库:

    ¥Install the JavaScript::Duktape::XS library:

cpan install JavaScript::Duktape::XS

在某些系统上,必须以 root 用户身份运行该命令:

¥On some systems, the command must be run as the root user:

sudo cpan install JavaScript::Duktape::XS
  1. 下载 SheetJSDuk.pl:

    ¥Download SheetJSDuk.pl:

curl -LO https://xlsx.nodejs.cn/duk/SheetJSDuk.pl
  1. 下载 SheetJS ExtendScript 构建和测试文件:

    ¥Download the SheetJS ExtendScript build and test file:

curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.extendscript.js
curl -LO https://xlsx.nodejs.cn/pres.xlsx
  1. 运行脚本:

    ¥Run the script:

perl SheetJSDuk.pl pres.xlsx

如果脚本成功,测试文件中的数据将打印在 CSV 行中。该脚本还将导出 SheetJSDuk.xlsb。

¥If the script succeeded, the data in the test file will be printed in CSV rows. The script will also export SheetJSDuk.xlsb.

在某些测试运行中,该命令由于缺少 File::Slurp 而失败:

¥In some test runs, the command failed due to missing File::Slurp:

Can't locate File/Slurp.pm in @INC (you may need to install the File::Slurp module)

修复方法是安装 File::Slurp 和 cpan:

¥The fix is to install File::Slurp with cpan:

sudo cpan install File::Slurp

Rust​

ducc 是与 Duktape 引擎的 Rust 绑定。​​它提供了许多与引擎交换数据的便捷方法。

¥ducc is a Rust binding to the Duktape engine. It provides a number of convenience methods for exchanging data with the engine.

上次测试此演示时,将 Uint8Array 对象传回 Rust 时出现问题。此演示会生成一个 Base64 编码的字符串,将该字符串传回 Rust,然后使用 base64 crate 进行解码。

¥When this demo was last tested, there were issues passing Uint8Array objects back to Rust. Instead, this demo generates a Base64-encoded string, passes the string back to Rust, and decodes using the base64 crate.

Rust 演示​

¥Rust Demo

测试部署

该演示在以下部署中进行了测试:

¥This demo was tested in the following deployments:

架构版本日期
darwin-x642.2.12025-03-31
darwin-arm2.2.12025-03-31
win11-x642.2.12025-04-17
linux-x642.2.12025-04-18
linux-arm2.2.12025-04-18
  1. 创建一个新项目:

    ¥Create a new project:

cargo new sheetjs-duk-rs
cd sheetjs-duk-rs
cargo run
  1. 下载 SheetJS 独立脚本并将其复制到 src 文件夹:

    ¥Download the SheetJS Standalone script and shim to the src folder:

curl -L -o src/shim.min.js https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
curl -L -o src/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
  1. 下载测试文件。将文件移动到项目目录:

    ¥Download the test file. Move the file to the project directory:

curl -LO https://xlsx.nodejs.cn/pres.numbers
  1. 下载 main.rs 并替换 src/main.rs:

    ¥Download main.rs and replace src/main.rs:

curl -L -o src/main.rs https://xlsx.nodejs.cn/duk/main.rs
  1. 安装依赖:

    ¥Install dependencies:

cargo add ducc base64
  1. 构建并运行应用:

    ¥Build and run the app:

cargo run pres.numbers

如果程序成功,CSV 内容将打印到控制台并创建文件 sheetjsw.xlsb。可以使用支持 XLSB 电子表格的电子表格编辑器打开该文件。

¥If the program succeeded, the CSV contents will be printed to console and the file sheetjsw.xlsb will be created. That file can be opened with a spreadsheet editor that supports XLSB spreadsheets.

[^1]: 请参阅 PHP 文档中的 对外函数接口。

¥See Foreign Function Interface in the PHP documentation.

[^2]: 请参阅 Python 文档中的 ctypes。

¥See ctypes in the Python documentation.