[GAS]スプレッドシートのフィルタビューを一括削除する方法

**そのスプレッドシート、無法地帯になってませんか？**

スプレッドシートには「フィルタビュー」と「ベーシックフィルタ」の[2種類のフィルタ](https://support.google.com/a/users/answer/9308952?hl=ja)があります。

- フィルタビュー: 共同編集者からの見え方を変えずにデータをフィルタする
- ベーシックフィルタ: すべてのユーザーの画面に反映されるようにデータをフィルタする

フィルタビューは、各ユーザーが自由にフィルタを作成できるため、多くのユーザーが編集できるスプレッドシートはカオスになりがち。
混沌としたフィルタビューを整理すべく、Google Apps Scriptで一括削除する方法について解説します。

# 解いた課題

・フィルタビューの整理、一括操作

# 記事を書いた背景

前述の通り、フィルタビューは各ユーザーが好き勝手に作成できてしまいます。
また、削除のUIも一括操作がなく、ひとつひとつ削除をする必要があります。
メニューにずらっと並んでいますが、ソート順も指定ができません。
結果、いくつものフィルタビューが混在し、削除しようにも非常に煩わしい状態に。

**これを一括で削除できないか？**というのが今回の課題でした。

ベーシックフィルタはGAS標準のサービスに用意されているAPIを使えば簡単に削除ができます。
対して、**フィルタビューは拡張サービスを使わなければ操作ができません**。
インターネット上を検索してみても、Googleの拡張サービスを使ったコードやドキュメントはあまり情報がないのが現状です。

スプレッドシートにはマクロ生成機能が備わっており、画面上でスプレッドシートを操作すると、操作履歴がマクロとして記録され、GASのコードが自動生成されます。
しかしなんと、**フィルタビューはマクロ機能の対象外**なのです。

さらに、ググってみても、Qiitaで探してみても、フィルタビューの操作については日本語の記事がひとつもありませんでした。（執筆時点）
StackOverflowなどで英語のQAを探してみたところ、やっと見つけたのがこの拡張サービスによる削除の方法でした。

ちなみに、Sheets APIの公式記事には、コードはPythonですがフィルタビューの操作について記載がありました。
[Filters | Sheets API | Google Developers](https://developers.google.com/sheets/api/guides/filters)

# 実装

GASでの実装ですが、具体的には「Google Sheets API」を使います。
フィルタビュー、フィルタの順に記載します。

## フィルタビューの削除

フィルタビューは、以下の操作で作成できるもので、編集権限があるユーザーが個別にフィルタを作成できる機能です。
また、スプレッドシート単位で作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581277/92781516-a60d-40c2-6d9e-71b7bfe33913.png)

この拡張サービスをONにするには以下の手順で操作を行います。

スクリプトエディタのメニュー -> 「リソース」 -> 「Googleの拡張サービス」 -> 「Google Sheets API」をONに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581277/cb46f33d-6194-ee71-9609-8fb11fc08500.png)

Google Develop ConsoleでGoogle Sheets APIを有効にします。
https://console.developers.google.com/apis/library/sheets.googleapis.com?q=Sheets

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581277/93de4173-0042-641a-3893-b782a55d98a9.png)


これによってSheetsのAPIが使えるようになります。コードは以下の通りです。

```javascript:データフィルタの一括削除
// アクティブなスプレッドシートのIDを取得
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ssId = ss.getId()

// スプレドシートのデータフィルタを全て取得
const response = Sheets.Spreadsheets.getByDataFilter({
  dataFilters: [],
  includeGridData: false
}, ssId)
const requests = [] // 一括削除のリクエストデータを登録する配列
for (const sheet of response.sheets) {
  for (const filterView of sheet.filterViews) {
    // 一括削除に投げるフィルタIDをリクエストデータに追加
    requests.push({
      'deleteFilterView': {
        'filterId': filterView.filterViewId
      }
    })
  }
}

// 指定したデータフィルタを一括削除
if (requests.length > 0) {
  Sheets.Spreadsheets.batchUpdate({'requests': requests}, ssId)
} else {
  throw new Error('フィルタが1件もありません。処理を終了します。')
}​
```

特定の名前を含んだものだけを削除したければ、fiterView.titleでフィルタビューの名称を取得して必要なものだけをリクエストするように実装を加えれば実現可能です。

```javascript:特定のデータフィルタのみを削除（一部抜粋）
  for (const filterView of sheet.filterViews) {
    // 名前に「フィルタ」を含むもののみ削除対象とする
    if (filterView.title.indexOf('フィルタ') > -1) {
      // 一括削除に投げるフィルタIDをリクエストデータに追加
      requests.push({
        'deleteFilterView': {
          'filterId': filterView.filterViewId
        }
      })
    }
  }
```

## ベーシックフィルタの削除

ベーシックフィルタは以下の操作で作成できるもので、すべてのユーザに共通して適用されるフィルタです。
また、シート単位で作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581277/900d3845-0e77-e7dc-6a76-7c230d0cae2c.png)

ベーシックフィルタについてはSheet#getFliter()を使って簡単に削除ができます。

[Class Sheet | Apps Script | Google Developers](https://developers.google.com/apps-script/reference/spreadsheet/sheet#getFilter())

```javascript:ベーシックフィルタの削除
const ss = SpreadsheetApp.getActiveSpreadsheet()
const sheet = ss.getSheetByName('対象のシート')

// フィルタを削除
const filter = sheet.getFilter()
if (filter) {
  filter.remove()
}

```