質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2150閲覧

GASで行を下から取得(配列に入れる)について

musashidayo

総合スコア62

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/10/14 03:05

編集2021/10/14 06:59

スプレッドシートから自動でhtml要素を出力するプログラムを組んでいるのですが、上から順に出力することはでき、下から順に出力したい場面が出てきたのでreverse()関数で配列を逆順にすればできるかな?と思いやってみたところ予期しないものが出力されてしまったためこの方法ではできないのでしょうか。
イメージ説明

javascript

1function myFunction() { 2 var spreadsheet = SpreadsheetApp.openByUrl("https://***"); 3 var sheet = spreadsheet.getSheetByName("***"); 4 var values = sheet.getDataRange().getValues(); 5 values = values.reverse(); 6 7 var day = values[0][0]; 8 var field = values[0][1]; 9 var num = values[0][2]; 10 11 var str = []; 12 13 for (var i = 1; i < values.length - 1; i++) { 14 var obj = {}; 15 16 obj[day] = values[i][0]; 17 obj[field] = values[i][1]; 18 obj[num] = values[i][2]; 19 if(obj[day] !== ''){ 20 str += '<li>\ 21 <div>日付'+obj[day]+' '+obj[field]+' 番号'+obj[num]+'</div>\ 22 </li>'; 23 } 24 } 25return str; 26}

上記がソースコードですが日付(Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時))が消えてしまい原因がわかりませんでした

↓reverse()前の結果

<li> <div>日付Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時) 三国 番号11</div> </li> <li> <div>日付Sat Oct 09 2021 00:00:00 GMT+0900 (日本標準時) 津 番号5</div> </li>

↓reverse()後の結果

<li> <div>日付津 津 番号5</div> </li> <li> <div>日付三国 三国 番号11</div> </li>

この逆順にすると日付が消えてしまう原因がわかる方がおりましたらご教授いただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

3_April_2021

2021/10/14 03:53

現在の状態を明確に共有するために、失敗した出力処理のコードを提示してもらえませんか。
3_April_2021

2021/10/14 03:54

また、以下の情報は二度手間の防止になるでしょう。 - データ取得元のスプレッドシートの状態(意図がわからない場合は画像) - 出力場所に関する情報(意図がわからない場合はスプレッドシートかどうかYESNOで答えます)
musashidayo

2021/10/14 04:13

説明が足りず申し訳ございません。 出力するとラベルまで表示されてしまい、逆順にはできているようなのですがこれを排除するのができていないようです。また、日付が空白になってしまいます。 逆順前 <li> <div>日付Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時) 三国 番号11</div> </li> <li> <div>日付Sat Oct 09 2021 00:00:00 GMT+0900 (日本標準時) 津 番号5</div> </li> ↓reverse()後 <li> <div>日付津 津 番号5</div> </li> <li> <div>日付三国 三国 番号11</div> </li> <li> <div>日付会場 会場 番号番号</div> </li>
3_April_2021

2021/10/14 04:33

<li> <div>日付Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時) 三国 番号11</div> </li> の実際の理想イメージは <li> <div>Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時) 三国 11</div> </li> なのですか?
musashidayo

2021/10/14 04:59

はい。デバッグの際にわかりやすくラベルを付けていたため出力する際に"日付"というものは消すのでご指摘の形で下から順に表示するのが理想となります。
3_April_2021

2021/10/14 06:51 編集

誤解を招く可能性があるため、編集されました。
musashidayo

2021/10/14 05:34

ラベルの件に関してはおっしゃる通り str += '<li>\ <div>'+obj[day]+' '+obj[field]+obj[num]+'</div>\ </li>'; 上記の形にすればいいのは認識しているのですが、 values = values.reverse(); 配列を逆順にする際に上記を記述してから出力したあとに日付部分が表示されない原因がわからず苦戦している次第です。
3_April_2021

2021/10/14 06:52 編集

誤解を招く可能性があるため、編集されました。
3_April_2021

2021/10/14 05:43

と推測しているのですが、引っ繰り返す前だと表示されるのですか?
musashidayo

2021/10/14 05:44

そうなんです。reverse()掛ける前だと表示されるのでなぜだかわかっていない状態です。
3_April_2021

2021/10/14 09:21 編集

誤解を招く可能性があるため、編集されました。
musashidayo

2021/10/14 06:15

行為の意味といいますと、上から下に向かって日付が新しくなるように行が並んでいるものを出力する際にreverse()で逆順に(最新の方から降順になるように)したいということなのですが、ご指摘の部分はこちらに対するものでしょうか。
3_April_2021

2021/10/14 09:21 編集

誤解を招く可能性があるため、編集されました。
musashidayo

2021/10/14 06:26

はい。strに関しては出力用のhtmlのulタグの中に作成した<li>---</li><li>---</li>.....という形でhtml要素としてまとめたいのでこのような形としています。 その中で逆順にすると日付が消えてしまうのでなぜなのかと思いご教授をお願いしたくお聞きした次第でございます。
3_April_2021

2021/10/14 06:50

疑問は解消されませんでした。 出力先の形式や処理を明確に想像できないことと重なって、私には希望処理のイメージが原因特定が困難です。申し訳ありませんが、他のユーザを待ってください。 出力結果に期待される結果と実際の処理、および日付が消えるという現象は、質問に追加した方が良い情報だと思います。
musashidayo

2021/10/14 07:01

お付き合いいただきまして大変ありがたく思います。 アドバイスを元に追記致しました。
3_April_2021

2021/10/14 07:16

