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

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

ただいまの
回答率

88.83%

GAS 指定した行を最終行に並べ替えしたい。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,155
退会済みユーザー

退会済みユーザー

関数が少しわかる程度の初心者です。
どうか条件付の並べ替えについて教えてください。

前提・実現したいこと

スプレッドシートで案件の管理をしており、A列からBE列まで情報を記載してます。
案件によっては納期が変更になる事もあるのでその都度、メニューから並べ替えを選んで納期順にしています。
また、一時的に案件がストップしたものはA~Bセルをピンク色に塗りつぶし、最終行に手作業で並べ替えをしています。
私がやりたい事は、ボタンを押すと勝手に納期順に並べ替えをし、かつピンク色に塗りつぶした行は納期の日にち関係なく
最終行にもっていくという事を実現したいです。

【 例 】
A列:月
B列:納期
C列:案件名
D列:お客様名…等

試した事、分からない事

自分で考えた結果
1 まずはピンク色の色コードを取得

function getBackColor(){
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var sheet=ss.getSheets()[0];
  var cell=sheet.getRange('A67')
  cell.setBackground('A67')

  Browser.msgBox("A67のカラーコードは「"+cell.getBackground()+"」");
}


2 1で取得したコードは「#ffccff」だったので
「#ffccff」だったら最終行に並べ替え
「#ffccff」以外だったらB列の納期別に並べ替え
という指示を書きたかったのですが、それをどのように書いていいのか分かりません。

