GAS（Google Apps Script）を使って感性実験用アンケートを作ってみた


# はじめに
感性実験では、順序効果を消すために質問の順序を考慮する必要があります。Googleフォームの機能で質問をランダムに並び変えることはできますが、細かい並び替えの条件を指定することはできません。
この記事では、GAS（Google App Script）を使って、感性実験用のフォームを作成する方法を紹介します。

## 実験設定
- 5文を4人が7件法で評価
- 1文に対する評価項目
    - 日本語として正しいと感じるか
    - 心に響くか
- 4人に対する文章の提示順はランダム

:::note warn
実験設定は記事を書くために適当に考えたものです。
:::

## 今回の実装
1. 文章が保存されたスプレッドシートから文章を取得
1. 提示順の並びかえ
1. フォームの作成
1. 複数フォームの一括作成



## Apps Scriptの開き方
まず、適当に新しいGoogleフォームを作成します。次に右上のボタンをスクリプトエディタを開けばApps Scriptを使うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958443/9ab5f223-48bc-3a6a-27ac-a68e3c0c3a66.png)


# スプレッドシートからのデータ取得
今回は以下のような形でスプレッドシートに文章を保存しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958443/45b255c9-949b-2de5-2688-a6fe9984a64a.png)


## スプレッドシートからデータを取得する関数
以下の関数では、シートの名前が`sheetName`のシート全体からデータを配列として取得し、列名の部分を除去して返すようになっています。

```
function getSpreadsheetData(sheetName) {
  var spreadsheetId = '文章を保存したスプレッドシートのID';
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);

  // 指定したシートを取得
  var sheet = spreadsheet.getSheetByName(sheetName);

  // データ範囲を取得
  var dataRange = sheet.getDataRange();
  
  // データを配列として取得
  var dataValues = dataRange.getValues();

　// 列名の除去
  var row = dataValues.length;
  var dataValues = dataValues.slice(1,row);

  // データを返す
  return dataValues;
}
```
### スプレッドシートのIDの取得方法
スプレッドシートやGoogleフォームにはIDが設定されています。IDはURLから取得することができます。URLの`d`と`edit`の間がIDになります。例えば、以下のURLの場合、`1A2B3C4D5E6F7G8H9I0J`がIDです。
```
https://docs.google.com/spreadsheets/d/1A2B3C4D5E6F7G8H9I0J/edit
```


## 取得したデータの並び替えを行う関数
行の並び替えを行う関数です。今回はランダムな並び替えで実装しています。
```
function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]]; // 行を入れ替え
  }
  return array;
}
```


# フォームを作成する関数
以下の関数を用いてフォームの作成を行います。`title`は作成するフォームのタイトル、`sentences`は`form`という変数に作成したフォームを格納し、`form`に対して関数を実行することで質問の追加などを行っていきます。
```
function createGoogleForm(title, sentences) {
  const form = FormApp.create(title); 
  const dataNum = sentences.length;
  
  // タイトルの設定
  form.setTitle(title)
      .setDescription('ChatGPTによって生成された文章の感じ方に関する調査です。文章を読み質問に7段階で答えてください。\n1...全く当てはまらない\n2...ほとんど当てはまらない\n3...あまり当てはまらない\n4...どちらともいえない\n5...やや当てはまる\n6...かなり当てはまる\n7...非常に当てはまる\n')
      .setConfirmationMessage('回答を受け付けました。')　
      .setCustomClosedFormMessage('回答は現在受け付けておりません。')
      .setAcceptingResponses(true);
      
　// 文章の提示と質問の提示
  for (var i = 0; i < dataNum; i++) {
    // 文章の提示
    form.addSectionHeaderItem()　
        .setTitle('文章' + (i+1))
        .setHelpText(sentences[i][1]); 
    // 質問項目の提示
    form.addScaleItem() 
        .setTitle('文章' + (i+1) + "は日本語として正しいと感じるか")
        .setBounds(1,7)　
        .setLabels("全く当てはまらない","非常に当てはまる")
        .setRequired(true);
    form.addScaleItem()
        .setTitle('文章' + (i+1) + "は心に響くか")
        .setBounds(1,7)
        .setLabels("全く当てはまらない","非常に当てはまる")
        .setRequired(true);
  }
　// フォームとシートをリンク　一つのスプレッドシートに回答が集まる
  form.setDestination(FormApp.DestinationType.SPREADSHEET, '回答収集用のスプレッドシートのID');
}
```


# 複数のGoogleフォームを一括で作成
以下の関数を実行することで4つの並び順の異なるフォームを作成します。
```
function main() {
  var sentences = getSpreadsheetData('sentence');

  for (var i = 0; i < 4; i++) {
    shuffledSentences = shuffleArray(sentences);
    var title = '文章の感じ方に関する調査' + (i+1);

    createGoogleForm(title, shuffledSentences);
  }
}
```
実行するとFromsのホームにフォームが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958443/12bf8ca7-e172-5aeb-0ebb-353e67854a23.png)

[フォーム](https://forms.gle/AGUvhUuiJ8qD2kK8A)の中身は以下のようになってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958443/4f801950-3e15-6aa1-89b9-c6c2a940c722.png)




## 注意
初回の実行では、GASにスプレッドシートへのアクセス権限を与えていないため、以下のような表示がされます。アクセス権限を付与するために、詳細のボタンを押して赤丸で囲った部分を押してアクセス権限を付与してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958443/e610c6e4-ec94-d60b-9971-21a10125c9cf.png)


# おわりに
今回の実装は私が行った実験に合わせているため、プログラム自体の汎用性はあまりないです。ただ、GASを使ってGoogleフォームを作成するときの参考にはなるかなと思います。

実装にあたって、以下の記事~~とChatGPT~~を参考にしました。

https://gas-4u.com/gas18/#index_id10