【のこるんvol.3】3タップ完了LINEフォトアルバム #LINE #GAS #AppSheet

## スマホ中の写真　埋もれてない？

 前回記事　：[【のこるんvol.2】3タップ完了LINEフォトアルバム](https://qiita.com/okinakamasayoshi/items/69715a210e63625fa3ab)
 前々回記事： [3タップで完了するLINEフォトアルバム](https://qiita.com/okinakamasayoshi/items/1b30f3b8533a61bd2f12) 

 2022年あけましておめでとうございます🎍
 クリスマスからお正月にかけて、写真を撮るイベント盛りだくさんでしたよね。
 年賀状や写真整理など、一年間の写真の振り返りも大変だったんじゃないでしょうか。

 スマホがこの世に誕生し、写真の撮影枚数はそれ以前の1,500倍に、
 1スマホの中に少なくとも1,000枚以上の写真があるそうです。
 ![Group 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/59ecf2f0-486c-36fd-cd51-73cd6706fabb.png)

 せっかく撮影しても、整理できずにいませんか？。
 <font color="Red">**思い出が埋もれたり、写真と一緒に消えてしまうのは悲しい。**</font>
 とはいえ新たにアプリを使うのはめんどくさい。

 そこで・・・

 プログラミングの「プ」の字も知らなかった初心者ですが、
<font color="Red">**日本一簡単操作のLINEフォトアルバムアプリを自分で作ります**</font>💪

 写ルだけじゃなく残ルンです!!　その名も<font color="Red">**「のこるん」**</font>ぜひ覚えて下さい♪


## スプレッドシートからいよいよアプリ化へ挑戦!!
 **【前回まで】**
 まずはLINEで送付された　①写真　と　②コメント　の情報を取得し、
 <font color="Red">**スプレッドシート上にデータ保存できるようになりました!!**</font>

**【今回のトライ】**
 LINEで写真とコメントを送ると、即アルバムが完成する<font color="Red">**webアプリ**</font>を作ってきます!!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/8d9e2e44-af8c-e78d-b648-cb70e92d0a89.png)

今回のステップ「スプレッドシート上にデータをアプリで表現」のLINE操作と全体図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/74df6c51-ba0c-6f04-bec7-5545a08fbd11.png)