function sort(){
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var s=ss.getActiveSheet()[0];
  var lastRow=ss.getLastRow();
  var lastCol=ss.getLastColumn();
  const color='#ffccff';
  switch(color){
     case '#ffccff:
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • macaron_xxx

    2019/04/23 09:04

    無理やり書けばGASで実行できなくはないのですが、背景色は1行ごとにAPIを叩いて見に行かないといけないです。
    方向としては、仮行に色の情報を持たせて、ソートすることになるのですが、
    例えばBF列に「STOP」と書けば条件付き書式でA,B列が色付きになる。という運用に変えると、ソートもより楽になるのですが、それはお望みではないですか?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2019/04/24 12:57

    コメントありがとうございます。
    「STOP」と書けば条件付書式でA,B列が色付きになるという運用でも問題ございません。
    今は手作業で中断した案件の行(A列、B列)を塗りつぶしをしていたのを条件付書式に運用を変えるだけでソートが楽になるというのが初心者には見当もつかないのでお恥ずかしいですが・・・
    そこからは、hiroshi0240さんがおっしゃっている事を使えば出来るという事なんでしょうか。

    キャンセル

  • hiroshi0240

    2019/04/24 13:09

    「STOP」などデータ上で情報を読み取れる列があれば、データ全体をシンプルに並び替え(「STOP」が書いてある列が第一優先、納期が第2優先でソート)するだけで実現できますよ。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2019/04/24 13:18

    コメントありがとうございます。
    冷静に考えればそうですよね・・・。
    「色のついたものをソート」だけが自分の頭の中にあって、macaron_xxxさんがおっしゃった事を
    ちゃんと理解できませんでした・・・。
    細かな所までわざわざ教えて頂きありがとうございます!

    キャンセル

回答 2

checkベストアンサー

+2

パターンA:そのまま実装すると

function sort() {
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.getDataRange().sort([{column:2, ascending:true}]);
  const lastRow = sheet.getLastRow();
  const pink = "#ffccff";
  const rows = sheet.getRange(1,1,lastRow,1).getBackgrounds().map(function(e,i){ return {R:i+1, Col:e[0]}}).filter(function(e){ return e.Col == pink;}).map(function(e){return e.R}).reverse();
  const pinks = rows.length;
  rows.forEach(function(r) { sheet.moveRows(sheet.getRange(r, 1, 1, 5), lastRow+1);});
  sheet.getRange(lastRow - pinks + 1, pinks, 5).sort([{column:2, ascending:true}]);
}


ピンクのを後ろに下げたときに、その中でもソートがかかっていることにするのが厄介でした。ミュータブルなinsertPosをデクリメントしながらやれば、再ソートは不要でしたね。もう検証したくないので書き直しませんが。
必ずA列が着色されているとき、色をまとめてとることはできるので、ボトルネックになるのは、着色行を一つずつ移動させる部分です。着色行が十分に少なければ、実用できると思います。

パターンB:ソート可能なデータを付与できるとすると

推奨されているソート可能なデータを付与する例ですが、個人的にはチェックボックスをおすすめします。ワンクリックだし誤入力(全角半角)もない。

見た目はこう
運用イメージ

コードはこう

function onEdit(e) {
    const sheet = e.range.getSheet();
    if(sheet.getName() !== "そのシートの名前") return;
    const c = e.range.getColumn();
    if(c !== 1) { return; }
    const r = e.range.getRow();
    const value = e.value;
    switch(value) {
        case "TRUE" :
            sheet.getRange(r, 2, 1, 2).setBackground("#ffccff");
            break;
        case "FALSE" :
        default :
            sheet.getRange(r, 2, 1, 2).setBackground(null);
            break;
    }
}
function sortByCheck() {
    const sheet = SpreadsheetApp.getActiveSheet();
    sheet.getDataRange().sort([{column:1, ascending:true}, {column:3, ascending:true}]);
}


こちらは、他人がチェックをつけたときに、コードで色がつくのかなーという疑問がありますが、個人的にG Suiteを持たなくなったので分かりません。
(もし運用上可能なら、色のことは忘れて、チェックがあることを延期と思えばいいような)
→条件付き書式なんですね。それは思いつかなかった。条件付き書式だとしたら、onEditは不要です)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/30 03:32

    チェックボックスなら、空白セルをFalseで扱う事が出来るので、私も賛成です。という事で+1

    キャンセル

  • 2019/05/07 10:27

    皆様、初心者の私に色々教えて頂きありがとうございます。
    チェックボックスであればpapinianusさんのおっしゃる通り誤入力等がなくなるので
    良い案だと思います!
    またご丁寧にコードまで教えて頂きありがとうございます!

    キャンセル

0

私もmacaron_xxxさんのご意見に賛成(というか自分ならそうします)が、とりあえず、実現させたいであろうことに必要な情報を。
まずは、データ範囲全体の並び替えを行ったあとの処理と想定し、全行に対して背景色を見に行く必要があるので、for文などの繰り返し処理を書きます。
その中で、1行ごとに、ifやswitchのような条件分岐で、「#ffccff」だったら最終行に移動、それ以外は何もしない。と記載すればよいかと。
行の移動は moveRowsを使えばできます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/24 16:46

    アドバイス頂きましたが、もう少し教えてください。
    hiroshi0240さんがおっしゃった下記の発言ですが、

    『「STOP」などデータ上で情報を読み取れる列があれば、データ全体をシンプルに並び替え(「STOP」が書いてある列が第一優先、納期が第2優先でソート)するだけで実現できますよ。』

    私はこれを「STOP」をキーにsortで並べ替えをして最後尾に持っていくと解釈しましたが
    あっておりますでしょうか?
    あっているなら、この「STOP」をキーに並べ替えるコードの書き方が分かりません。
    sort ( { column : 55 , ascending : true }); で書いても
    「STOP」と書いたものが一番上に並べ替えられてしまいます。
    ※trueをfalseに変えても結果は同じでした。

    この「STOP」という文字列をキーに並べ替える書き方があれば教えてください。
    ※ネットで探しましたが、見つける事が出来ませんでした。

    キャンセル

  • 2019/04/25 11:20 編集

    sortって空白セルは対応できないんですね。stop以外の空白セルにダミーでスペースを入力するか、配列データ(getValuesした値)として以下の様にソートすればできるかと思います。
    対象配列=data
    data.sort(function(a,b){
    var A =a[1];//stopが入力されている列数-1(2列目なら1)
    var B =b[1];//stopが入力されている列数-1(2列目なら1)
    if(A != "stop" && B == "stop") return -1;
    if(A == "stop" && B != "stop") return 1;
    return 0;
     });

    キャンセル

  • 2019/04/29 23:50 編集

    配列をソートするというのは、data = getRange().getValues()して、getRange().setValues(data)するという意味ですよね?そうなると、色は追従しないように思いますがいかがでしょうか?
    →条件付き書式にするのでしたね。すみません。見落としてました。

    キャンセル

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

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

関連した質問

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