GASとYahooAPIを使ってGoogleスライドへ自動ルビ振り

## 概要
Googleスライドで資料を作っており、一度にふりがなが触れたらなと思いやってみました。
結果として、ここまでできました。
「念の為」や「持っていきましょう」のところはおかしくなっています。（形態素分析の調整が必要？）

調整には時間がかかりそうだったので、今回は諦めました。
（最後は、人間の目で確認するため、その時手動で調整するようにしています。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/f5313d66-f6df-5fc6-8a3a-70723b561871.png)



## やり方
今回はYahooAPIの「ルビ振り」を使用しました。
https://developer.yahoo.co.jp/webapi/jlp/furigana/v2/furigana.html

使用するには、Client IDが必要ですので以下の手順を参考に登録を進めてください
https://developer.yahoo.co.jp/start/


### 実際のコード
以下のコードをGoogleスライドで使用します。


```
var APPID = "d*****-"; // <-- ここにあなたのClient ID（アプリケーションID）を設定してください。
var URL = "https://jlp.yahooapis.jp/FuriganaService/V2/furigana?appid=" + APPID;

function addRubyToText() {
  var slideApp = SlidesApp.getActivePresentation();
  var slides = slideApp.getSlides();
  
  for (var i = 0; i < slides.length; i++) {
    var shapes = slides[i].getShapes();
    for (var j = 0; j < shapes.length; j++) {
      var textRange = shapes[j].getText();
      if (textRange) {
        var text = textRange.asString();
        var rubyData = post(text);
        var words = rubyData.result.word;

        var currentPosition = 0; // 現在の文字の位置を追跡するための変数
        var currentLine = 0; // 現在の行を追跡するための変数
        var lineHeight = shapes[j].getText().getTextStyle().getFontSize() * 1.8; // 行の高さを推定

        //　一つのテキストボックス内で改行があった場合は、その行の文字の上にふりがなをふる
        for (var k = 0; k < words.length; k++) {
          if (words[k].surface === "\n") { // 改行を検出
            currentLine++;
            currentPosition = 0;
            continue;
          }

          if (words[k].furigana) {
            var textBox = slides[i].insertTextBox(words[k].furigana);
            var originalTextTop = shapes[j].getTop();
            var originalTextLeft = shapes[j].getLeft();
            var fontSize = shapes[j].getText().getTextStyle().getFontSize();
            textBox.getText().getTextStyle().setFontSize(fontSize * 0.5); // ふりがなのサイズを半分に

            // ふりがなのテキストボックスの大きさを調整
            var textBoxWidth = textBox.getWidth();
            var textBoxHeight = textBox.getHeight();
            //0.7の数値を変えればテキストボックスの長さを調整できます（0.５だと短すぎました）
            textBox.setWidth(textBoxWidth * (words[k].furigana.length / textBox.getText().asString().length)*0.7);
            textBox.setHeight(textBoxHeight * 0.5);

            textBox.setTop(originalTextTop + currentLine * lineHeight - fontSize * 0.5); // ふりがなを適切な行の上に配置
            textBox.setLeft(originalTextLeft + currentPosition * fontSize); // 現在の文字の位置に基づいてふりがなを配置
            currentPosition += words[k].surface.length; // 文字の位置を更新
          } else {
            currentPosition += words[k].surface.length; // ふりがながない場合も文字の位置を更新
          }
        }
        
        textRange.setText(text); // テキストボックスのテキストを更新
      }
    }
  }
}



function post(query) {
  var headers = {
      "Content-Type": "application/json",
      "User-Agent": "Yahoo AppID: " + APPID,
  };

  var param_dic = {
    "id": "1234-1",
    "jsonrpc": "2.0",
    "method": "jlp.furiganaservice.furigana",
    "params": {
      "q": query,
      "grade": 1
    }
  };
  
  var options = {
    "headers": headers,
    "payload": JSON.stringify(param_dic)
  };
  
  var response = UrlFetchApp.fetch(URL, options);
  var responseBody = JSON.parse(response.getContentText());
  
  // APIのレスポンスにresultが存在しない場合のエラーハンドリング
  if (!responseBody.result || !responseBody.result.word) {
    Logger.log("API Response: " + JSON.stringify(responseBody));
    throw new Error("APIからのレスポンスが期待した形式ではありません。");
  }
  
  // responseBodyからルビを取得して結果を返す
  var words = responseBody.result.word;
  var rubyText = "";
  for (var i = 0; i < words.length; i++) {
    if (words[i].furigana) {
      rubyText += words[i].surface + "(" + words[i].furigana + ")";
    } else {
      rubyText += words[i].surface;
    }
  }
  
  //return rubyText;
  return responseBody;
}

```



## 注意点
・オブジェクトをグループ化しているとうまくいかない
グループ化しているとその中のテキストボックスまで見ることができず、ふりがながふれない
→一時的に解除するしかないかも

・APIの利用回数には制限があります。
文字の多かったり何十ページもある資料だと、制限を超えてしまう恐れがありますので注意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/7f2e5065-bc9a-dcee-4585-1e1fbbdbad55.png)