[Google Sheets API] フィルタビューを追加・更新・複製・削除する

Google Sheets API v4（Java）を使用して、
スプレットシートのシートにフィルタビューを追加・削除する方法
についてご紹介します。

#### フィルタとは
スプレットシートには下記２種類のフィルタが存在します。

・フィルタビュー（フィルタ表示）
名前をつけてフィルタを定義できます。
複数定義することが可能で、使用したいフィルタを自由に呼び出すことができます。
シートメニュー：「データ」⇨「フィルタ表示」で追加・削除・編集ができます。

・Basicフィルタ（フィルタ）
シートに一つだけ設定できるフィルタです。
シートメニュー：「データ」⇨「フィルタを作成」または「フィルタを削除」で
追加・削除ができます。
Basicフィルタの詳細は以下の記事を参照ください。
[[Google Sheets API] Basicフィルタを追加・削除する](https://qiita.com/doran/items/80ea26eff1e28845831e)

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Sheets API] Google Sheets API v4をJavaで操作する](https://qiita.com/doran/items/3d43f776188b2281044c)
を参照ください。
```
例：requests.add(moveDimension(sheetId)); //実行したいリクエストのMethodを指定
```
:::

:::note info
その他のGoogle Sheets APIは、下記の記事を参照ください。
[⧉[Google Sheets API] JavaでスプレットシートのメニューとAPIを関連づけてみた](https://qiita.com/doran/items/2f6f8932b994fbd1a170)
:::

|No||目次|
|---|---|---|
|1||[フィルタビューの追加](#1-フィルタビューの追加)|
||1|[並べ替え](#11-並べ替え)|
||2|[色でフィルタリングする場合](#12-色でフィルタリングする場合)|
||3|[条件でフィルタリングする場合](#13-条件でフィルタリングする場合)|
||4|[値でフィルタリングする場合](#14-値でフィルタリングする場合)|
|2||[フィルタビューの更新](#2-フィルタビューの更新)|
|3||[フィルタビューの複製](#3-フィルタビューの複製)|
|4||[フィルタビューの削除](#4-フィルタビューの削除)|

## 1. フィルタビューの追加
フィルタビューを追加します。
同じフィルタビューのID(setFilterViewId) または フィルタビューの名前(setTitle)
が既に設定されている場合はエラーになります。

**サンプル コード**
A列の指定した日付以降で、B列を降順にソートしたフィルタビューを追加します。
```
public Request addFilterView(Integer sheetId) {
    Request request = new Request();

    //フィルタビューを適用する範囲の設定
    GridRange range = new GridRange();
    range.setSheetId(sheetId);                //設定するシートID
    range.setStartRowIndex(0);                //開始行(0スタート)
    range.setEndRowIndex(7);                  //終了行(1スタート)
    range.setStartColumnIndex(0);             //開始列(0スタート)
    range.setEndColumnIndex(2);               //終了列(1スタート)

    //並べ替えの設定
    List<SortSpec> sortSpecs = new ArrayList<>();
    SortSpec sort = new SortSpec();
    sort.setSortOrder("DESCENDING");           //降順にソート
    sort.setDimensionIndex(1);                 //1列目(B列)に並び順を指定
    sortSpecs.add(sort);
    
    //フィルタの設定
    Map<String, FilterCriteria> criteria = new HashMap<>();
    BooleanCondition con = new BooleanCondition();
    List<ConditionValue> values = new ArrayList<>();
    ConditionValue value = new ConditionValue();
    value.setUserEnteredValue("2023-03-01");  //「2023-03-01」以降の日
    values.add(value);
    con.setValues(values);                    //条件の値。
    con.setType("DATE_AFTER");                //「次より後の日付」を指定
    
    FilterCriteria c = new FilterCriteria();
    c.setCondition(con);
    criteria.put("0", c);                     //0列目(A列)にフィルタを設定

    FilterView filter = new FilterView();
    filter.setFilterViewId(1);                //フィルタービューのID(省略すると自動で採番)
    filter.setTitle("フィルタビューテスト");        //ファイルタービューの名前
    filter.setRange(range);			          //フィルタを適用する範囲
    filter.setSortSpecs(sortSpecs);           //並べ替えの設定
    filter.setCriteria(criteria);             //フィルタの設定

    AddFilterViewRequest r = new AddFilterViewRequest();
    r.setFilter(filter);	                  //フィルタの設定

    request.setAddFilterView(r);
    return request;
}
```
**実行結果**
「フィルタビューテスト」という名前のフィルタビューがない状態で実行すると
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/4f751d24-c873-b0e2-d16e-f98eaae85271.png">

フィルタビューが追加され、A列の指定した日付以降が表示され、
B列が降順にソートされています。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/f01edf8c-8f15-a207-c486-474ab18fe8b1.png">

**その他の並び替えとフィルタリング**
サンプルで示した項目以外にも、様々な並び替えの指定や条件を設定できます。
スプレットシートのフィルタを選択して表示されるメニューはAPIで全て設定できます。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/43b8e14b-afc6-7469-b329-01d776010b3a.png">

### 1.1. 並べ替え
SortSpecクラスの下記メソッドで設定します。
・昇順で並べ替え
　　setSortOrder("ASCENDING")
・降順で並べ替え
　　setSortOrder("DESCENDING")
・色で並べ替え
　・塗りつぶしの色
  　　　setBackgroundColor または setBackgroundColorStyle
　・テキストの
  　　　setForegroundColor または setForegroundColorStyle

**サンプル コード**
A列を赤色のセルを昇順で並べ替えてみます。
```
Color color = new Color();
color.setRed(1.0f);color.setGreen(0f);color.setBlue(0f);

List<SortSpec> sortSpecs = new ArrayList<>();
SortSpec sort = new SortSpec();
sort.setSortOrder("ASCENDING");    //昇順を指定
sort.setBackgroundColor(color);    //塗りつぶし色を指定
sort.setDimensionIndex(0);         //0列目(A列)を指定
sortSpecs.add(sort);

FilterView filter = new FilterView();
filter.setSortSpecs(sortSpecs);    //並べ替えの設定
```
### 1.2. 色でフィルタリングする場合
FilterCriteriaクラスの下記メソッドで設定します。
　・色でフィルタ
　　・塗りつぶしの色
 　　　　setVisibleBackgroundColor または setVisibleBackgroundColorStyle
　　・テキストの色
 　　　　setVisibleForegroundColor または setVisibleForegroundColorStyle
     
**サンプル コード**
B列のフィルタに赤色のテキストだけを表示する設定を追加してみます。
```
Color color = new Color();
color.setRed(1.0f);color.setGreen(0f);color.setBlue(0f);

Map<String, FilterCriteria> criteria = new HashMap<>();
FilterCriteria f = new FilterCriteria();
f.setVisibleForegroundColor(color);  //テキストの色を指定
criteria.put("1", f);                //1列目(B列)にフィルタを設定

FilterView filter = new FilterView();
filter.setCriteria(criteria); 	     //フィルタの設定
```

### 1.3. 条件でフィルタリングする場合
BooleanConditionクラスでTypeをConditionValueクラスで条件の内容を設定します。
表中のvalueは、ConditionValueクラスのsetUserEnteredValueの必須数です。

|メニュー|サブ|type/RelativeDate|value|
|---|---|---|---|
|空白||BLANK|0|
|空白ではない||NOT_BLANK|0|
|次を含むテキスト||TEXT_CONTAINS|1|
|次を含まないテキスト||TEXT_NOT_CONTAINS|1|
|次で始まるテキスト：||TEXT_STARTS_WITH|1|
|次で終わるテキスト：||TEXT_ENDS_WITH|1|
|完全一致するテキスト||TEXT_EQ|1|
|日付||DATE_EQ||
||本日|TODAY|0|
||明日|TOMORROW|0|
||昨日|YESTERDAY|0|
||過去1週間以内|PAST_WEEK|0|
||過去1ヶ月以内|PAST_MONTH|0|
||過去1年以内|PAST_YEAR|0|
||正確な日付||1|
|次より前の日付||DATE_BEFORE||
||本日|TODAY|0|
||明日|TOMORROW|0|
||昨日|YESTERDAY|0|
||過去1週間以内|PAST_WEEK|0|
||過去1ヶ月以内|PAST_MONTH|0|
||過去1年以内|PAST_YEAR|0|
||正確な日付||1|
|次より後の日付||DATE_AFTER||
||本日|TODAY|0|
||明日|TOMORROW|0|
||昨日|YESTERDAY|0|
||正確な日付||1|
|次より大きい||NUMBER_GREATER|1|
|以上||NUMBER_GREATER_THAN_EQ|1|
|次より小さい||NUMBER_LESS|1|
|以下||NUMBER_LESS_THAN_EQ|1|
|次と等しい||NUMBER_EQ|1|
|次と等しくない||NUMBER_NOT_EQ|1|
|次の間にある||NUMBER_BETWEEN|2|
|次の間にない||NUMBER_NOT_BETWEEN|2|
|カスタム数式||CUSTOM_FORMULA|1|

**サンプル コード**
A列のフィルタに「次の間にある」と、
B列のフィルタに「次より前の日付」「本日」を追加してみます。
```
Map<String, FilterCriteria> criteria = new HashMap<>();

//A列のフィルタに「次の間にある」
BooleanCondition con1 = new BooleanCondition();
List<ConditionValue> values1 = new ArrayList<>();
ConditionValue v1_1 = new ConditionValue();
v1_1.setUserEnteredValue("1");   //値を2つ設定（1つ目）
ConditionValue v1_2 = new ConditionValue();
v1_2.setUserEnteredValue("10");  //値を2つ設定（2つ目）
values1.add(v1_1);
values1.add(v1_2);
con1.setValues(values1);
con1.setType("NUMBER_BETWEEN");  //「次の間にある」を指定
criteria.put("0", con1);         //0列目(A列)に設定

//B列のフィルタに「次より前の日付」「本日」
BooleanCondition con2 = new BooleanCondition();
List<ConditionValue> values2 = new ArrayList<>();
ConditionValue v2 = new ConditionValue();
v2.setRelativeDate("TODAY");     //「本日」を指定
values2.add(v2);
con2.setValues(values2);
con2.setType("DATE_BEFORE");     //「次より前の日付」を指定
criteria.put("1", con2);         //1列目(B列)に設定

FilterView filter = new FilterView();
filter.setCriteria(criteria); 	 //フィルタの設定
```
### 1.4. 値でフィルタリングする場合
FilterCriteriaクラスのsetHiddenValuesで指定した値を表示しないように設定します。

**サンプル コード**
A列のセルが「あいう」、「かきく」を表示しないようにフィルタリングしてみます。
```
Map<String, FilterCriteria> criteria = new HashMap<>();
FilterCriteria c = new FilterCriteria();
List<String> hidden = new ArrayList<>();
hidden.add("あいう");
hidden.add("かきく");
c.setHiddenValues(hidden);       //非表示にする値

criteria.put("0", c);            //0列目(A列)に設定

FilterView filter = new FilterView();
filter.setCriteria(criteria); 	 //フィルタの設定
```

## 2. フィルタビューの更新
設定済みのフィルタビューを更新します。

更新するフィルタビューのIDの指定は必須です。
存在しないフィルタビューのIDを指定するとエラーになります。

更新する内容はsetFieldsに文字列で指定します。
指定しない場合は更新されません。
複数更新する場合は、「,」で繋げます。（例：title,range）
|更新する内容|field|
|---|---|
|名前|title|
|範囲|range|
|並べ替え|sortSpecs|
|フィルタ|criteria|

**サンプル コード**
「名前」と「範囲」と「並べ替え」を更新します。
```
public Request updateFilterView(Integer sheetId) {
    Request request = new Request();

    GridRange range = new GridRange();
    range.setSheetId(sheetId);                //設定するシートID
    range.setStartRowIndex(0);                //開始行(0スタート)
    range.setEndRowIndex(50);                 //終了行(1スタート)
    range.setStartColumnIndex(0);             //開始列(0スタート)
    range.setEndColumnIndex(3);               //終了列(1スタート)

    List<SortSpec> sortSpecs = new ArrayList<>();
    SortSpec sort = new SortSpec();
    sort.setSortOrder("ASCENDING");            //昇順にソート
    sort.setDimensionIndex(1);                 //1列目(B列)に並び順を指定
    sortSpecs.add(sort);
    
    FilterView filter = new FilterView();
    filter.setFilterViewId(1);                 //更新するフィルタビューID(必須)
    filter.setTitle("フィルタビュー更新");         　//ファイルタービューの名前
    filter.setRange(range);			          　//フィルタを適用する範囲
    filter.setSortSpecs(sortSpecs);           　//並べ替えの設定	    

    UpdateFilterViewRequest r = new UpdateFilterViewRequest();
    r.setFields("title,range,sortSpecs");
    r.setFilter(filter);

    request.setUpdateFilterView(r);
    return request;
}
```
**実行結果**
このフィルタを更新します。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/f01edf8c-8f15-a207-c486-474ab18fe8b1.png">

「名前」と「範囲」と「並べ替え(B列を昇順に)」が更新されました。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/6f55e7ed-9cef-0bf6-0a8c-75dce3e20880.png">


## 3. フィルタビューの複製
設定済みのフィルタビューを複製します。

複製するフィルタビューのIDの指定は必須です。
存在しないフィルタビューのIDを指定するとエラーになります。

複製後のフィルタの名前は指定できません。
複製後のフィルタの名前は、「複製されるフィルタの名前"のコピー"」となります。
例：同じフィルタを複数回コピーした場合、
「テスト」 ⇨ 「テストのコピー」 ⇨ 「テスト(1)のコピー」 ⇨ 「テスト(2)のコピー」

**サンプル コード**
```
public Request duplicateFilterView(Integer sheetId) {
    Request request = new Request();

    DuplicateFilterViewRequest r = new DuplicateFilterViewRequest();
    r.setFilterId(1);             //複製したいフィルタID(必須)

    request.setDuplicateFilterView(r);
    return request;
}
```
**実行結果**
フィルタの名前「フィルタビュー更新」がコピーされました。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/b94f41e2-b505-79a1-8b2e-cf7e82674a55.png">


## 4. フィルタビューの削除
設定済みのフィルタビューを削除します。

削除するフィルタビューのIDの指定は必須です。
存在しないフィルタビューのIDを指定するとエラーになります。

**サンプル コード**
```
public Request deleteFilterView(Integer sheetId) {
    Request request = new Request();

    DeleteFilterViewRequest r = new DeleteFilterViewRequest();
    r.setFilterId(1);	//削除するフィルタID(必須)

    request.setDeleteFilterView(r);
    return request;
}
```
**実行結果**
フィルタの名前「フィルタビュー更新」を削除します。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/b94f41e2-b505-79a1-8b2e-cf7e82674a55.png">

フィルタが削除されました。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/942c3038-eb29-512f-f9be-9f08d0f7fda3.png">

おしまい。。