Home About
UXP , InDesign , Spreadsheet

UXP InDesign, SheetJS を利用して MSエクセルデータを扱う

UXP Script ではモダンなJavaScript(ES6) に対応したので、既存のJavaScriptライブラリを利用できるようになりました。

今回は SheetJS を使って MSエクセルデータを扱う方法を試しました。

完成したスクリプトの配布時にそれを一つにまとめたいので rollup.js を使います。 この手のバンドルツールといえば webpack が定番ですが、 今回試した範囲では webpack と UXP InDesign Script の組み合わせはうまくいかなったので webpack の代わりに rollup.js を使います。

uxp-indesign-and-sheetjs

完成したスクリプトの作動デモはこちらを https://youtu.be/SnpH6Ui7nOs ご覧ください。

使用した InDesign のバージョンは 2023 (version 18.1)と UDT version 1.7.0.13 です。

またプロジェクトは Node.js を使ってつくります。 それらのバージョンは以下の通り:

$ node --version
v16.15.0
$ npm --version
8.5.5

はじめにプロジェクトディレクトリを作成して必要なライブラリをインストール。

$ mkdir myxlsx
$ cd myxlsx
$ npm init -y
$ npm install https://cdn.sheetjs.com/xlsx-0.19.1/xlsx-0.19.1.tgz
$ npm install rollup --save-dev
$ mkdir src
$ touch src/main.js

package.json の scripts 項目に rollup コマンドを追記。

    "build": "rollup src/main.js -o main.idjs -f es",

これで npm run build することで、 src/main.js の内容が rollup されて main.idjs に保存されます。

package.json 全体は以下の通り。

{
  "name": "myxlsx",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "rollup src/main.js -o main.idjs -f es",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.1/xlsx-0.19.1.tgz"
  },
  "devDependencies": {
    "rollup": "^3.10.1"
  }
}

src/main.js を書きます。

// src/main.js

import xlsx from '../node_modules/xlsx/xlsx.mjs';

const rows = [];
rows.push({ name: 'Pikachu', type: 'Electric' });
rows.push({ name: 'Squirtle', type: 'Water' });
rows.push({ name: 'Charmander', type: 'Fire' });

const worksheet = xlsx.utils.json_to_sheet(rows);
const workbook  = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(workbook, worksheet, "pokemons");
const buffer = xlsx.write(workbook, { type: 'buffer', bookType: 'xlsx' })

const fs = require("uxp").storage.localFileSystem;
const file = await fs.getFileForSaving("pokemons.xlsx");
await file.write(buffer);

簡単にスクリプトの内容を説明すると・・・

以下の部分で、サンプルのエクセルコンテンツを用意。

const rows = [];
rows.push({ name: 'Pikachu', type: 'Electric' });
rows.push({ name: 'Squirtle', type: 'Water' });
rows.push({ name: 'Charmander', type: 'Fire' });

SheetJS を使ってサンプルコンテンツを XLSXのバッファに変換。

const worksheet = xlsx.utils.json_to_sheet(rows);
const workbook  = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(workbook, worksheet, "pokemons");
const buffer = xlsx.write(workbook, { type: 'buffer', bookType: 'xlsx' })

uxp モジュールを使って、XLSXバッファをファイルに保存。

const fs = require("uxp").storage.localFileSystem;
const file = await fs.getFileForSaving("pokemons.xlsx");
await file.write(buffer);

という内容です。

あとは rollup を実行して、SheetJSモジュールと main.js を一つにまとめ main.idjs ファイルに保存します。

$ npm run build

> myxlsx@1.0.0 build
> rollup main.js --file main.idjs


src/main.js → main.idjs...
created main.idjs in 1.2s

あとは、この main.idjs を UDT を使って実行するだけです。

これ以降は Demo 動画 https://youtu.be/SnpH6Ui7nOs をご覧ください。

デモ動画では UDT から main.idjs 直接実行していますが、 これを 所定のフォルダ ( この環境では ~/Library/Preferences/Adobe\ InDesign/Version\ 18.0-J/ja_JP/Scripts/Scripts\ Panel/ ) 内に配置することで、 InDesign のスクリプトパネルから選んで実行することができます。

インストール先のフォルダに関しては こちらの Installing scripts のセクションを参照してください。

まとめ

今回は、エクセルデータを扱える最小のデモとするため、UXP Script 内でエクセルデータを生成してファイル保存するだけの形にしました。 しかし、SheetJS を使えば書き出しだけでなく読み込みも可能です。 つまり、たとえば、InDesignで作成したカタログの価格データをエクセルで管理していたとして、 それを反映したり、逆にInDesing上から価格情報を抜き出してエクセルデータに保存することが可能になります。 もちろん、UXP Script を使わなくても、その手のワークフローはCSVを経由するなどある種の方法を使ってすでに実現できていたとは思います。 UXP Script の利点は、これを Node.js や JavaScritp の標準的な手法を使って直接 xlsx ファイルを扱えるようになったことでしょうか。