docs.sheetjs.com/docz/docs/03-demos/12-engines/11_perl.md

135 lines
3.1 KiB
Markdown
Raw Normal View History

2023-02-13 09:20:49 +00:00
---
title: Perl + JE
2023-02-28 11:40:44 +00:00
pagination_prev: demos/bigdata/index
pagination_next: solutions/input
2023-02-13 09:20:49 +00:00
---
2023-04-27 09:12:19 +00:00
import current from '/version.js';
2023-05-07 13:58:36 +00:00
import CodeBlock from '@theme/CodeBlock';
2023-04-27 09:12:19 +00:00
2023-02-13 09:20:49 +00:00
:::warning
In a production application, it is strongly recommended to use a binding for a
C engine like [`JavaScript::Duktape`](/docs/demos/engines/duktape)
:::
JE is a pure-Perl JavaScript engine.
2023-04-19 20:03:23 +00:00
The [ExtendScript build](/docs/getting-started/installation/extendscript) can be
2023-02-13 09:20:49 +00:00
parsed and evaluated in a JE context.
## Integration Details
The engine deviates from ES3. Modifying prototypes can fix some behavior:
```js
/* String#charCodeAt is missing */
var string = "";
for(var i = 0; i < 256; ++i) string += String.fromCharCode(i);
String.prototype.charCodeAt = function(n) {
var result = string.indexOf(this.charAt(n));
if(result == -1) throw this.charAt(n);
return result;
};
/* workaround for String split bug */
Number.prototype.charCodeAt = function(n) { return this + 48; };
/* String#match bug with empty results */
String.prototype.old_match = String.prototype.match;
String.prototype.match = function(p) {
var result = this.old_match(p);
return (Array.isArray(result) && result.length == 0) ? null : result;
};
```
When loading the ExtendScript build, the BOM must be removed:
```perl
## Load SheetJS source
my $src = read_file('xlsx.extendscript.js', { binmode => ':raw' });
$src =~ s/^\xEF\xBB\xBF//; ## remove UTF8 BOM
my $XLSX = $je->eval($src);
```
### Reading Files
Data should be passed as Base64 strings:
```perl
use File::Slurp;
use MIME::Base64 qw( encode_base64 );
## Set up conversion method
$je->eval(<<'EOF');
function sheetjsparse(data) { try {
return XLSX.read(String(data), {type: "base64", WTF:1});
} catch(e) { return String(e); } }
EOF
## Read file
my $raw_data = encode_base64(read_file($ARGV[0], { binmode => ':raw' }), "");
## Call method with data
$return_val = $je->method(sheetjsparse => $raw_data);
```
### Writing Files
Due to bugs in data interchange, it is strongly recommended to use a simple
format like `.fods`:
```perl
use File::Slurp;
## Set up conversion method
$je->eval(<<'EOF');
function sheetjswrite(wb) { try {
return XLSX.write(wb, { WTF:1, bookType: "fods", type: "string" });
} catch(e) { return String(e); } }
EOF
## Generate file
my $fods = $je->method(sheetjswrite => $workbook);
## Write to filesystem
write_file("SheetJE.fods", $fods);
```
## Complete Example
:::note
This demo was tested on 2023 February 12 against JE 0.066
:::
1) Install `JE` through CPAN:
```bash
cpan install JE
```
2) Download the [ExtendScript build](/docs/getting-started/installation/extendscript):
2023-05-07 13:58:36 +00:00
<CodeBlock language="bash">{`\
2023-04-27 09:12:19 +00:00
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.extendscript.js`}
2023-05-07 13:58:36 +00:00
</CodeBlock>
2023-02-13 09:20:49 +00:00
2023-02-15 01:00:49 +00:00
3) Download the demo [`SheetJE.pl`](pathname:///perl/SheetJE.pl):
2023-02-13 09:20:49 +00:00
2023-02-15 01:00:49 +00:00
```bash
curl -LO https://docs.sheetjs.com/perl/SheetJE.pl
2023-02-13 09:20:49 +00:00
```
4) Download a test file and run:
```bash
curl -LO https://sheetjs.com/data/cd.xls
perl SheetJE.pl cd.xls
```
After a short wait, the contents will be displayed in CSV form. It will also
write a file `SheetJE.fods` that can be opened in LibreOffice.