GoogleAppsScriptを用いた学生実験レポートの自動化

#はじめに

プログラミングを用いて学生実験のデータ加工からグラフ作成まで自動化する手法を紹介します。

この記事は、授業でC言語は触ったことある！くらいのひとを対象に描きます。

しかしながら、GoogleAppsScriptに関する記事はネット上に少ないようなので、レポートの自動化以外の場面でも応用が効くと思います。

#用意するもの

- GoogleSpreadSheet
- 実験データ
- 楽をするぞ！という気持ち

実験データはGoogleSpreadSheetに保存するようにしてください。GoogleSpreadSheetはマイクロソフトが提供するExelのGoogle版みたいなものです。

今回はこんなデータを用いました。周波数に対して色々な値をかけたりルートを取ったりして、理論値(単位:dB)を求めます。

![スクリーンショット 2021-06-09 9.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1530170/0ce69329-5193-d427-79f4-db7485c2bb00.png)


#自動化する上でのコツ

計算を自動化する上でのコツは、自分で計算した方が早いところは自分の手で計算することです。(当たり前かもしれませんが笑)

今回であれば次のような回路のインピーダンス、電気系以外の人向けの言い換えると回路抵抗を求め、いくつかの加工を施した後に$K=\frac{Zf}{Zs}$としてKの値を求め、$20log|K|$を取ることで理論値であるデシベルを求めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1530170/261357c1-2276-cb13-12d3-6524763142ff.png)
電気系以外の人もこの記事を読むことをを想定しているので細かいところは省きますが、ZfはC,Rf1,Rf2を用いて次のような式で表されます。

$Zf=\frac{Rf2(Rf1+\frac{1}{jC\omega})}{Rf2+(\frac{1}{jC\omega}+1)}$

このとき、式には虚数単位(j)が混じっており、このZfの絶対値をそのまま計算するプログラムを書くのは、できないことはないですがちょっとめんどくさいです。

そこでZfを次のように変形します。

$Zf=\frac{Rf2(Rf1+\frac{1}{jC\omega})}{Rf2+(\frac{1}{jC\omega}+1)}=\frac{Rf1+Rf1Rf2(Rf1+Rf2)(C\omega)^2+jCRf1^2\omega}{1+((Rf1+Rf2)C\omega)^2}$

ちょっと複雑になりましたが、これだったら$|Zf|=\sqrt{Re(Zf)^2+Im(Zf)^2}$で計算可能なのでプログラムを書くのが楽になりました。

#プログラムで計算を自動化

では、いよいよ自動化するプログラムを書きます。GoogleSpreadSheet→ツール→スクリプトエディタと移動していきます。

そうすると、GoogleAppsScriptのページに移動するはずです。

GoogleAppsScriptとは、JavaScriptベースのスクリプト言語で、ドキュメント、​スプレッドシート、スライド、フォームなどのG Suiteサービスをカスタマイズ、拡張できます。

![スクリーンショット 2021-06-09 9.15.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1530170/631cb528-0524-b4d5-71d1-134da7e62962.png)
すると次のようなコードがあらかじめ記述されていると思います。

```
function myFunction() {
  
}
```

このフォーマットに沿ってコードを書いていきます。

今回は、Zs,Rf1,Rf2,C,$\omega=2\pi f$を用いてデシベルの理論値を計算するプログラムを書きます。

このプログラムは次の通りになります。

C言語で関数を書くことが出来れば難しくはないと思います。

今回は私のレポートを題材にしてQiitaを執筆しているので、以下のコードはみなさんの必要に応じて変更してください。

```getDecibel.js
//周波数を引数にとってデシベルをreturnする関数
function getDecibel(frequency) {
  //実験時に用いた各定数はconstで宣言
  const Rf1 = 100000;
  const Rf2 = 10000;
  const Zs = 1000;
  const C = 0.0000000047;
  const w = 2*Math.PI*frequency;

  //Zfを求めるのに必要な分母と分子の計算
  const denominator = 1+getSquare((Rf1+Rf2)*w*C);
  const numerator = getSqrt(Rf1+Rf1*Rf2*(Rf1+Rf2)*getSquare(w*C),w*C*getSquare(Rf1));

  Zf = numerator/denominator;
  K = Zf/Zs;

  dB = 20*Math.log10(K);

  return dB;
}

//getDecibelに用いるサブ関数
function getSqrt(x,y) {

  z = Math.sqrt(x*x + y*y);

  return z;
}

//getDecibelに用いるサブ関数
function getSquare(x) {
  return x*x;
}
```
#GoogleSpreadSheetのセルから値を持ってくる

getDecibel関数では、周波数を引数にとってデシベルの理論値を計算して返しています。

GoogleSpreadSheetの各周波数値を関数にいちいち代入してもいいですが、せっかくなので値をGoogleSpreadSheetから取ってきて、関数に代入し、GoogleSpreadSheetに代入するところまで自動化してしまいましょう。

そこで、次のような関数を書きます。

```putValuesToSheet.js
function putValuesToSheet() {
  var gss = SpreadsheetApp.getActiveSheet();

  for (let i = 3;i < 22; i++) {
    var cell = gss.getRange(i,4);
    var f = gss.getRange(i,2).getValue();

    cell.setValue(getDecibel(f));
  }
}
```

C言語では変数名を必ず宣言するので、varやconstという書き方に違和感を覚えてた人がいるかもしれません。

これらは、var(=variable)やconstと宣言し名前を付ければ、どんな値が代入されるかでコンピューターが都合のいいように解釈してくれるという仕組みに基づいているものだと思っていただいて構いません。

それらを踏まえて、putValuesToSheet関数を見てみます。

まずgssという変数にSpreadsheetApp.getActiveSheet()を用いて対応するGoogleSpreadSheetを紐づけています。

その後、gssのi行4列目のセルをcellという変数に対応させ、fに対してgetRange()とgetValue()でi行2列目から周波数の値を取ってきています。

最後に、setValue()を用いて対応させたcellに対して値を書き込んでいます。getDecibel()には、fに保存していたGoogleSpreadSheetに書き込んである周波数値を代入して、getDecibel()の戻り値であるデシベルの理論値を書き込むという仕組みです。

全体をfor文を用いてループしていて、1行づつgetDecibel()の計算と計算結果の書き込みが行われています。

#実行結果

実行結果は次のようになりました。

グラフもプログラムで書くことができますが、今回は割愛します。

C列の実験値とD列の理論値がほとんど一緒でした！

![スクリーンショット 2021-06-09 10.00.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1530170/18d57388-1fc0-e4fb-f8b5-69ce213728ea.png)

#さいごに

こんな感じに綺麗に自動化できるとプログラミング学んでいてよかったなぁって思います！

この記事が、ここまで読んでくださった方の役に立てば幸いです。