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

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

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

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

Q&A

解決済

1回答

5542閲覧

GASを利用して、ある条件に合致した範囲の移動を行いたい

Tom001

総合スコア11

Google Apps Script

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

0グッド

0クリップ

投稿2019/05/13 08:21

編集2019/05/13 08:43

前提・実現したいこと

GoogleSpreadSheetで、条件に一致した範囲(1行内の範囲)が、特定の行へ移動するような関数をつくりたいです。
イメージ説明

発生している問題

行や列全体の移動が出来ることは分かったのですが(sheet.moveRows())、
範囲の移動でいい方法が見つからず困っています。

例えば、(上記画像のような)ある範囲をコピー&ペースト&元のデータを削除であれば出来るのですが、
もちろんこのままだと、次に同じ操作が行われたときに、上書きされてしまいます。

ある範囲内(上の画像で言えば、B19:H44)での未入力部分の最終行(or最初行)の判定が出来れば可能なものだとは思うのですが、
その方法も見つけられず...。

なので、

sheet.moveRows()のように、範囲が移動する際、もとの値が上に押し上げられるような動きをするMethod
②ある範囲内での未入力部分の最終行(or最初行)の判定

のどちらかの方法か、その他良い別の方法があれば、お教えいただけますと幸いです。

該当のソースコード

GoogleAppsScript

function moveRow(){ var sheet = SpreadsheetApp.getActiveSheet(); for(var i = 4; i <= 18; i++){ var range = sheet.getRange("B"+i + ":" + "H"+i); //4-18行の各行を取得 var values = range.getValues(); //4-18行の各値を取得 if(sheet.getRange("B"+i).getValue() == "A"){ //B列が"A"の場合 var moveTo = sheet.getRange("B19:H19"); //コピー先範囲 moveTo.setValues(values); //コピー先範囲へ値をセット range.clearContent(); //元の値を削除 } } }

どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

sheet.moveRows()のように、範囲が移動する際、もとの値が上に押し上げられるような動きをするMethod

A. おそらくない。
理由:moveRowsのRangeバージョンはmoveToだが、質問者様期待の動作をしない。説明文ではカット&ペーストと書いている。質問者様期待の動作をするには、セルを削除したときの、どちらにつめるか(左右や上下のどちらから詰めるか)を指定するオプションがないため、下から上に持ちあげる動作をすることができない(deleteCellsという操作では方向を指定できる)

ある範囲内での最終行(or最初行)の判定

A. 通常(Sheet.)getLastRowなどを使うが、提示された例では期待の動作を得られない。
そもそも、18行目以前に複数行の空白があり、なにをもって19行目を移す先と思うかが人間的判断
なので

javascript

1var target = 19; 2for(var i = 19; i < 45; i++) { 3 if(sheet.getRange(i, 4).getValue() !== "") continue; 4 target = i; 5 break; 6}

のように自分で1セルずつ判定するほかない

余談
APIアクセスを減らすにしても、↓こういう方法しか思いつかなかった。

javascript

1 var dat = sheet.getRange(19,1, 25,1).getValues().reverse(); 2 var target = 44; 3 foreach(var i = 0; i < dat.length; i++) { 4 if(dat[i] == "") { target--; continue; } 5 break; 6 }

一般にこのように整形される帳票形式のデータと、保存する生データは別に管理し、生データに表示上の都合がからまない設計にしたほうがマクロは作りやすい

投稿2019/05/13 08:54

papinianus

総合スコア12705

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

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

papinianus

2019/05/13 09:16

質問者様の状況にあわない不適当な回答をしていました。お詫びします。 おそらく、insertCellsをしてコピー先を安全にRangeを確保して、確保したRangeにmoveToで貼り付け、移動元のRangeを削除。するのが適当だと思います。 ただこれをやるとき、45,46行目の結合セルが結合解除されたりスタイルが崩れたりする危険があるので、範囲の縦方向は適切に結合セルの切れ目と合致する必要があると思います。
Tom001

2019/05/14 05:26

迅速なご回答ありがとうございます!大変助かります! また、お詫びなど、とんでもございません...。 ご提案いただいたように、insertCellsで上書きを防ぎつつ、もとを削除という方法で再設定してみます! また、空白のセルを判定していくという方法も思いつかなかったため、 重たくならないよう気を付けながら、そちらも試してみようと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問