JSC Swift Linux demo
This commit is contained in:
parent
7d749963f4
commit
066741f185
docz
data
docs
static/swift
@ -334,8 +334,8 @@
|
|||||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||||
<Cell ss:StyleID="s16"/>
|
<Cell ss:StyleID="s16"/>
|
||||||
<Cell ss:StyleID="s16"/>
|
<Cell ss:StyleID="s16"/>
|
||||||
<Cell ss:StyleID="s16"/>
|
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||||
<Cell ss:StyleID="s16"/>
|
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rb#complete-example"><Data ss:Type="String">ExecJS</Data></Cell>
|
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/rb#complete-example"><Data ss:Type="String">ExecJS</Data></Cell>
|
||||||
|
@ -24,7 +24,7 @@ generate CSV files for the LangChain CSV loader. These conversions can be run in
|
|||||||
a preprocessing step without disrupting existing CSV workflows.
|
a preprocessing step without disrupting existing CSV workflows.
|
||||||
|
|
||||||
In ["SheetJS Loader"](#sheetjs-loader), we will use SheetJS libraries in a
|
In ["SheetJS Loader"](#sheetjs-loader), we will use SheetJS libraries in a
|
||||||
custom loader to directly generate documents and metadata.
|
custom `LoadOfSheet` data loader to directly generate documents and metadata.
|
||||||
|
|
||||||
["SheetJS Loader Demo"](#sheetjs-loader-demo) is a complete demo that uses the
|
["SheetJS Loader Demo"](#sheetjs-loader-demo) is a complete demo that uses the
|
||||||
SheetJS Loader to answer questions based on data from a XLS workbook.
|
SheetJS Loader to answer questions based on data from a XLS workbook.
|
||||||
|
@ -312,11 +312,25 @@ FILE *f = fopen("sheetjsw.xlsb", "wb"); fwrite(buf, 1, sz, f); fclose(f);
|
|||||||
|
|
||||||
This demo was tested in the following environments:
|
This demo was tested in the following environments:
|
||||||
|
|
||||||
|
**Built-in**
|
||||||
|
|
||||||
|
Swift on MacOS supports JavaScriptCore without additional dependencies.
|
||||||
|
|
||||||
| Architecture | Swift | Date |
|
| Architecture | Swift | Date |
|
||||||
|:-------------|:--------|:-----------|
|
|:-------------|:--------|:-----------|
|
||||||
| `darwin-x64` | `5.10` | 2024-04-04 |
|
| `darwin-x64` | `5.10` | 2024-04-04 |
|
||||||
| `darwin-arm` | `5.9.2` | 2024-02-21 |
|
| `darwin-arm` | `5.9.2` | 2024-02-21 |
|
||||||
|
|
||||||
|
**Compiled**
|
||||||
|
|
||||||
|
The ["Swift C"](#swift-c) section starts from the static libraries built in the
|
||||||
|
["C++"](#c) section and build Swift bindings.
|
||||||
|
|
||||||
|
| Architecture | Version | Date |
|
||||||
|
|:-------------|:-----------------|:-----------|
|
||||||
|
| `linux-x64` | `7618.2.12.11.7` | 2024-06-22 |
|
||||||
|
| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 |
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
The demo includes a sample `SheetJSCore` Wrapper class to simplify operations.
|
The demo includes a sample `SheetJSCore` Wrapper class to simplify operations.
|
||||||
@ -325,6 +339,8 @@ The demo includes a sample `SheetJSCore` Wrapper class to simplify operations.
|
|||||||
|
|
||||||
This example requires MacOS + Swift and will not work on Windows or Linux!
|
This example requires MacOS + Swift and will not work on Windows or Linux!
|
||||||
|
|
||||||
|
The ["Swift C"](#swift-c) section covers integration in other platforms.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
0) Ensure Swift is installed by running the following command in the terminal:
|
0) Ensure Swift is installed by running the following command in the terminal:
|
||||||
@ -391,8 +407,8 @@ This demo was tested in the following environments:
|
|||||||
|:-------------|:-----------------|:-----------|
|
|:-------------|:-----------------|:-----------|
|
||||||
| `darwin-x64` | `7618.1.15.14.7` | 2024-04-24 |
|
| `darwin-x64` | `7618.1.15.14.7` | 2024-04-24 |
|
||||||
| `darwin-arm` | `7618.2.12.11.7` | 2024-05-24 |
|
| `darwin-arm` | `7618.2.12.11.7` | 2024-05-24 |
|
||||||
| `linux-x64` | `7618.1.15.14.7` | 2024-04-24 |
|
| `linux-x64` | `7618.2.12.11.7` | 2024-06-22 |
|
||||||
| `linux-arm` | `7618.2.12.11.7` | 2024-05-25 |
|
| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 |
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
@ -401,12 +417,20 @@ This demo was tested in the following environments:
|
|||||||
<details>
|
<details>
|
||||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||||
|
|
||||||
On the Steam Deck, a few dependencies must be installed before building JSC:
|
The build requires CMake and Ruby.
|
||||||
|
|
||||||
|
On the Steam Deck, dependencies should be installed with `pacman`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo pacman -Syu base-devel cmake ruby icu glibc linux-api-headers
|
sudo pacman -Syu base-devel cmake ruby icu glibc linux-api-headers
|
||||||
```
|
```
|
||||||
|
|
||||||
|
On Debian and Ubuntu, dependencies should be installed with `apt`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install build-essential cmake ruby
|
||||||
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
1) Create a project folder:
|
1) Create a project folder:
|
||||||
@ -523,7 +547,7 @@ When this demo was last tested on ARM64, there was a dangling pointer error:
|
|||||||
{" |"} <span {...r}>~~~~~~~^~~~~~</span>
|
{" |"} <span {...r}>~~~~~~~^~~~~~</span>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
The error can be suppressed with a preprocessor pragma:
|
The error can be suppressed with preprocessor directives around the definition:
|
||||||
|
|
||||||
```cpp title="WebKitBuild/JSCOnly/Release/WTF/Headers/wtf/SentinelLinkedList.h (add highlighted lines)"
|
```cpp title="WebKitBuild/JSCOnly/Release/WTF/Headers/wtf/SentinelLinkedList.h (add highlighted lines)"
|
||||||
BasicRawSentinelNode() = default;
|
BasicRawSentinelNode() = default;
|
||||||
@ -609,6 +633,118 @@ curl -LO https://docs.sheetjs.com/pres.numbers`}
|
|||||||
If successful, a CSV will be printed to console. The script also tries to write
|
If successful, a CSV will be printed to console. The script also tries to write
|
||||||
to `sheetjsw.xlsb`, which can be opened in a spreadsheet editor.
|
to `sheetjsw.xlsb`, which can be opened in a spreadsheet editor.
|
||||||
|
|
||||||
|
### Swift C
|
||||||
|
|
||||||
|
:::note pass
|
||||||
|
|
||||||
|
For macOS and iOS deployments, it is strongly encouraged to use the official
|
||||||
|
`JavaScriptCore` bindings. This demo is suited for Linux Swift applications.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
0) Install the Swift toolchain.[^8]
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||||
|
|
||||||
|
The `linux-x64` test was run on [Ubuntu 22.04 using Swift 5.10.1](https://download.swift.org/swift-5.10.1-release/ubuntu2204/swift-5.10.1-RELEASE/swift-5.10.1-RELEASE-ubuntu22.04.tar.gz)
|
||||||
|
|
||||||
|
The `linux-arm` test was run on [Debian 12 "bookworm" using Swift 5.10.1](https://download.swift.org/swift-5.10.1-release/debian12-aarch64/swift-5.10.1-RELEASE/swift-5.10.1-RELEASE-debian12-aarch64.tar.gz)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
1) Follow the entire ["C" demo](#c). The shared library will be used in Swift.
|
||||||
|
|
||||||
|
2) Enter the `sheetjs-jsc` folder from the previous step.
|
||||||
|
|
||||||
|
3) Create a folder `sheetjswift`. It should be in the `sheetjs-jsc` folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir sheetjswift
|
||||||
|
cd sheetjswift
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Download the SheetJS Standalone script and the test file. Save both files in
|
||||||
|
the project directory:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
|
||||||
|
<li><a href="https://docs.sheetjs.com/pres.numbers">pres.numbers</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{`\
|
||||||
|
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||||
|
curl -LO https://docs.sheetjs.com/pres.numbers`}
|
||||||
|
</CodeBlock>
|
||||||
|
|
||||||
|
5) Copy all generated headers to the current directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find ../WebKit-WebKit*/WebKitBuild/JSCOnly/Release/JavaScriptCore/Headers/ -name \*.h | xargs -I '%' cp '%' .
|
||||||
|
```
|
||||||
|
|
||||||
|
6) Edit each header file and replace all instances of `<JavaScriptCore/` with
|
||||||
|
`<`. For example, `JavaScript.h` includes `<JavaScriptCore/JSBase.h>`:
|
||||||
|
|
||||||
|
```c title="JavaScript.h (original include)"
|
||||||
|
#include <JavaScriptCore/JSBase.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
This must be changed to `<JSBase.h>`:
|
||||||
|
|
||||||
|
```c title="JavaScript.h (modified include)"
|
||||||
|
#include <JSBase.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
7) Print the current working directory. It will be the path to `sheetjswift`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pwd
|
||||||
|
```
|
||||||
|
|
||||||
|
8) Create a new header named `JavaScriptCore-Bridging-Header.h` :
|
||||||
|
|
||||||
|
```c title="JavaScriptCore-Bridging-Header.h"
|
||||||
|
#import "/tmp/sheetjs-jsc/sheetjswift/JavaScript.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace the import path to the working directory from step 7. For example, if
|
||||||
|
the path was `/home/sheetjs/sheetjs-jsc/sheetjswift/`, the import should be
|
||||||
|
|
||||||
|
```c title="JavaScriptCore-Bridging-Header.h"
|
||||||
|
#import "/home/sheetjs/sheetjs-jsc/JavaScript.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
9) Create the default module map `module.modulemap`:
|
||||||
|
|
||||||
|
```text title="module.modulemap"
|
||||||
|
module JavaScriptCore {
|
||||||
|
header "./JavaScript.h"
|
||||||
|
link "JavaScriptCore"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
10) Download [`SheetJSCRaw.swift`](pathname:///swift/SheetJSCRaw.swift):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -LO https://docs.sheetjs.com/swift/SheetJSCRaw.swift
|
||||||
|
```
|
||||||
|
|
||||||
|
11) Build `SheetJSwift`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
swiftc -Xcc -I$(pwd) -Xlinker -L../WebKit-WebKit-7618.2.12.11.7/WebKitBuild/JSCOnly/Release/lib/ -Xlinker -lJavaScriptCore -Xlinker -lWTF -Xlinker -lbmalloc -Xlinker -lstdc++ -Xlinker -latomic -Xlinker -licuuc -Xlinker -licui18n -import-objc-header JavaScriptCore-Bridging-Header.h SheetJSCRaw.swift -o SheetJSwift
|
||||||
|
```
|
||||||
|
|
||||||
|
12) Run the command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./SheetJSwift pres.numbers
|
||||||
|
```
|
||||||
|
|
||||||
|
If successful, a CSV will be printed to console. The program also tries to write
|
||||||
|
to `SheetJSwift.xlsx`, which can be opened in a spreadsheet editor.
|
||||||
|
|
||||||
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||||
[^2]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
[^2]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||||
[^3]: See [`JSObjectMakeTypedArrayWithBytesNoCopy`](https://developer.apple.com/documentation/javascriptcore/jsobjectmaketypedarraywithbytesnocopy(_:_:_:_:_:_:_:)/) in the JavaScriptCore documentation.
|
[^3]: See [`JSObjectMakeTypedArrayWithBytesNoCopy`](https://developer.apple.com/documentation/javascriptcore/jsobjectmaketypedarraywithbytesnocopy(_:_:_:_:_:_:_:)/) in the JavaScriptCore documentation.
|
||||||
@ -616,4 +752,5 @@ to `sheetjsw.xlsb`, which can be opened in a spreadsheet editor.
|
|||||||
[^5]: See [`JSObjectGetTypedArrayBytesPtr`](
|
[^5]: See [`JSObjectGetTypedArrayBytesPtr`](
|
||||||
https://developer.apple.com/documentation/javascriptcore/jsobjectgettypedarraybytesptr(_:_:_:)/) in the JavaScriptCore documentation.
|
https://developer.apple.com/documentation/javascriptcore/jsobjectgettypedarraybytesptr(_:_:_:)/) in the JavaScriptCore documentation.
|
||||||
[^6]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
[^6]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||||
[^7]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
[^7]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||||
|
[^8]: See ["Install Swift"](https://www.swift.org/install) in the Swift website.
|
||||||
|
189
docz/static/swift/SheetJSCRaw.swift
Normal file
189
docz/static/swift/SheetJSCRaw.swift
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/* SheetJSCore (C) 2024-present SheetJS LLC -- https://sheetjs.com */
|
||||||
|
import Foundation;
|
||||||
|
import JavaScriptCore;
|
||||||
|
|
||||||
|
enum JSCError: Error {
|
||||||
|
case badJSContext;
|
||||||
|
case badJSWorkbook;
|
||||||
|
case badJSWorksheet;
|
||||||
|
case badJSValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
func DOIT(code: String, ctx: JSContextRef) -> JSValueRef {
|
||||||
|
let script: JSStringRef = JSStringCreateWithUTF8CString(code);
|
||||||
|
let result: JSValueRef = JSEvaluateScript(ctx, script, nil, nil, 0, nil);
|
||||||
|
JSStringRelease(script);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
func JS_STR_TO_C(val: JSValueRef, ctx: JSContextRef) -> String {
|
||||||
|
let str: JSStringRef = JSValueToStringCopy(ctx, val, nil);
|
||||||
|
let sz = JSStringGetMaximumUTF8CStringSize(str);
|
||||||
|
let buf = malloc(sz);
|
||||||
|
JSStringGetUTF8CString(str, buf, sz);
|
||||||
|
let ptr = buf!.bindMemory(to: CChar.self, capacity: 1);
|
||||||
|
let result = String.init(cString: ptr);
|
||||||
|
free(buf);
|
||||||
|
JSStringRelease(str);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
func GET_NAMED_PROP(val: JSValueRef, key: String, ctx: JSContextRef) throws -> JSValueRef {
|
||||||
|
if(!JSValueIsObject(ctx, val)) { throw JSCError.badJSValue; }
|
||||||
|
let o: JSObjectRef = JSValueToObject(ctx, val, nil);
|
||||||
|
let k: JSStringRef = JSStringCreateWithUTF8CString(key);
|
||||||
|
let result: JSValueRef = JSObjectGetProperty(ctx, o, k, nil);
|
||||||
|
JSStringRelease(k);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
func SET_NAMED_PROP(obj: JSValueRef, key: String, val: JSValueRef, ctx: JSContextRef) throws {
|
||||||
|
if(!JSValueIsObject(ctx, obj)) { throw JSCError.badJSValue; }
|
||||||
|
let k: JSStringRef = JSStringCreateWithUTF8CString(key);
|
||||||
|
JSObjectSetProperty(ctx, obj, k, val, 0, nil);
|
||||||
|
JSStringRelease(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SJSWorksheet {
|
||||||
|
var context: JSContextRef!;
|
||||||
|
var wb: JSValueRef;
|
||||||
|
var ws: JSValueRef;
|
||||||
|
var idx: UInt32;
|
||||||
|
|
||||||
|
func toCSV() throws -> String {
|
||||||
|
let global = JSContextGetGlobalObject(self.context);
|
||||||
|
let XLSX = try GET_NAMED_PROP(val: global!, key: "XLSX", ctx: self.context);
|
||||||
|
let utils: JSValueRef = try GET_NAMED_PROP(val: XLSX, key: "utils", ctx: self.context);
|
||||||
|
let sheet_to_csv: JSValueRef = try GET_NAMED_PROP(val: utils, key: "sheet_to_csv", ctx: self.context);
|
||||||
|
var exc: JSValueRef?;
|
||||||
|
let result = JSObjectCallAsFunction(self.context, JSValueToObject(self.context, sheet_to_csv, nil), JSValueToObject(self.context, utils, nil), 1, [ws], &exc);
|
||||||
|
if(exc != nil && JSValueIsObject(exc, self.context)) {
|
||||||
|
let e = JS_STR_TO_C(val: exc!, ctx: self.context);
|
||||||
|
print(e)
|
||||||
|
throw JSCError.badJSValue;
|
||||||
|
}
|
||||||
|
return JS_STR_TO_C(val: result!, ctx: self.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
init(ctx: JSContextRef, wb: JSValueRef, ws: JSValueRef, idx: UInt32) throws {
|
||||||
|
self.context = ctx;
|
||||||
|
self.wb = wb;
|
||||||
|
self.ws = ws;
|
||||||
|
self.idx = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SJSWorkbook {
|
||||||
|
var context: JSContextRef!;
|
||||||
|
var wb: JSValueRef;
|
||||||
|
var SheetNames: JSValueRef;
|
||||||
|
var Sheets: JSValueRef;
|
||||||
|
|
||||||
|
func getSheetAtIndex(idx: UInt32) throws -> SJSWorksheet {
|
||||||
|
let SheetNameRef = try GET_NAMED_PROP(val: self.SheetNames, key: String(idx), ctx: self.context);
|
||||||
|
let SheetName: String = JS_STR_TO_C(val: SheetNameRef, ctx: self.context)
|
||||||
|
let ws: JSValueRef! = try GET_NAMED_PROP(val: self.Sheets, key: SheetName, ctx: self.context);
|
||||||
|
return try SJSWorksheet(ctx: self.context, wb: self.wb, ws: ws, idx: idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeData(bookType: String = "xlsx") throws -> Data {
|
||||||
|
let global = JSContextGetGlobalObject(self.context)!;
|
||||||
|
let XLSX = try GET_NAMED_PROP(val: global, key: "XLSX", ctx: self.context);
|
||||||
|
let write: JSValueRef = try GET_NAMED_PROP(val: XLSX, key: "write", ctx: self.context);
|
||||||
|
let opts = DOIT(code: String(format: "({type:'buffer', bookType:'%@', WTF:1})", bookType), ctx: self.context);
|
||||||
|
|
||||||
|
var exc: JSValueRef?;
|
||||||
|
let result = JSObjectCallAsFunction(self.context, JSValueToObject(self.context, write, nil), JSValueToObject(self.context, XLSX, nil), 2, [self.wb, opts], &exc);
|
||||||
|
if(exc != nil && JSValueIsObject(exc, self.context)) {
|
||||||
|
let e = JS_STR_TO_C(val: exc!, ctx: self.context);
|
||||||
|
print(e)
|
||||||
|
throw JSCError.badJSValue;
|
||||||
|
}
|
||||||
|
let u8: JSObjectRef = JSValueToObject(self.context, result, nil);
|
||||||
|
let sz = JSObjectGetTypedArrayLength(self.context, result, nil);
|
||||||
|
let buf = JSObjectGetTypedArrayBytesPtr(self.context, u8, nil);
|
||||||
|
let data = Data(bytes: buf!, count: sz);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
init(ctx: JSContextRef, wb: JSValueRef) throws {
|
||||||
|
self.context = ctx;
|
||||||
|
self.wb = wb;
|
||||||
|
self.SheetNames = try GET_NAMED_PROP(val: self.wb, key: "SheetNames", ctx: self.context);
|
||||||
|
self.Sheets = try GET_NAMED_PROP(val: self.wb, key: "Sheets", ctx: self.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SheetJSCore {
|
||||||
|
var context: JSContextRef!;
|
||||||
|
var XLSX: JSValueRef!;
|
||||||
|
|
||||||
|
func init_context() throws -> JSContextRef {
|
||||||
|
let context = JSGlobalContextCreate(nil);
|
||||||
|
if (context == nil) { throw JSCError.badJSContext; }
|
||||||
|
do {
|
||||||
|
_ = DOIT(code: "var global = (function(){ return this; }).call(null);", ctx: context!);
|
||||||
|
_ = DOIT(code: "if(typeof wbs == 'undefined') wbs = [];", ctx: context!);
|
||||||
|
let src = try String(contentsOfFile: "xlsx.full.min.js");
|
||||||
|
_ = DOIT(code: src, ctx: context!);
|
||||||
|
return context!;
|
||||||
|
} catch { print(error.localizedDescription); }
|
||||||
|
throw JSCError.badJSContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
func version() throws -> String {
|
||||||
|
if(self.context == nil) { throw JSCError.badJSContext; }
|
||||||
|
let res: JSValueRef = try GET_NAMED_PROP(val: self.XLSX, key: "version", ctx: self.context);
|
||||||
|
if(!JSValueIsString(self.context!, res)) {
|
||||||
|
print("Could not get SheetJS version.");
|
||||||
|
throw JSCError.badJSValue;
|
||||||
|
}
|
||||||
|
return JS_STR_TO_C(val: res, ctx: self.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
func readData(data: inout Data) throws -> SJSWorkbook {
|
||||||
|
let wb: JSValueRef = try data.withUnsafeMutableBytes{ (ptr: UnsafeMutableRawBufferPointer) throws in
|
||||||
|
let u8: JSValueRef = JSObjectMakeTypedArrayWithBytesNoCopy(self.context, kJSTypedArrayTypeUint8Array, ptr.baseAddress, ptr.count, nil, nil, nil);
|
||||||
|
try SET_NAMED_PROP(obj: JSContextGetGlobalObject(self.context), key: "payload", val: u8, ctx: self.context);
|
||||||
|
let wb: JSValueRef = DOIT(code: "XLSX.read(payload);", ctx: self.context);
|
||||||
|
if !JSValueIsObject(wb, self.context) { throw JSCError.badJSWorkbook; }
|
||||||
|
return wb;
|
||||||
|
}
|
||||||
|
return try SJSWorkbook(ctx: context, wb: wb);
|
||||||
|
}
|
||||||
|
func readFile(file: String) throws -> SJSWorkbook {
|
||||||
|
var data: Data! = try NSData(contentsOfFile: file) as Data;
|
||||||
|
return try readData(data: &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
init() throws {
|
||||||
|
self.context = try init_context();
|
||||||
|
do {
|
||||||
|
let global = JSContextGetGlobalObject(self.context);
|
||||||
|
self.XLSX = try GET_NAMED_PROP(val: global!, key: "XLSX", ctx: self.context);
|
||||||
|
if self.XLSX == nil { throw JSCError.badJSContext; }
|
||||||
|
} catch { print(error.localizedDescription); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
let sheetjs = try SheetJSCore();
|
||||||
|
|
||||||
|
|
||||||
|
/* Print the SheetJS library version */
|
||||||
|
try print(sheetjs.version());
|
||||||
|
|
||||||
|
/* Read file */
|
||||||
|
let wb: SJSWorkbook = try sheetjs.readFile(file: CommandLine.arguments[1]);
|
||||||
|
|
||||||
|
/* Convert the first worksheet to CSV and print */
|
||||||
|
let ws: SJSWorksheet = try wb.getSheetAtIndex(idx: 0);
|
||||||
|
let csv: String = try ws.toCSV();
|
||||||
|
print(csv);
|
||||||
|
|
||||||
|
/* write an XLSX file to SheetJSwift.xlsx */
|
||||||
|
var wbout: Data = try wb.writeData(bookType: "xlsx");
|
||||||
|
let cwd = FileManager.default.currentDirectoryPath;
|
||||||
|
let uri = URL(fileURLWithPath: cwd).appendingPathComponent("SheetJSwift.xlsx");
|
||||||
|
try wbout.write(to: uri);
|
Loading…
Reference in New Issue
Block a user