Office ScriptでHTTP要求（外部 API 呼び出し）が成功したので備忘録

# はじめに
Google Apps Scriptの`UrlFetchAppクラス fetchメソッド`が
とても好きなので、Office Scriptでも案外できるのではないかと思い、
調査したところ、ちゃんと実現できそうでしたので、備忘録として記録します。

:::note warn
お願い
筆者の`TypeScript`および`Microsoft365 Excel`の機能理解が浅い部分がございますので
甘いところはご指摘いただければ幸いです。
:::

# リファレンス
Office ScriptでのHTTP要求（外部API呼び出し）については、
下記のサイトで実現できることが理解できました。

https://learn.microsoft.com/ja-jp/office/dev/scripts/develop/external-calls

`Power Automate`という強力なツールで、様々なAPI連携が実現できるようになっておりますが、
[プレミアム コネクタ](https://learn.microsoft.com/ja-jp/connectors/connector-reference/connector-reference-premium-connectors)が必要になり、ライセンスが異なります。

**Power Automateの力を十二分に活かすのであれば、プレミアム コネクタで実現することをおすすめします**が、
どうにもならない場面や、Excel Onlineを楽しむという意味でも、
Office Scriptによる実現方法は学ぶ価値があると思います。

https://learn.microsoft.com/ja-jp/power-platform/admin/power-automate-licensing/types

# 今回やってみたこと
まずは **入門編！** ということで「Google Books API」を使って検証してみたいと思います。

https://qiita.com/DEmodoriGatsuO/items/29f7b3e145b1215e5bb8

このAPIは以前Power Automateでも試したことがあるAPIです。
サンプルはAmazonのビジネス書のTop10くらいのものを選んでいます。
|ISBN-13|Title
|---|---
|978-4478116692|頭のいい人が話す前に考えていること
|978-4862763181|解像度を上げる
|978-4763140067|1年で億り人になる
|978-4295016380|先読み!IT×ビジネス講座 ChatGPT 対話型AIが生み出す未来
|978-4910063232|異能の掛け算新規事業のサイエンス
|978-4478025819|嫌われる勇気
|978-4163916767|コンサルティング会社完全サバイバルマニュアル
|978-4296200917|キーエンス解剖最強企業のメカニズム
|978-4862760852|イシューからはじめよ
|978-4799329368|思考の質を高める構造を読み解く力

これをGoogle Apps Scriptの知識を応用して書いてみます。

# コード
```typescript:sendRequest.osts
/**
 * main
 */
async function main(workbook: ExcelScript.Workbook,
  sheetName: string = "Sheet1") {
  // Get the worksheet named "Sheet1".
  const sheet = workbook.getWorksheet(sheetName);
  // Get the entire data range.
  const range = sheet.getUsedRange(true);

  // If the used range is empty, end the script.
  if (!range) {
    console.log(`No data on this sheet.`);
    return;
  }

  // get Detail By ISBN values.
  let values = range.getValues();
  
  // range values clearcontents
  range.clear();

  // create Values
  for (let i = 1; i < values.length; i++) {
    let isbnCode = values[i][0];
    isbnCode = isbnCode.toString().replace('-', '');
    
    let json: TableData[] = [];
    
    // http request function
    json = await getRequest(isbnCode);
    
    // set values
    values[i][1] = json["title"];
    values[i][2] = json["imageLinks"]["thumbnail"];
    values[i][3] = json["publishedDate"];
    values[i][4] = json["authors"][0];
    values[i][5] = json["description"];
    console.log(json);
  }

  range.setValues(values);  
}
/**
 * HTTP Request function
 */
async function getRequest(isbn: string) {
    // Retrieve sample JSON data from a test server.
    let fetchResult = await fetch('https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn);

    // Convert the returned data to the expected JSON structure.
    let json: JSONData = await fetchResult.json();
  return json["items"][0]["volumeInfo"];
}

/**
 * An interface that matches the returned JSON structure.
 * The property names match exactly.
 */
interface JSONData {
    kind: string;
    totalItems: number;
}
interface TableData {
  title: string
}
```

このコードでは`interface`の定義がかなり雑です。
スクリプトへの入力とスクリプトからの出力の両方で、
必要な JSON 構造に一致するように`interface`の定義の必要性がリファレンスが
説かれていますが、自分の知識と経験不足で甘い内容になっています。

堅牢な仕組みを作り上げることが`TypeScript`の醍醐味でありますので、
真摯に反省し、精進していこうかと思います。

## このコードの注意点 非同期関数 async、await
`フェッチAPI`は、外部サービスから情報を取得しますが、
**非同期処理であるため`async`、`await`をしっかりと明記**しなければ
思う結果が得られません。

具体的には外部API呼び出しの結果が戻る前に`main`関数が終了してしまい、
値の取得が確約できないということです。

そのため、`async`、`await`を明記する必要があります。

下記のサイトが非常に参考になりましたのでご確認ください。

https://kokoroe.konomi.app/docs/office-scripts/async/

# 実際の結果
今回使ったサンプルデータは下記のとおりです。
もとに入っているデータがISBN-13の部分
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/007e2efb-b2cb-2923-e068-e173a3956bba.png)

***スクリプトを走らせた結果***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8a0c4538-7f7f-05ef-f562-faf4bf7ecf9a.png)

ブラッシュアップの余地がありますが、素案はできました。
API連携を使いことなすことは、業務改善の一つのヒントですので、Office Scriptもしっかりと学んでいきたいと思います。

自分の開発環境にマッチした手法で策を適用できると良いですね！

# 最後に
今回の外部API呼び出しの場合、必然的に`GET`メソッドになっていますが、
それ以外できないのかというと、それはNoです。

下記の方のBlogが大変参考になりますのでおススメさせていただきます。

https://mofumofupower.hatenablog.com/entry/2021/02/18/014249

私も学び、API連携のノウハウを蓄積していきたいです。

読んでくださり、ありがとうございました！