docs.sheetjs.com/docz/docs/03-demos/32-extensions/12-maple.md

6.7 KiB

title sidebar_label pagination_prev pagination_next sidebar_custom_props
Modern Spreadsheets in Maple Maple demos/cloud/index demos/bigdata/index
summary
Generate Maple-compatible XLSX workbooks from incompatible files

import current from '/version.js'; import CodeBlock from '@theme/CodeBlock';

Maple is a numeric computing platform. It offers a robust C-based extension system.

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

This demo uses SheetJS to pull data from a spreadsheet for further analysis within Maple. We'll create a Maple native extension that loads the Duktape JavaScript engine and uses the SheetJS library to read data from spreadsheets and converts to a Maple-friendly format.

flowchart LR
  ofile[(workbook\nXLSB file)]
  nfile[(clean file\nXLSX)]
  data[[Maple\nTable]]
  ofile --> |Maple Extension\nSheetJS + Duktape| nfile
  nfile --> |ExcelTools\nImport|data

:::note Tested Deployments

This demo was tested by SheetJS users in the following deployments:

Architecture Version Date
darwin-x64 2024 2024-04-25
win10-x64 2024 2024-04-25

:::

:::info pass

Maple has limited support for processing spreadsheets through the ExcelTools package1. At the time of writing, it lacked support for XLSB, NUMBERS, and other common spreadsheet formats.

SheetJS libraries help fill the gap by normalizing spreadsheets to a form that Maple can understand.

:::

Integration Details

The current recommendation involves a native plugin that reads arbitrary files and generates clean XLSX files that Maple can import.

The extension function ultimately pairs the SheetJS read2 and write3 methods to read data from the old file and write a new file:

var workbook = XLSX.read(original_file_data, { type: "buffer" });
var new_file_data = XLSX.write(workbook, { type: "array", bookType: "xlsx" });

The extension function will receive a file name and perform the following steps:

flowchart LR
  ofile{{File\nName}}
  subgraph JS Operations
    ojbuf[(Buffer\nFile Bytes)]
    wb(((SheetJS\nWorkbook)))
    njbuf[(Buffer\nXLSX bytes)]
  end
  obuf[(File\nbytes)]
  nbuf[(New file\nbytes)]
  nfile[(XLSX\nFile)]
  ofile --> |C\nRead File| obuf
  obuf --> |Duktape\nBuffer Ops| ojbuf
  ojbuf --> |SheetJS\n`read`| wb
  wb --> |SheetJS\n`write`| njbuf
  njbuf --> |Duktape\nBuffer Ops| nbuf
  nbuf --> |C\nWrite File| nfile

C Extensions

Maple extensions are shared libraries or DLLs that use special Maple methods for parsing arguments and returning values. They are typically written in the C programming language.

To simplify the flow, the new function will take one argument (the original file name) and return one value (the new file name).

The official documentation has a comprehensive list4 of methods. For this demo, the following methods are used:

  • MapleNumArgs and IsMapleString are used in argument validation. The demo function will raise a Maple exception if no file name is specified.

  • MapleRaiseError and MapleRaiseError2 programmatically raise errors.

  • MapleToString and ToMapleString convert between Maple and C strings.

Duktape JS Engine

This demo uses the Duktape JavaScript engine. The SheetJS + Duktape demo covers engine integration details in more detail.

The SheetJS Standalone scripts can be loaded in Duktape by reading the source from the filesystem.

Complete Demo

:::info pass

This demo was tested in Windows x64. The path names and build commands will differ in other platforms and operating systems.

:::

The sheetjs-maple.c extension exports the SheetToXLSX Maple method. It takes a file name argument, parses the specified file, exports data to sheetjsw.xlsx and returns the string "sheetjsw.xlsx".

This can be chained with Import from ExcelTools:

with(ExcelTools);
Import(SheetToXLSX("pres.numbers"))
  1. Install "Windows Subsystem for Linux" (WSL)5 and Visual Studio6.

  2. Open a new "x64 Native Tools Command Prompt" window and create a project folder c:\sheetjs-maple:

cd c:\
mkdir sheetjs-maple
cd sheetjs-maple
  1. Copy the headers and lib files from the Maple folder to the project folder. For example, using Maple 2024 on Windows x64:
copy "C:\Program Files\Maple 2024\extern\include\"*.h .
copy "c:\Program Files\Maple 2024\bin.x86_64_WINDOWS"\*.lib .
  1. Run bash to enter WSL

  2. Within WSL, install 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. Still within WSL, download SheetJS scripts and the test file.

{\ 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://docs.sheetjs.com/pres.numbers}

  1. Still within WSL, download the extension C code
curl -LO https://docs.sheetjs.com/maple/sheetjs-maple.c
  1. Exit WSL by running exit. The window will return to the command prompt.

  2. Build the extension DLL:

cl -Gz sheetjs-maple.c duktape.c /EHsc -link -dll -out:sheetjs-maple.dll maplec.lib
  1. Close and re-open Maple, then create a new Maple Worksheet or Document

  2. Run the following command in Maple to change the working directory:

currentdir("c:\\sheetjs-maple");
  1. Load the SheetToXLSX method from the extension:
with(ExternalCalling):
dll:=ExternalLibraryName("sheetjs-maple"):
SheetToXLSX:=DefineExternal("SheetToXLSX",dll):
  1. Read the pres.numbers test file:
with(ExcelTools);
Import(SheetToXLSX("pres.numbers"))

The result will show the data from pres.numbers

Maple Screenshot


  1. See "ExcelTools" in the Maple documentation. ↩︎

  2. See read in "Reading Files" ↩︎

  3. See write in "Writing Files" ↩︎

  4. See "C OpenMaple and ExternalCalling Application Program Interface (API)" in the Maple documentation. ↩︎

  5. In a PowerShell terminal window, run wsl --install Ubuntu ↩︎

  6. See the Visual Studio website for download links. In the Visual Studio Installer, install the "Desktop development with C++" workflow. ↩︎