一部のコメントは見当が外れている可能性が高くなったので、不要な問題発生を回避するために編集されました。 もともと最善の解決策や確実な正解として与えられたものではなかったので、覚えていても一旦忘れてください。しかし型の件にしても、この情報に頑なに触れないのは、そう判断できる理由があるのか全くわからないからなのか読み取れませんでした。
3_April_2021

2021/10/14 08:30

編集された質問を読み直しましたところ、よくわからなかった原因に「values = values.reverse()」の読み飛ばしがあったことが判明しました。 return先の仕様ややりたいことがよく読み取れないので、return先で発生している問題協力なら難しいのですが、return内で発生しているのであれば、時間があれば小さな協力はできると思いますから、よろしければその点だけ教えていただけますか?
papinianus

2021/10/14 09:30

編集されすぎて何をどう理解できないのか理解できないですが return の直前で console.log(str) とすれば質問者さまが何に困っているか、これがどういう質問かわかると思います。
musashidayo

2021/10/14 09:30

ありがとうございます。 上記js内には function doGet() { return HtmlService.createTemplateFromFile("html").evaluate(); } として出力先を選択し、 return先はGAS内にhtml.htmlを作成し、 <!DOCTYPE html> <html> <head> <base target="_top"> </head> <body><ul><?= myFunction(); ?></ul></body> </html> としています。
papinianus

2021/10/14 09:55

return 先は関係ないです。実装とデータの話。 たとえばこの関数をセル関数に書き換えたとしてもこの問題は本質的には起こり得ます。
3_April_2021

2021/10/15 00:22

「return内」というのは変な表現でした、申し訳ないです。 しかしその結果入手した情報から不明瞭に感じていた部分の確証が取れましたので、限定的な協力ではなく、問題なく総合的協力(原因特定や代替案)できそうです。 踏まえて準備しますが、作業内容上次のアクションには一定時間がかかると思いますので、この報告のみ取り急ぎ。 (幸い回答もつき始めたようですし、解決できれば解決でお気になさらず)
musashidayo

2021/10/15 02:01

処理について詳しく説明いただき大変納得がいきました。 for (var i = 1; i < values.length - 1; i++) { //var obj = []; //空のオブジェクト(初期化) var o_day = values[i][0]; var o_field = values[i][1]; var o_num = values[i][2]; .... } 当方でも回答いただける間に試行錯誤して上記のように配列ではなくそれぞれを変数にして同様の処理を行ってみると意図した表示になっていたのでそこも含めて全ての疑問が解決できました。 2名の先輩方には大変感謝しております。ありがとうございました。
guest

回答1

0

ベストアンサー

- 回答
B4,C4 のいずれか片方が空(未入力)で、もう片方が全角空白のような表示されない文字がある
A4 と B4 は同じデータを持つ

  • 説明

事象としては「日付」が消える、ではなく「会場が二重に表示される」が正しい。

for (var i = 1; i < values.length - 1; i++) { のループを 3 行しかないデータに対して適用すると、ループは 1 回しか実行されないので、

↓reverse()前の結果

<li> <div>日付Fri Oct 01 2021 00:00:00 GMT+0900 (日本標準時) 三国 番号11</div> </li> <li> <div>日付Sat Oct 09 2021 00:00:00 GMT+0900 (日本標準時) 津 番号5</div> </li>

このように 2 行分のデータがでることは考えられない。
したがって getDataRange が 4 行分のデータを返していると考えられる。

4 行目にデータがあるとして、A,B,C になんのデータもなく D 列より右に何かデータがあったとした場合、obj の 3 つのキー(day,field,num)はいずれも "" になってしまい↓のように会場と番号という 2 種類のデータを保持できない。
したがって、B4 または C4 はそれぞれ違うデータを保持していると推測される。
しかし、キャプチャにはそのような文字は見えないので、スペースのような見えない文字(白色の文字でも良い)が入力されているのではないかと考えられる。

仮に A4 および B4 が "" で C4 が " " であると仮定する。
このとき day も field も同じデータなのでキーとしても同じとなり obj[day] と obj[field] は同じデータを指すことになる。このため、より後にセットされる values[i][1] が obj[day] にも表示される。

  • 場当たり的な修正方法
 values = values.reverse(); var day = values[0][0]; var field = values[0][1]; var num = values[0][2];

var day = values[0][0]; var field = values[0][1]; var num = values[0][2];  values = values.reverse();

とする。

ただ、そもそもループが 1 からはじまっているので、現在のデータでは動くが 4 行目をちゃんと削除した場合に 1 行しか出力できなくなるので、全体に見直したほうがよさそうです。
getDataRange は人間が思ってもない範囲を使っている範囲と思うのでご注意ください。

こんな感じですかね。いまのところわざわざ object 作らなくても良さそうなので 1 行でできそうです。

javascript

1const q364329 = () => { 2 const spreadsheet = SpreadsheetApp.getActive("https://***"); 3 const sheet = SpreadsheetApp.getActiveSheet(); 4 const values = sheet.getDataRange().getValues(); 5 const [day, field, num] = values[0]; 6 const data = values.slice(1).filter(e=> e[0] !== "").map(e=> ({[day]:e[0],[field]:e[1],[num]:e[2]})).reverse(); 7 return `<li>${data.reduce((a,c)=> `${a} <div>日付${c[day]} ${c[field]} 番号${c[num]}</div></li>`,"")}</li>`; 8} 9const q364329_2 = () => `<li>${SpreadsheetApp.getActiveSheet().getDataRange().getValues().slice(1).filter(e=> e[0] !== "").reverse().reduce((a,c)=> `${a} <div>日付${c[0]} ${c[1]} 番号${c[2]}</div></li>`,"")}</li>`;

投稿2021/10/14 09:27

編集2021/10/14 09:53
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問