FileMaker,WEBビューアでExcel互換のスプレッドシートを使う。

この記事は、下記イベントに参加しています。
Qiita Engineer Festa 2022
https://qiita.com/official-campaigns/engineer-festa/2022
Claris FileMaker で作った App を JavaScript で拡張したらどうなる？！
https://qiita.com/official-events/0005a02478acfc50dd13

## Claris FileMaker で作った App を JavaScript で拡張したら...
- WEBビューアでExcel互換のスプレッドシートの表示ができます。
- Excelがなくても、セルの幅・高さ、色等を指定して.xlsx, .xls の保存が可能です。
- フィールド名と異なるタイトルの設定が容易です。

<iframe width="560" height="415" src="https://www.youtube.com/embed/dvjsHuKApUk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

![Image 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/3de49fd5-c06e-c2bc-555a-0e6695747c87.png)

## 使用するUIフレームワークク

Syncfusion
[JavaScript Spreadsheet](https://www.syncfusion.com/javascript-ui-controls/js-spreadsheet)

Excel互換のスプレッドシートが扱えるJSライブラリです。

年間総収入が100万米ドル以下で、開発者が5人以下の場合、無料で使えます。(登録が必要)  
登録無しでもお試し可能です。

COMMUNITY LICENSE
https://www.syncfusion.com/sales/communitylicense

> The Community License provides free access to Syncfusion Essential Studio products for companies and individuals with less than $1 million USD in annual gross revenue and 5 or fewer developers.

> 訳:DeepL
コミュニティライセンスは、年間総収入が100万米ドル以下で、開発者が5人以下の企業や個人を対象に、Syncfusion Essential Studio製品を無料で提供するものです。

## 動作検証
Windows 10
FileMaker 19.5
※macOSでもスプレッドシートの表示は出来ますが、ファイル保存は出来ません。

## サンプルファイル

https://github.com/qb-dp/FM-Spreadsheet

#### personal_infomation.fmp12
[Spredsheet]ボタンをクリック
![Image 5.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/c5f107d9-a011-d53f-1169-5dde5cf0a6a7.png)

ファイル:Spreadsheet.fmp12 のWEBビューアでSpredsheetが表示されます。
##### ライセンスキーを登録していない場合、以下のダイアログが表示されます。[X]で閉じてください。

:::note alert
このアプリケーションは、Syncfusion Essential Studioの試用版を使用して作成されています。このライセンス確認メッセージを永久に削除するには、有効なライセンスを添付してください。また、30日間の無料評価版ライセンスを取得することで、評価期間中にこのメッセージを一時的に削除することができます。詳しくは、こちらのヘルプをご覧ください。
:::
> 登録方法の説明はこの記事では、省略...。

![Image 19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/cc8ded8d-4f90-6263-29fc-670b316b741e.png)

![Image 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/7b80cbfc-dd02-85dc-5604-90a2a9a9ec06.png)

予め保存された書式が適応されています。
□applyStyle のチェックを外すと、スタイル無しで表示されます。  
※セルの幅は、チェックを外していても適用されます。
再度、personal_infomation.fmp12 の[Spredsheet]ボタンをクリックで、確認できます。
![Image 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/5adf4efa-5340-87dd-e6d7-e3368e36a847.png)

スプレッドシートのスタイルは、以下にJson形式で保存されています。
[Style]をクリック。
![Image 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/57d85b7e-c7a7-ae5d-a8db-8978270a26ff.png)

## スプレッドシート スタイルの保存
セルの色や幅・高さなどを変更し、[SAVE STYLE]をクリックで、保存できます。  
[LOAD STYLE]で現在保存しているスタイルを確認できます。 

![Image 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/13312966-c2b3-25a4-5458-231331bae158.png)

## Excel保存
1. Save As > Microsoft Excel
1. SAVE
1. ダウンロードされます。

![Image 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/caf6cfde-c0a3-a6c5-3510-c4f32c3d4552.png)

#### WEB版 Excelで確認

![Image 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/27147fc1-711e-9549-d938-46f7181c7b89.png)

## サンプルファイル: Spreadsheet.fmp12 は、複数のファイルから利用可能です。

#### 住所.fmp12
[Spredsheet]ボタンをクリック
![Image 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/6da3c166-6cd5-f763-478d-209fc96db339.png)

ファイル名・テーブル名をキーとして個別にスプレッドシートのスタイルを保存しています。

![Image 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/1b5382d0-578c-0862-6cb9-e0c5d4ae7104.png)

#### スプレッドシートのタイトルを変更したい場合は、
スクリプト:Spreadsheet $titleList を編集
![Image 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/6faafccc-dc28-0473-3386-88ee5d36f050.png)

#### スプレッドシートに入力するデータを変更したい場合は、
スクリプト:Spreadsheet $fieldList を編集
![Image 15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/818caa36-0fc3-367f-a3dc-a95e7b9229ac.png)

# ファイル:Spreadsheet.fmp12 中身

![Image 16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/76907b90-baec-4a13-22f8-8b76f48a79cc.png)

![Image 17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/02de229e-88f4-0f60-c76e-79a954f107ac.png)

##### テーブル:SourceCode

![Image 18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/7fe288f7-1f0e-8dcb-4d0a-4ee3d06d8cc4.png)

##### WEBビューア表示用 spreadsheet.html,spreadsheet.js 

```html:spreadsheet.html
<!DOCTYPE html>
<html lang="en">

<head>
    <link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAWCAAAACOIEQVQI12NgYAAAAAMAASDVIMCAAAAASUVORK5CYII=" id="favicon">
    <title>EJ2 SpreadSheet</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Typescript UI Controls">
    <meta name="author" content="Syncfusion">
    <link rel="shortcut icon" href="resources/favicon.ico">
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-base/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-inputs/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-buttons/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-splitbuttons/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-lists/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-navigations/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-popups/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-dropdowns/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-grids/styles/material.css" rel="stylesheet">
    <link href="https://cdn.syncfusion.com/ej2/20.1.58/ej2-spreadsheet/styles/material.css" rel="stylesheet">
    <!--
    <link href="styles.css" rel="stylesheet">
   -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
    <!--
    <script src="system.config.js"></script>
       -->
    <script src="https://cdn.syncfusion.com/ej2/20.1.58/dist/ej2.min.js" type="text/javascript"></script>
</head>

<body>
    <!--Element which is going to render-->

    <div id="container">
        <div id="spreadsheet"></div>
        <button class="e-btn" id="save">Save Style</button>
        <button class="e-btn" id="load">load  Style</button>
    </div>


    <script>
        var ele = document.getElementById('container');
        if (ele) {
            ele.style.visibility = "visible";
        }   
    </script>
    <script src="spreadsheet.js" type="text/javascript"></script>
</body>

</html>
```

```JavaScript:spreadsheet.js
// Registering Syncfusion license key
//ej.base.registerLicense('登録した場合は、ココにライセンスキーを記入');
//登録した場合は、上記にライセンスキーを記入しコメントアウトを外す。

        const performScriptWithOption = (script, parameter, option, retry) => {

            retry = retry ? retry : 0;
            var numRetries = 5;
            try {
                FileMaker.PerformScriptWithOption(script, parameter, option);
            }
            catch (e) {
                if (retry < numRetries) {
                    setTimeout(function () {
                        performScriptWithOption(script, parameter, option, retry);
                    }, 500);
                }
                else {
                    location.reload();
                }
            }
            /*
            special thanks
            @TeraPicoData
            https://www.seedcode.com/web-viewer-tips-for-filemaker-19-hardening-the-filemaker-performscript-function/
            */
        };

//ダミーデータ 未使用
var data= [{
    OrderID: 10248,
    CustomerID: 'VINET',
    EmployeeID: 5,
    ShipName: 'あいうえお',
    ShipCity: 'Reims',
    ShipAddress: '59 rue de lAbbaye'
  },
  {
    OrderID: 10249,
    CustomerID: 'TOMSP',
    EmployeeID: 6,
    ShipName: 'Toms Spezialitäten',
    ShipCity: 'Münster',
    ShipAddress: 'Luisenstr. 48'
  },
  {
    OrderID: 10250,
    CustomerID: 'HANAR',
    EmployeeID: 4,
    ShipName: 'Hanari Carnes',
    ShipCity: 'Rio de Janeiro',
    ShipAddress: 'Rua do Paço, 67'
  },
  {
    OrderID: 10251,
    CustomerID: 'VICTE',
    EmployeeID: 3,
    ShipName: 'Victuailles en stock',
    ShipCity: 'Lyon',
    ShipAddress: '2, rue du Commerce'
  },
  {
    OrderID: 10252,
    CustomerID: 'SUPRD',
    EmployeeID: 4,
    ShipName: 'Suprêmes délices',
    ShipCity: 'Charleroi',
    ShipAddress: 'Boulevard Tirou, 255'
  }];

var sheet = [{
/* このコメントアウトを外すと上記ダミーデータが初期値として登録される
                ranges: [{ dataSource: data }],
                columns: [{ width: 80 }, { width: 80 },{ width: 80},
                          { width: 160 }, { width: 100 }, {width: 150}]
*/
            }]


            let response;

// Initialize the Spreadsheet component.
var spreadsheet = new ej.spreadsheet.Spreadsheet({
 locale: "ja-JP" ,
    sheets: sheet,
    allowOpen: true,
    openUrl: 'https://ej2services.syncfusion.com/production/web-services/api/spreadsheet/open',
    saveUrl: 'https://ej2services.syncfusion.com/production/web-services/api/spreadsheet/save',
        created: function () {
            fetch("https://js.syncfusion.com/demos/ejservices/data/Spreadsheet/LargeData.xlsx") // fetch the remote url
                .then((response) => {
                    response.blob().then((fileBlob) => { // convert the excel file to blob
                    var file = new File([fileBlob], "Sample.xlsx"); //convert the blob into file
                    spreadsheet.open({ file: file }); // open the file into Spreadsheet
                    })
                })
            },

    created: function () {
    //spreadsheet作成後に実行される
    spreadsheet.height = document.documentElement.clientHeight-30; //spreadsheetの高さをWEBビューアに合わせる
	performScriptWithOption('boolSpreadsheet(bool)', 1, '5', 0);   //spreadsheetが作成されたことをFileMakerに伝える
    }
});

// Render initialized Spreadsheet.
spreadsheet.appendTo('#spreadsheet');

window.addEventListener('resize', function () {
    //ウインドウ リサイズ時に実行される
    //Set height for a spreadsheet while resizing the window.
    spreadsheet.height = document.documentElement.clientHeight-30;
});

//現在のスプレッドシートの内容をJson形式で保存
//FileMaker,テーブル:Spreadsheet フィールド:SpreadsheetDataAsJson に保存
const asyncSaveAsJson = async () => {
  let promise = spreadsheet.saveAsJson().then(Json => (response = Json)); // to save JSON data in Spreadsheet.
  let result = await promise; 
  console.log(JSON.stringify(response.jsonObject ));
  performScriptWithOption('ReceiveSpreadsheetDataAsJson', JSON.stringify(response.jsonObject ), '3', 0);
}
　
//保存ボタン
document.getElementById("save").onclick = () => {
  asyncSaveAsJson();
};

//フィールド:SpreadsheetDataAsJson に保存したデータを読み込み
document.getElementById("load").onclick = () => {
 //spreadsheet.openFromJson({ file: response.jsonObject }); // To load JSON data in the Spreadsheet.
 performScriptWithOption('SetJsonToSpreadsheet', '', '3', 0); 
};

//スプレッドシートへデータを渡し描画
const setJsonToSpreadsheet = (json) =>{
  let obj = JSON.parse( json )
  spreadsheet.openFromJson({ file: obj });
}
```

#### FileMakerスクリプト

```java:スクリプト:OnFirstWindowOpen
スクリプト実行 [ 「StartupProcess」 ]
```

```java:スクリプト:StartupProcess
スクリプト実行 [ 「Output_SourceCode」 ]
変数を設定 [ $$pathHtmlSpreadsheet; 値:Let([ ~path=Get ( テンポラリパス ) & "Spreadsheet.html" ;~os=Get (システムプラットフォーム) ]; Case ( ~os=1 ; ConvertFromFileMakerPath (~path ; URLPath) ; ~os=-2 ; ConvertFromFileMakerPath (~path ; URLPath) ; ~os=3 ; "file:/" & ConvertFromFileMakerPath (~path ; PosixPath) ; ConvertFromFileMakerPath (~path ; URLPath) ) ) ]
変数を設定 [ $$ExecutedStartupProcess; 値:1 ]
レイアウト切り替え [ 「Spreadsheet」 (Spreadsheet) ]
ウインドウを選択 [ 現在のウインドウ ]
Loop
Exit Loop If [ $$boolSpreadsheet = 1 ]
新規ウインドウ [ スタイル: カード; 名前: "processing"; 使用するレイアウト: 「processing」 (Spreadsheet); 閉じる: はい; 最小化: いいえ; 最大化: いいえ; サイズ変更: いいえ; メニューバー: いいえ; 親ウインドウを淡色表示: はい; ツールバー: いいえ ]
スクリプト一時停止/続行 [ 間隔（秒）: 1 ]
End Loop
ウインドウを閉じる [ 名前: "processing"; 現在のファイル ]
```

##### WEBビューア用 spreadsheet.html,spreadsheet.js をテンポラリフォルダへエクスポート
```java:スクリプト:Output_SourceCode
レイアウト切り替え [ 「SourceCode」 (SourceCode) ]
全レコードを表示
変数を設定 [ $count; 値:Get(対象レコード数) ]
変数を設定 [ $n; 値:0 ]
変数を設定 [ $temporaryPath; 値:Get ( テンポラリパス ) ]
Loop
Exit Loop If [ Let($n=$n+1;$n>$count) ]
レコード/検索条件/ページへ移動 [ $n ] [ ダイアログなし ]
If [ not IsEmpty ( SourceCode::fileName ) ]
変数を設定 [ $object; 値:TextEncode (SourceCode::code ; "utf-8" ; 3) ]
変数を設定 [ $filePath; 値:$temporaryPath & SourceCode::fileName ]
データファイルを作成 [ 「$filePath」 ; フォルダを作成: オン ]
データファイルを開く [ 「$filePath」 ; ターゲット: $fileID ]
データファイルに書き込む [ ファイル ID: $fileID ; データソース: $object ; 書き込み: UTF-8 ; 改行を追加: オフ ]
データファイルを閉じる [ ファイル ID: $fileID ]
End If
End Loop
```

##### スプレッドシート保存データをWEBビューアから受け取る

```java:スクリプト:ReceiveSpreadsheetDataAsJson
変数を設定 [ $arg; 値:Get(スクリプト引数) ]
フィールド設定 [ Spreadsheet::SpreadsheetDataAsJson; $arg ]
レコード/検索条件確定 [ ダイアログなし ]
```

##### フィールド:SpreadsheetDataAsJson に保存したデータをスプレッドシートへ
```java:スクリプト:SetJsonToSpreadsheet
変数を設定 [ $json; 値:Spreadsheet::SpreadsheetDataAsJson ]
Web ビューアで JavaScript を実行 [ オブジェクト名: "wv_Spreadsheet"; 関数名: "setJsonToSpreadsheet"; 引数 1: $json ]
```

##### spreadsheetが作成されたことを確認するために使用

```java:スクリプト:boolSpreadsheet(bool)
変数を設定 [ $$boolSpreadsheet; 値:Get(スクリプト引数) ]
```

##### spreadsheet 描画

```java:スクリプト:SetJsonToSpreadsheet(json)
変数を設定 [ $arg; 値:Get(スクリプト引数) ]
変数を設定 [ $json; 値:$arg ]
If [ $$ExecutedStartupProcess ≠ 1 ]
スクリプト実行 [ 「StartupProcess」 ]
End If
変数を設定 [ $fileName; 値:JSONGetElement ( $json ; "fileName" ) ]
変数を設定 [ $tableName; 値:JSONGetElement ( $json ; "tableName" ) ]
変数を設定 [ $rows; 値:JSONGetElement ( $json ; "rows" ) ]
変数を設定 [ $rows; 値:Substitute ( $rows ; "\"cells\":" ; "\"height\":26,\"cells\":" ) ]
レイアウト切り替え [ 「Spreadsheet」 (Spreadsheet) ]
ウインドウを選択 [ 現在のウインドウ ]
If [ Spreadsheet::fileName ≠ $fileName or Spreadsheet::tableName ≠ $tableName ]
検索モードに切り替え [ ]
フィールド設定 [ Spreadsheet::fileName; "==" & $fileName ]
フィールド設定 [ Spreadsheet::tableName; "==" & $tableName ]
エラー処理 [ オン ]
検索実行 [ ]
エラー処理 [ オフ ]
If [ Get(対象レコード数) = 0 ]
新規レコード/検索条件
フィールド設定 [ Spreadsheet::fileName; $fileName ]
フィールド設定 [ Spreadsheet::tableName; $tableName ]
End If
End If
If [ IsEmpty ( Spreadsheet::SpreadsheetDataAsJson ) ]
テキストを挿入 [ $default ] [ 選択 ]
フィールド設定 [ Spreadsheet::SpreadsheetDataAsJson; $default ]
End If
If [ Spreadsheet::applyStyle = 1 ]
スクリプト実行 [ 「AddStyle[cells](json)」; 引数: $rows ]
変数を設定 [ $rows; 値:Get(スクリプトの結果) ]
End If
変数を設定 [ $SpreadsheetDataAsJson; 値:JSONSetElement ( Spreadsheet::SpreadsheetDataAsJson ; "Workbook.sheets[0].rows" ; $rows ; JSONArray ) ]
Web ビューアで JavaScript を実行 [ オブジェクト名: "wv_Spreadsheet"; 関数名: "setJsonToSpreadsheet"; 引数 1: $SpreadsheetDataAsJson ]
```

##### スプレッドシートのスタイルを適用

```java:スクリプト:AddStyle[cells](json)
テキストを挿入 [ $dataJson ] [ 選択 ]
変数を設定 [ $dataRows; 値:JSONGetElement ( $dataJson ; "rows" ) ]
変数を設定 [ $dataRows; 値:Get(スクリプト引数) ]
変数を設定 [ $dataRowsListKeys; 値:JSONListKeys ( $dataRows ; "" ) ]
変数を設定 [ $countData; 値:ValueCount ( $dataRowsListKeys ) ]
変数を設定 [ $tempJson; 値:JSONGetElement ( Spreadsheet::SpreadsheetDataAsJson ; "Workbook.sheets[0]" ) ]
変数を設定 [ $tempRows; 値:JSONGetElement ( $tempJson ; "rows" ) ]
変数を設定 [ $tempRowsListKeys; 値:JSONListKeys ( $tempRows ; "" ) ]
変数を設定 [ $countTemp; 値:ValueCount ( $tempRowsListKeys ) ]
変数を設定 [ $count; 値:GetAsNumber ( GetValue ( SortValues ( List( $countData; $countTemp ) ; 2) ; 1) ) ]
変数を設定 [ $n; 値:0 ]
Loop
Exit Loop If [ Let($n=$n+1;$n>$count) ]
変数を設定 [ $tempRow; 値:JSONGetElement ( $tempRows ; "[" & $n-1 & "]" ) ]
変数を設定 [ $height; 値:JSONGetElement ( $tempRow ; "height" ) ]
If [ not IsEmpty ( $height ) and Left($height;1) ≠ "?" ]
変数を設定 [ $key; 値:"[" & $n-1 & "].height" ]
変数を設定 [ $dataRows; 値:JSONSetElement ( $dataRows ; $key ; $height ; JSONNumber ) ]
End If
######
変数を設定 [ $tempCells; 値:JSONGetElement ( $tempRow ; "cells" ) ]
変数を設定 [ $tempCellsListKeys; 値:JSONListKeys ( $tempCells ; "" ) ]
変数を設定 [ $countB; 値:ValueCount ( $tempCellsListKeys ) ]
変数を設定 [ $nB; 値:0 ]
Loop
Exit Loop If [ Let($nB=$nB+1;$nB>$countB) ]
変数を設定 [ $style; 値:JSONGetElement ( $tempCells ; "[" & $nB-1 & "].style" ) ]
If [ $style ≠ "{}" and not IsEmpty ( $style ) ]
変数を設定 [ $key; 値:"[" & $n-1 & "].cells[" & $nB-1 & "].style" ]
変数を設定 [ $dataRows; 値:JSONSetElement ( $dataRows ; $key ; $style ; JSONObject ) ]
End If
End Loop
######
End Loop
現在のスクリプト終了 [ 結果: $dataRows ]
```

#### サンプルファイル:personal_infomation.fmp12 からJsonデータを作成し、ファイル:Spreadsheet.fmp12 へ送るスクリプト

```java:スクリプト:Spreadsheet
テキストを挿入 [ $titleList ] [ 選択  ;「連番
氏名
フリガナ
性別
電話番号
メールアドレス
郵便番号
住所1
住所2
生年月日」]

変数を設定 [ $count; 値:ValueCount ( $titleList ) ]
変数を設定 [ $n; 値:0 ]
Loop
Exit Loop If [ Let($n=$n+1;$n>$count) ]
変数を設定 [ $val; 値:GetValue ( $titleList ; $n ) ]
変数を設定 [ $cells; 値:JSONSetElement ( $cells ;[ "cells.[" & $n-1 & "].value" ; $val ; 1 ] ) ]
End Loop
テキストを挿入 [ $fieldList ] [ 選択 ;「personal_infomation::連番
personal_infomation::氏名
personal_infomation::氏名_カタカナ_
personal_infomation::性別
personal_infomation::電話番号
personal_infomation::メールアドレス
personal_infomation::郵便番号
personal_infomation::住所1
personal_infomation::住所2
personal_infomation::生年月日」]
変数を設定 [ $rows; 値:JSONSetElement ( $rows ; "[0]" ; $cells ; JSONObject ) ]
変数を設定 [ $countRec; 値:Get(対象レコード数) ]
変数を設定 [ $nRec; 値:0 ]
Loop
Exit Loop If [ Let($nRec=$nRec+1;$nRec>$countRec) ]
変数を設定 [ $n; 値:0 ]
Loop
Exit Loop If [ Let($n=$n+1;$n>$count) ]
変数を設定 [ $val; 値:Let([ ~fieldName=GetValue ( $fieldList ; $n ) ]; GetNthRecord ( Evaluate ( ~fieldName ) ; $nRec ) ) ]
変数を設定 [ $cells; 値:JSONSetElement ( $cells ;[ "cells.[" & $n-1 & "].value" ; $val ; 1 ] ) ]
End Loop
変数を設定 [ $rows; 値:JSONSetElement ( $rows ; "[" & $nRec & "]" ; $cells ; JSONObject ) ]
End Loop
変数を設定 [ $json; 値:JSONSetElement ( "" ;[ "fileName" ; Get ( ファイル名 ); JSONString ] ;[ "tableName" ; Get ( レイアウトテーブル名 ) ; JSONString ] ;[ "rows" ; $rows ; JSONArray ] ) ]
ファイルを開く [ 「Spreadsheet」 ]
スクリプト実行 [ 「SetJsonToSpreadsheet(json)」 , ファイル: 
```

#### スプレッドシートデータ サンプル
> メモ:
Workbook.sheets[0]rows[0].height //行の高さ
Workbook.sheets[0]rows[0].cells[0]style //セルのスタイル
```json:スプレッドシートデータ サンプル
{
    "Workbook": {
        "locale": "ja-JP",
        "allowOpen": true,
        "openUrl": "https://ej2services.syncfusion.com/production/web-services/api/spreadsheet/open",
        "saveUrl": "https://ej2services.syncfusion.com/production/web-services/api/spreadsheet/save",
        "enableRtl": false,
        "enablePersistence": false,
        "cellStyle": {
            "fontFamily": "Calibri",
            "verticalAlign": "bottom",
            "textIndent": "0pt",
            "backgroundColor": "#ffffff",
            "color": "#000000",
            "textAlign": "left",
            "fontSize": "11pt",
            "fontWeight": "normal",
            "fontStyle": "normal",
            "textDecoration": "none",
            "border": "",
            "borderLeft": "",
            "borderTop": "",
            "borderRight": "",
            "borderBottom": ""
        },
        "showRibbon": true,
        "showFormulaBar": true,
        "showSheetTabs": true,
        "allowEditing": true,
        "allowSave": true,
        "enableContextMenu": true,
        "allowAutoFill": true,
        "selectionSettings": {
            "mode": "Multiple"
        },
        "enableKeyboardNavigation": true,
        "allowNumberFormatting": true,
        "enableKeyboardShortcut": true,
        "enableClipboard": true,
        "allowCellFormatting": true,
        "allowSorting": true,
        "allowResizing": true,
        "allowHyperlink": true,
        "allowUndoRedo": true,
        "allowFiltering": true,
        "allowWrap": true,
        "allowInsert": true,
        "allowDelete": true,
        "allowDataValidation": true,
        "allowFindAndReplace": true,
        "allowMerge": true,
        "allowConditionalFormat": true,
        "allowImage": true,
        "allowChart": true,
        "activeSheetIndex": 0,
        "cssClass": "",
        "height": 794,
        "width": "100%",
        "allowScrolling": true,
        "scrollSettings": {
            "enableVirtualization": true,
            "isFinite": false
        },
        "allowFreezePane": true,
        "definedNames": [],
        "isProtected": false,
        "password": "",
        "autoFillSettings": {
            "showFillOptions": true
        },
        "showAggregate": true,
        "filterCollection": [],
        "sortCollection": [],
        "sheets": [
            {
                "activeCell": "A1",
                "colCount": 100,
                "columns": [
                    {},
                    {
                        "customWidth": true,
                        "width": 100
                    },
                    {
                        "customWidth": true,
                        "width": 138
                    },
                    null,
                    {
                        "customWidth": true,
                        "width": 115
                    },
                    {
                        "customWidth": true,
                        "width": 236
                    },
                    {
                        "customWidth": true,
                        "width": 74
                    },
                    {
                        "customWidth": true,
                        "width": 238
                    },
                    null,
                    {
                        "customWidth": true,
                        "width": 91
                    }
                ],
                "frozenColumns": 0,
                "frozenRows": 0,
                "index": 0,
                "isProtected": false,
                "name": "Sheet1",
                "paneTopLeftCell": "A1",
                "protectSettings": {
                    "selectUnLockedCells": false
                },
                "rowCount": 100,
                "rows": [
                    {
                        "cells": [
                            {
                                "value": "連番"
                            },
                            {
                                "value": "氏名"
                            },
                            {
                                "value": "フリガナ"
                            },
                            {
                                "value": "性別"
                            },
                            {
                                "value": "電話番号"
                            },
                            {
                                "value": "メールアドレス"
                            },
                            {
                                "value": "郵便番号"
                            },
                            {
                                "value": "住所1"
                            },
                            {
                                "value": "住所2"
                            },
                            {
                                "value": "生年月日"
                            }
                        ],
                        "height": 26
                    },
                    {
                        "cells": [
                            {
                                "value": "10001"
                            },
                            {
                                "value": "中 美恵子"
                            },
                            {
                                "value": "ナカ ミエコ"
                            },
                            {
                                "value": "女"
                            },
                            {
                                "value": "0984-3-3569"
                            },
                            {
                                "value": "miekonaka@emiz.jg"
                            },
                            {
                                "value": "880-0914"
                            },
                            {
                                "value": "宮崎県宮崎市宮の元町2-16-14"
                            },
                            {
                                "value": "宮の元町スカイ100"
                            },
                            {
                                "value": "1965/08/29",
                                "format": "mm-dd-yyyy"
                            }
                        ],
                        "height": 26
                    }
                ],
                "selectedRange": "A1:A1",
                "showGridLines": true,
                "showHeaders": true,
                "state": "Visible",
                "topLeftCell": "A1",
                "usedRange": {
                    "rowIndex": 1,
                    "colIndex": 9
                },
                "id": 1
            }
        ]
    }
}
```

## 作り込めば...
:::note info
以下でスプレッドシートのデータが取得出来るので、スプレッドシートでデータを入力し、FileMakerへ登録することも可能。
:::
```JavaScript
const asyncSaveAsJson = async () => {
  let promise = spreadsheet.saveAsJson().then(Json => (response = Json)); // to save JSON data in Spreadsheet.
  let result = await promise; 
  console.log(JSON.stringify(response.jsonObject ));
performScriptWithOption('ReceiveSpreadsheetDataAsJson', JSON.stringify(response.jsonObject ), '3', 0);
}
```
## 不具合

- 罫線を付けたら行がずれる。
![Image 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/6e0f087c-f8e4-b781-d4d8-38b2cb94be04.png)