Jspreadsheet 使い方メモ3（カラム・セルオプション）

# はじめに
これは、[Jspreadsheet Advent Calendar 2024](https://qiita.com/advent-calendar/2024/jspreadsheet)の21日目の記事となります。

「[Handsontable 使い方メモ３（カラム・セルオプション）](https://qiita.com/opengl-8080/items/ccf5cbccd0ceb0a6bb47)」と比較しながら書いていきます。

※全てのオプションは網羅していません。

全てのオプションを確認したい場合は、 [公式ドキュメント](https://bossanova.uk/jspreadsheet/v4/docs/quick-reference) を参照

## 注意
現時点(2025/03/09)では、Jspreadsheet CE Version 4 を対象としています。
Version 5 のリリースにより見直す予定です。

https://bossanova.uk/jspreadsheet/docs/upgrade-from-v4-to-v5

# カラムオプション
`type`の指定は下記がある。
'text' | 'number' | 'numeric' | 'percent' | 'notes' | 'dropdown' | 'autocomplete' | 'calendar' | 'color' | 'checkbox' | 'radio' | 'autonumber' | 'progressbar' | 'rating' | 'email' | 'url' | 'image' | 'html' | 'hidden' | 'tags' | 'record'

https://jspreadsheet.com/docs/editors

## 基本
```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [{}],
  columns: [
    { 
      type: `text` 
    }
  ]
});
```

* カラムのオプション指定は、`columns`に配列を渡し、列番号に対応する要素にオブジェクトを渡すことで設定する

## `type`：カラムの型を指定する
### `text`：テキスト
```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'text' 
    }
  ]
});
```

* デフォルトは`text`
* 文字列入力になる
* 基本、何でも入力可能
* 文字は自動で中央寄せになる(Handsontableは左寄せ)

### `numeric`：数値
フォーマットや国際化（例：金額やカンマ区切り）が必要な場合は、`numeric`を選ぶのが適切です。単純なフォーマットなら、`number`を使用する。
但し、`format`を指定する必要がある。

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'numeric',
      format: '0'
    }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/ab3c6bdb-b345-6b9c-d5a7-95ece4a204a3.png)

* 数値の入力のみ可になる
* 数値以外を入力できない
* 文字は自動で中央寄せになる(Pro版は右寄せになる)
* 0のみ入力する場合、別数値を入力してから0を入力する(Pro版は改善済み)

#### フォーマットする
```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'number',
      format: '#,##0;[Red](#,##0)'
    }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/3079b556-0f4d-46dc-74eb-4c894a5136bc.png)

* `format` でフォーマットを指定できる
* [公式のフォーマット](https://jspreadsheet.com/docs/format)が使える

```
0
0.00
0%
0.00%
#,##0
#,##0.00
#,##0;(#,##0)
#,##0;[Red](#,##0)
#,##0.00;(#,##0.00)
#,##0.00;[Red](#,##0.00)
```

### `checkbox`：チェックボックス

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [
    [true],
    [false],
    [true]
  ],
  columns: [
    { 
      type: 'checkbox'
    }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/eb08fcfd-fef7-feb0-8169-ff7cc722990b.png)

* `checkbox`でチェックボックスになる
* `true`でチェックがオンになり、`false`でオフになる

#### オン・オフの値を変更する
Handsontableの`checkedTemplate`と`uncheckedTemplate`のような機能はない。

#### ラベルを表示する
Handsontableの`label`を表示する機能はない。

## `dropdown`：ドロップダウン
ブラウザ画面が狭い(800px未満)場合では項目選択画面は別画面になるが、広い場合はセル項目内で選択できる。

### 基本
```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'dropdown',
      source: ['one', 'two', 'three', 'four', 'five'],
      multiple: true
    }
  ]
});
```
ブラウザ画面が広い(800px以上)場合
![dropdown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/3a767968-aba5-8348-b933-d7f6985bf1d3.gif)

### 複数選択
複数選択を可能にするには、`multiple`に`true`を指定する。

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'dropdown',
      source: ['one', 'two', 'three', 'four', 'five']
    }
  ]
});
```

ブラウザ画面が広い(800px以上)場合
![dropdown2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/626ad6bf-ff24-6007-fadf-ca118bc8ee75.gif)

## `autocomplete`：オートコンプリート
`autocomplete` は、`dropdown` と違い、項目を検索できる。
ブラウザ画面が狭い(800px未満)場合では項目選択画面は別画面になるが、広い場合はセル項目内で選択できる。

