Googleドキュメント(Google Docs)に図表番号挿入機能を実装する~実装とGoogleドキュメントへ適用~

[前回の記事(Googleドキュメント(Google Docs)に図表番号挿入機能を実装する~環境構築と仕様決定~)](https://qiita.com/Allermist/items/5675bc246984b052843c)では環境構築と機能の仕様を決定しました。

今回は作成した仕様に基づいて実装していきます。

各関数の細かい説明は省いているので、気になる方は[リファレンス](https://developers.google.com/apps-script/reference/document/)を見て下さい。


# 仕様

仕様については[前回の記事](https://qiita.com/Allermist/items/5675bc246984b052843c)で説明していますが、簡単に載せておきます。

- 図表番号の挿入機能
 - カーソル位置の取得
 - その位置に挿入すべき番号の取得
 - カーソル位置に番号を挿入
- 挿入後の自動更新機能
 - その位置において適切な番号の取得
 - 挿入前の番号を挿入後の番号へ置換
 

# 図表番号の挿入機能

- カーソル位置の取得
- その位置に挿入すべき番号の取得
- カーソル位置に番号を挿入

これら3つの処理を行うことで挿入機能は実現できます。

コード全体を先に載せておきますね。

```javascript:コード.gs
function insertFigTableNum( name){
  var coursor, bodyTexts, target;
  var cnt=0;
  var text;
  Logger.log( 'LOG: insertFigTableNum' );
  // 一度，挿入位置を示すための目印を挿入
  coursor = DocumentApp.getActiveDocument().getCursor();
  coursor.insertText('<INSERTNUM></INSERTNUM>');
  Logger.log( coursor.getSurroundingText().getText() );
  
  // 「'<INSERTNUM></INSERTNUM>'」を探しながら，そこに至るまで図表番号を数える．
  bodyTexts = DocumentApp.getActiveDocument().getBody().getText().split('\n');
  for(var i=0;i<bodyTexts.length;i++){
    Logger.log(bodyTexts[i]);
    target = bodyTexts[i].split('　')[0];
    Logger.log('target= '+target);
    if(target.split('')[0]==name) cnt++;
    if(target=='<INSERTNUM></INSERTNUM>') break;
    Logger.log('');
  }
  // 最後に，図表番号を挿入して終わり
  cnt++;
  text = name+cnt;
  coursor.getSurroundingText().replaceText('<INSERTNUM></INSERTNUM>',text+'　ここにタイトルを入れる');
}
```

引数のnameは「図」か「表」です。
coursorはカーソルの位置、
bodyTextsはドキュメント内に書かれているテキスト全部を改行で区切り、配列化したもの、
targetはbodyTexts[i]を全角スペースで区切った配列の先頭要素が入ります。
もし、図表番号がその行に書かれている場合は、targetに「図(半角数字)」もしくは「表(半角数字)」が入っています。

文中に出てくる「Logger.log()」はログです。
これはコードを書いている画面の「表示→ログ」から確認できます。

さて、肝心な処理内容ですが、図表位置を示すための目印をカーソル位置に挿入しておきます。
これをやっておくと、カーソル位置までに何個の図表番号があるのかをカウントしやすくなります。

```javascript:コード.gs(5~7行目まで)
  // getCursor()でカーソル位置の取得
  coursor = DocumentApp.getActiveDocument().getCursor();
  // insertText()でテキストの挿入
  coursor.insertText('<INSERTNUM></INSERTNUM>');
```


\<INSERTNUM>\</INSERTNUM> という目印を探しながら、そこに至るまで図表番号を数えていきます。
これで、新しく挿入したい位置に来るべき番号が分かる仕組みです。

図表番号のカウントは図表番号が
「 図(半角数字)(全角スペース)タイトルか説明 」
のようになっていることを利用して行っていきます。
ドキュメント内のテキストを改行で区切り、その行毎で全角スペースで区切ります。
これによって、区切った後の配列の先頭要素には「図(半角数字)」が入ることになります。

そして、その先頭要素の先頭文字は「図」なので「図」が先頭文字である時のみカウント用の変数「cnt」をインクリメントします。こうすることで、図番が出た回数を記録できます。

\<INSERTNUM>\</INSERTNUM> が来たら終了です。
図番号で説明しましたが、表番号の場合は「図」を「表」に読み替えてください。

```javascript:コード.gs(10~19行目まで)
  // 「'<INSERTNUM></INSERTNUM>'」を探しながら，そこに至るまで図表番号を数える．
  bodyTexts = DocumentApp.getActiveDocument().getBody().getText().split('\n');
  for(var i=0;i<bodyTexts.length;i++){
    Logger.log(bodyTexts[i]);
    target = bodyTexts[i].split('　')[0];
    Logger.log('target= '+target);
    if(target.split('')[0]==name) cnt++;
    if(target=='<INSERTNUM></INSERTNUM>') break;
    Logger.log('');
  }
```

最後に挿入する図表番号になるのでcntに1を加算し、挿入します。

```javascript:コード.gs(20~23行目まで)
  // 最後に，図表番号を挿入して終わり
  cnt++;
  text = name+cnt;
  coursor.getSurroundingText().replaceText('<INSERTNUM></INSERTNUM>',text+'　ここにタイトルを入れる');
```

ここまでで、図表番号の挿入機能の実装は終了です！


# 挿入後の自動更新機能

次は、挿入後の自動更新機能を実装していきましょう。

- その位置において適切な番号の取得
- 挿入前の番号を挿入後の番号へ置換
 
前章と同様に先にコードを載せておきます。

```javascript:コード.gs
function resettingFigTableNum( name){
  var bodyTexts, target, tmp, nonTarget;
  var cnt=0;
  Logger.log( 'LOG: resettingFigTableNum' );
  body = DocumentApp.getActiveDocument().getBody();
  bodyTexts = body.getText().split('\n');
  for(var i=0;i<bodyTexts.length;i++){
    Logger.log(bodyTexts[i]);
    tmp = bodyTexts[i].split('　');
    target = tmp[0];
    nonTarget = '';
    for(var k=1;k<tmp.length;k++){
      nonTarget += tmp[k];
    }
    Logger.log('target= '+target);
    Logger.log('nonTarget= '+nonTarget);
    if(target.split('')[0]==name){
      cnt++;
      Logger.log('after replace= '+name+cnt+'　'+nonTarget);
      body.editAsText().replaceText(bodyTexts[i],name+cnt+'　'+nonTarget);
      Logger.log('cnt= '+cnt);
    }
    Logger.log('');
  }
}
```

その位置において適切な番号の取得は図表番号の挿入機能の時と同じ要領で行うので説明は割愛します。
その位置において適切な番号の取得とは

> 図1&nbsp;&nbsp;図1のタイトル
> 図3&nbsp;&nbsp;図3のタイトル
> 図2&nbsp;&nbsp;図2のタイトル

のようになっている場合、図3は図2となるべき行にあるので、「2」を取得するということです。

この関数を組む上で追加した変数はnonTargetです。
nonTargetの役割は図のタイトルや説明を記憶しておくことです。

nonTarget以外の変数の役割は図表番号の挿入機能の時と同じです。

そして、19行目にある下記のコードで元の図表番号を新しい図表番号に置換します。
置換は replaceText() が行ってくれます。

```javascript:コード.gs(19行目)
      body.editAsText().replaceText(bodyTexts[i],name+cnt+'　'+nonTarget);
```

これで、挿入後の自動更新機能の実装が終わったことになります。

お疲れ様でした！

ってなりたいところですが、まだGoogleドキュメント側から実行できないんです……。

Googleドキュメント側から実行できるようにして初めて今回作成した機能は役に立つので、
次章でそれをやっていきます。


# Googleドキュメントへ適用
今回作成した機能をついにGoogleドキュメントへ適用していきますよ！
と言っても、難しい作業やコードは一切ないです。

下のコードをスクリプトに打ち込みましょう。

```javascript:コード.gs

function insertFigNum(){
  insertFigTableNum('図');
  resettingFigTableNum('図');
}

function insertTableNum(){
  insertFigTableNum('表');
  resettingFigTableNum('表');
}


function onOpen(){
  var menu = DocumentApp.getUi().createMenu('図表番号の挿入');
  menu.addItem('図番号の挿入','insertFigNum');
  menu.addItem('表番号の挿入','insertTableNum');
  menu.addToUi();
}
```

insertFigNum関数が図番号の挿入、insertTableNum関数が表番号の挿入をする関数です。
と言っても、前章・前々章で作成した関数に引数を与えて呼び出すだけですが。

onOpen関数はGoogleドキュメントに適用する時の呪文と思って下さい。

コードが書けたら、onOpen関数を実行します。
実行→関数を実行→onOpenの順にクリックして下さい。
<img width="613" alt="スクリーンショット 2019-07-22 23.10.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466919/185a1e42-ff64-07ef-3e27-0bdab0d83682.png">

これを実行することで下の画像には表示されていない　「図表番号の挿入」を
<img width="804" alt="スクリーンショット 2019-07-22 22.45.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466919/cbb2a77a-15e5-79bf-c475-c209a58e7314.png">
下の画像のように追加できるのです。
<img width="804" alt="スクリーンショット 2019-07-22 22.45.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466919/de8d9a64-9b7d-56f0-ca90-5be57bed4e10.png">

追加できたら早速実行です！
実行方法は「図表番号の挿入」をクリックして「図番号の挿入」か「表番号の挿入」を選択するだけです。


# まとめ
[前回の記事](https://qiita.com/Allermist/items/5675bc246984b052843c)と二部構成で書かせていただきましたが、いかがでしたでしょうか。
今回は図表番号の追加と更新だけでしたが、

> 図2&nbsp;&nbsp;図2のタイトル
> 
> 図2のように…………

みたいな感じで本文中で「図2」って表記した部分も挿入後に必要があれば

> 図3&nbsp;&nbsp;図3のタイトル
> 
> 図3のように…………

こんな感じで自動更新できるようにしたいですね。


では、お疲れ様でした。
良い「図表番号の挿入ライフ？」を送って下さい。

最後まで、お付き合いいただきありがとうございました。