## 初心者でもAppSheetでアルバムアプリを作ろう!

 AppSheetについての記事は👇など沢山あります。

 https://www.yoshidumi.co.jp/collaboration-lab/google_appsheet_column02/

 が、意外と<font color="Red">**初心者向けの記事がない。。。**</font>そこで!
 初心者さん向けに<font color="Red">**「0」から解説いたします!!**</font>

 まずは[前回までの記事](https://qiita.com/okinakamasayoshi/items/69715a210e63625fa3ab)を参考に、LINEで送った写真・コメントがスプレッドシートに
 書き込まれている状態にしてください。

 <details><summary>前回の記事から少しコードを書き変えています　　<font color="Red">**(クリックで表示)**</font></summary><div><br><br>

```js

// 応答メッセージURL
const REPLY = "https://api.line.me/v2/bot/message/reply";

// アクセストークン
const ACCESS_TOKEN = "********";

// スプレッドシート情報

const SHEET_ID = '********';
const SHEET = SpreadsheetApp.openById(SHEET_ID).getSheetByName('シート1');

// Google Drive ID
const GOOGLE_DRIVE_ID = "********";

// LINEから送られてきたデータを取得 doPost()
function doPost(e) {

//メッセージ受信
const data = JSON.parse(e.postData.contents).events[0];
//ユーザーID取得
const lineUserId = data.source.userId;
// リプレイトークン取得
const replyToken = data.replyToken;
// 送信されたメッセージの種類を取得
// https://developers.line.biz/ja/docs/messaging-api/message-types/#sticker-messages
const postType = data.message.type;

//沖中追加①
const userMessage = JSON.parse(e.postData.contents).events[0].message.text;
//追加①ここまで

// 写真の時
if ( "image" === postType ) {
imageSave(replyToken, lineUserId, data);

} else {

SHEET.getRange('D' + 2).setValue(userMessage);
}

}

// 送信された画像を保存 imageSave()
function imageSave(replyToken, lineUserId, data) {

// LINEから画像取得 getImg()
const imgData = getImg(data);

// Googleドライブに保存　saveImg()
const imgInfo = saveImg(imgData, lineUserId);

// //「保存完了」とLINEにメッセージを送る
sendMessage(replyToken, imgInfo);

}

// LINEから画像取得　getImg()
function getImg(data) {

const IMG_URL = 'https://api-data.line.me/v2/bot/message/' + data.message.id + '/content';
const HEAD = {
"method":"get",
"headers": {
"Authorization" : "Bearer " + ACCESS_TOKEN
}
}
const imgData = UrlFetchApp.fetch(IMG_URL, HEAD);
return imgData;

}

// Googleドライブに保存　saveImg()
function saveImg(imgBinary, lineUserId){

//GoogleDriveフォルダID
const folder = DriveApp.getFolderById(GOOGLE_DRIVE_ID);
//ランダムな文字列を生成して、画像のファイル名とする
const fileName = Math.random().toString(36).slice(-8);
//Googleドライブのフォルダに画像を生成
const imageFile = folder.createFile(imgBinary.getBlob().setName(fileName));
//「保存しました」としたメッセージを変数に代入
const imgInfo = '画像保存したよ!コメントをどうぞ!';

//画像ファイルURL取得
const imageURL = 'https://drive.google.com/uc?export=view&id=' + imageFile.getId();

//画像ファイルにリンクでアクセスの権限付与
imageFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);

debugImgLog(imageURL, lineUserId);
return imgInfo;

}

// スプレッドシートに画像を保存 debugImgLog()
function debugImgLog(text, userId) {

if ('' == text) {
return;
}

const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss')
const userName = getUserDisplayName(userId)
const userImg = getUserDisplayImg(userId)

SHEET.appendRow([userId,userId,text,userName,date,userName]);
// 日付順に並び替え
const numColumn = SHEET.getLastColumn(); // 最後列の列番号を取得
const numRow = SHEET.getLastRow()-1; // 最後行の行番号を取得
const dataRange = SHEET.getRange(2, 1, numRow, numColumn);
dataRange.sort([{column: 5, ascending: false}]);

}

// ユーザーのプロフィール名取得 getUserDisplayName()
function getUserDisplayName(userId) {

const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).displayName;

}

// ユーザーのプロフィール画像取得 getUserDisplayImg()
function getUserDisplayImg(userId) {

const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).pictureUrl;

}

// LINEにメッセージ送信 sendMessage()
function sendMessage(replyToken, replyText) {

const postData = {
"replyToken" : replyToken,
"messages" : [
{
"type" : "text",
"text" : replyText
}
]
};

const headers = {
"Content-Type" : "application/json; charset=UTF-8",
"Authorization" : "Bearer " + ACCESS_TOKEN
};

const options = {
"method" : "POST",
"headers" : headers,
"payload" : JSON.stringify(postData)
};

return UrlFetchApp.fetch(REPLY, options);

}

```
</div></details>

 LINEで写真・コメントを送ると、スプレッドシートに👇のようにデータが溜まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/2d71db73-6668-3ff2-0227-666f93f85b73.png)
 細かい話ですが、写真を送るとD列には一旦「投稿者名」が入っています。
 コメントを送ると、「D列がコメントに置き換わる」という仕様にしています

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/debcddfe-e197-1ae6-e545-b85d1c34aad5.png)
 拡張機能→AppSheet→アプリを作成

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/b0b106fe-ca9e-7406-52e4-52089dfc3673.png)
 Data→スプレッドシートの中のどのシートをアプリで表現したいかを選びます　今回は「シート1」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/b6a62c5e-86e9-1f84-c466-82b8cb563dce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/21dd18ad-5274-56f9-c5b1-22b64d1ea826.png)
 一旦同じようにチェックを入れてみてください！<font color="Red">**URLのTYPEをImageに変更するのを忘れずに!**</font>
 ここまで来たら「SAVE」で更新してください!

## アプリ上での見せ方を整えよう

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/ffd57306-2982-f6ed-3f39-432ab140a65e.png)
 UX→今回は「シート1」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/5d9db41f-fc6e-6af5-65dc-43650be81fd6.png)
 ギャラリー→タイムスタンプ「Decending」→SAVEを押すと・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/d6e215f0-1f41-435b-32e2-13211a3bdb4a.png)
 <font color="Red">**じゃ～ん！もうなんとなく完成しました!!**</font>

## 次回は「のこるん」もっと見やすくするよ!

 ということで次回は、AppSheetを使って、更に見やすいアプリに仕上げていきます。
  <font color="Red">**数か月前までプログラミングの「プ」も知らなかったのに、スマホアプリを作るなんて・・・**</font>
 この先の挑戦もまた記事にします(*^^)vお楽しみに!!

  最後に宣伝させてください。
 私には<font color="Red">**『思い出を消さない未来を作りたい』という夢**</font>があります。

 **「のこるん」は夢の実現のための第一歩**です。
 どこまで実現できるか分かりませんが、<font color="Red">**1月中旬にはクラウドファンディングにも挑戦します!**</font>
 **「のこるん」誕生に向け、[よければ応援してください!!](https://camp-fire.jp/projects/528736/preview?token=2oax6gt3)**(*´ω｀*)　ではまた次回の記事で!!

 https://note.com/m_okinaka/n/n30c09e837ae0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/0f51a5a5-a0a6-6634-472e-055daa9261e5.png)
![Group 19 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/f1cf747c-e37a-504c-ec88-8321733dc51e.png)

https://camp-fire.jp/projects/528736/preview?token=2oax6gt3