### 基本

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'autocomplete',
      source: ['one', 'two', 'three', 'four', 'five']
    }
  ]
});
```
ブラウザ画面が狭い(800px未満)場合
![autocomplete.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/0b681588-f791-a7ee-fa36-bd7bd8b49348.gif)

* `type`を`autocomplete`にして`source`を指定すると、オートコンプリートが表示されるようになる
* 候補の検索は、部分一致で行われる
* `source`で定義した値以外は入力できない

### 複数選択
複数選択を可能にするには、`multiple`に`true`を指定する。

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'autocomplete',
      source: ['one', 'two', 'three', 'four', 'five'],
      multiple: true       
    }
  ]
});
```
![autocomplete2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d4b7271f-ce06-c69f-36f9-ee70e59e259c.gif)

* セミコロン(`delimiter`の初期値)区切りで複数の値をセットできる

### Handsontableとの違い
下記の機能はない
* `strict`：入力できる値を制限する
* `allowInvalid`：入力できる値を完全に制限する
* `source`に関数を指定する
* `filter`：候補を絞りこまないようにする

## `password`：パスワード
Handsontableの`password`のような機能はない。

## `calendar`：日付
Handsontableの`date`の機能に近いものは`calendar`にあたる。

https://jspreadsheet.com/docs/date

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'calendar'
    }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/28def881-0423-0095-ada8-4be6b0426547.png)

* `calendar` にすると日付入力になる
* セルの編集を開始すると、カレンダーが表示される

### `format`：日付書式を指定する
Handsontableの`dateFormat`の機能に近いものは`format`にあたる。

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [[]],
  columns: [
    { 
      type: 'calendar',
      options: {
        format: 'YYYY-MM-DD',
        months:['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
        weekdays:['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'], 
        weekdays_short: ['日', '月', '火', '水', '木', '金', '土'],
      }
    }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/6a8cd4af-4c94-c92c-db81-a10d9520ea2c.png)

* `options.format`で日付書式を指定できる

### Handsontableとの違い
下記の機能はない
* `defaultDate`：初期値を指定する
* `datePickerConfig`：細かい動作を調整する

## `type`：html をそのまま出力する
Handsontableの`renderer: 'html'`の機能に近いものは`type： 'html'`にあたる。

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [
    ['<u>underline</u>'],
    ['<a href="http://google.co.jp/">google</a>'],
    ['<button onclick="alert(\'hello\')">click</button>']
  ],
  columns: [
    { type: 'html' }
  ],
  defaultColWidth: 100
});
```

![typeHtml.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/3a34c547-9766-746d-5952-5bf29271032e.gif)

## `allowEmpty`：空入力を許可する
Handsontableの`allowEmpty`のような機能はない。

## `readonly`：読み取り専用
```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [
    ['hoge', 'fuga']
  ],
  columns: [
    { readOnly: true },
    { }
  ]
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/8121c275-41b9-ffd5-57a0-e2dd1be8023a.png)

* `readOnly`を`true` にすると、そのカラムは読み取り専用になる

## `allowInvalid`：不正な値の入力可否を制御する
Handsontableの`allowInvalid`のような機能はない。

## `validator`：入力値を制限する
Handsontableの`validator`のような機能はない。

## `className`：CSSクラスを設定する
Handsontableの`className`のような機能はない。

近いものとして、`style`を使用してCSSをセットすることはできる。

https://jspreadsheet.com/docs/style

```js
let grid = document.getElementById('grid');

let table = new jspreadsheet(grid, {
  data: [
    ['hoge', 'fuga']
  ],
  style: {
    'A1': 'background-color: #ccffff; font-weight: bold',
    'B1': 'color: red'
  }
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/6041a5b4-3a04-c920-816b-8752c21789d3.png)

* CE版は'A:A'という指定をしても反映されなかったが、Pro版は反映される

## セルの編集をドロップダウンにする
Handsontableの`editor: 'select'`に近いものとしては、`type: 'dropdown'`がある。

[ドロップダウン](#dropdown%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%83%80%E3%82%A6%E3%83%B3)

## セルを指定してオプションを設定する
Handsontableの`cell`のような機能はない。

列のタイプをプログラムで変更する方法はありそうです。

* [How to change the column type programatically..? #65](https://github.com/jspreadsheet/ce/issues/65)
* [How to change a cell type programatically ? #1016](https://github.com/jspreadsheet/ce/issues/1016)