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

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

ただいまの
回答率

87.51%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 140

score 39

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

function myFunction() {
  var spreadsheet = SpreadsheetApp.openByUrl("https://***");
  var sheet = spreadsheet.getSheetByName("***");
  var values = sheet.getDataRange().getValues();
 values = values.reverse();

  var day = values[0][0];
  var field = values[0][1];
  var num = values[0][2];

  var str = [];

  for (var i = 1; i < values.length - 1; i++) { 
    var obj = {};

    obj[day] = values[i][0];
    obj[field] = values[i][1];
    obj[num] = values[i][2];
    if(obj[day] !== ''){
      str += '<li>\
                <div>日付'+obj[day]+' '+obj[field]+' 番号'+obj[num]+'</div>\
            </li>';
    }
  }
return str;
}

上記がソースコードですが日付(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>

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • papinianus

    2021/10/14 18:55

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

    キャンセル

  • 3_April_2021

    2021/10/15 09:22

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

    キャンセル

  • musashidayo

    2021/10/15 11: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名の先輩方には大変感謝しております。ありがとうございました。

    キャンセル

回答 1

checkベストアンサー

+2

- 回答
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 行でできそうです。

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る