GoogleAppsScript屋さん

GoogleAppsScript のサンプルコードなどを載せていきます

指定した行や列を移動させる

はじめに

GoogleAppsScript に新しく追加された以下メソッドの検証です(2017.10.10 リリース)。

指定した行や列を移動させるだけなので簡単そうだと思ったものの、意外と使い方に癖がありました。読むだけで理解できるように書いたつもりなので是非ご一読ください。

Sheet.moveColumns(columnSpec, destinationIndex)

https://developers.google.com/apps-script/reference/spreadsheet/sheet#moveColumns(Range,Integer)

Sheet.moveRows(rowSpec, destinationIndex)

https://developers.google.com/apps-script/reference/spreadsheet/sheet#moveRows(Range,Integer)

Sheet.moveColumns(columnSpec, destinationIndex)

サンプルコード

まずは公式のサンプルコードをそのまま動かしてみます。

function myFunction() {
  // The code below moves rows A-B to destination index 5.
  // This results in those columns becoming columns C-D.
  var sheet = SpreadsheetApp.getActiveSheet();
  // Selects column A and column B to be moved.
  var columnSpec = sheet.getRange("A1:B1");
  sheet.moveColumns(columnSpec, 5);
}

実行前

f:id:rokuni62:20171026191253p:plain

実行後

f:id:rokuni62:20171026191141p:plain

結果検証

A,B 列が C,D 列に移動し、もとあった C,D 列が A,B 列にずれ込む結果となりました。

メソッドに渡している Range オブジェクトは Sheet.getRange("A1:B1") でしたが、渡した Range オブジェクトではなく Range オブジェクトが属する列ごと移動する という点には注意が必要かもしれませんね。

パラメータ検証

では、応用するためには理解が必要ということで、公式ドキュメントからパラメータの意味を読み解いてみます。

※自分なりに日本語訳しています

Name Type Description
columnSpec Range 列移動させる範囲の Range オブジェクト。
destinationIndex Integer 列を移動させる先のインデックス。このインデックスは、列が移動される前の座標に基づいています。列を移動するために削除されている間、スペースに既存のデータも移動します。したがって、データは当初指定されたインデックスとは異なるインデックスで終了する可能性があります。

まず columnSpec は「移動させたい列を含んだ Range オブジェクト」を渡すということで、これは分かりやすいですね。ちなみに Spec は specific(特定)の略だと思うので、「指定した列」という意味合いではないでしょうか。

次に destinationIndex は「列の移動先を指定するインデックス」という意味だと思いますが、先ほどのサンプルコードでは 5 を渡すと A,B 列が C,D 列に移動しました。この関連性はパッと分かりにくと思うので、他にも数字を当てはめて検証していきます。なお destination には 目的地、行き先、到着地、といった意味があるようです。

destinationIndex を変えてみる

先ほどのサンプルコードのうち destinationIndex を 5 ⇒ 7 に変更してみます。

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var columnSpec = sheet.getRange("A1:B1");
  sheet.moveColumns(columnSpec, 7);
}

実行前

f:id:rokuni62:20171026191253p:plain

実行後

f:id:rokuni62:20171026194746p:plain

結果検証

destinationIndex の値を 2 増やしたら A,B列 ⇒ C,D列だったのが A,B列 ⇒ E,F列になりました。2 つ右にズレたので納得の結果です。法則性をハッキリさせるため、今度は columnSpec を変えてみます。

columnSpec を変えてみる

サンプルコードの columnSpec を "A1:B1" ⇒ "A1" に変更してみます(destinationIndex は 5 に戻します)。

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var columnSpec = sheet.getRange("A1");
  sheet.moveColumns(columnSpec, 5);
}

実行前

f:id:rokuni62:20171026195541p:plain

実行後

f:id:rokuni62:20171026195549p:plain

結果検証

destinationIndex が 5 のままでも columnSpecA1:B1A1 と変更したら移動先が A列 ⇒ C列(2列移動)だったのが A列 ⇒ D列(3列移動)になりました。これで destinationIndex だけ移動先が決定するわけではなく、columnSpec の範囲も影響することが分かりました。

これまでの検証結果より、列が移動する時の法則性は以下のようになっているのではないでしょうか。

「destinationIndex - 移動させる範囲の列数」の列位置に移動する

  • 最初のサンプルコード 5 - 2 = 3 … 3列目に移動(A,B列 ⇒ C,D列)
  • destinationIndex を 7 に変更した場合 7 - 2 = 5 … 5列目に移動(A,B列 ⇒ E,F列)
  • columnSpec を "A1" に変更した場合 5 - 1 = 4 … 4列目に移動(A列 ⇒ D列)

この仕様は destinationIndex パラメータの説明でも「列が移動される前の座標に基づいています」と触れられているように、移動する際に出来るスペースが自動で詰められることが影響しているのでしょう。

例えば最初のサンプルコードでは columnSpec が "A1:B1" で destinationIndex が 5 です。5列目 = E,F 列に移動ということになりますが、もといた A,B 列が削除されてしまうため、C 列が A 列まで移動し、それに伴い、移動したばかりの E,F 列までもが C,D 列に移動してしまう、という動きになっています。

左方向に動かしてみる

さて、今までの検証はすべて右方向への移動でしたので、左方向にも動かしてみたいと思います。 columnSpec は "C1:D1" とし destinationIndex は 1 とします。

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var columnSpec = sheet.getRange("C1:D1");
  sheet.moveColumns(columnSpec, 1);
}

実行前

f:id:rokuni62:20171026203317p:plain

実行後

f:id:rokuni62:20171026203323p:plain

結果検証

C,D 列が A,B 列に移動していますね。

なお、左方向に動かす場合は先ほどの法則は適用されず、単純に destinationIndex の位置に移動しています。なぜかと考えると、左方向に動いた場合、自身が空けたスペースが詰められるのに影響を受けますが、右方向に動いた場合は影響を受けないからではないでしょうか。

f:id:rokuni62:20171026204659p:plain

※移動先に割り込む場合は右側にズレるのが前提

仕様まとめ

以上の検証結果より Sheet.moveColumns(columnSpec, destinationIndex) の仕様をまとめです。

移動方向 移動先
destinationIndex で指定した列位置
「destinationIndex - columnSpec の列数」の列位置

最終的な移動位置は destinationIndex だけでなく columnSpec で指定した Range オブジェクトの列数も関係する、というのは非常に重要な仕様ですね。

補足

なお、destinationIndex に以下のような値を設定すると実行時エラーになります。

設定値 エラーメッセージ
0 これらの列は範囲外にあります。
マイナス値 これらの列は範囲外にあります。
移動対象の範囲内 移動先のインデックスを移動対象の範囲に含めることはできません。

columnSpec に "A1:B2" を指定した場合、destinationIndex に 1~3 は実行時エラーとなる

Sheet.moveRows(rowSpec, destinationIndex)

さて、引き続き moveRows の検証ですが、moveColumns が列移動だったのに対しmoveRows は行移動である、という違いがあるだけで、基本的には同じような仕様ではないでしょうか。

サンプルコード

とりあえず公式のサンプルコードを動かしてみます。

function myFunction() {
 // The code below moves rows 1-2 to destination index 5.
 // This results in those rows becoming rows 3-4.
 var sheet = SpreadsheetApp.getActiveSheet();
 // Selects row 1 and row 2 to be moved.
 var rowSpec = sheet.getRange("A1:A2");
 sheet.moveRows(rowSpec, 5);
}

実行前

f:id:rokuni62:20171026232205p:plain

実行後

f:id:rokuni62:20171026232211p:plain

結果検証

1,2 行目が 3,4 行目に移動していますね。 先ほど moveColumns で得た法則がそのまま適用できそうです。

「destinationIndex - 移動させる範囲の行数」の行位置に移動する

行の下移動が検証できたので、次は行の上移動を検証してみます。

上方向に動かしてみる

rowSpec の指定を "A3:A4"(3,4行目)、detinationIndex の指定を1(行目)とします。

function myFunction() {
 var sheet = SpreadsheetApp.getActiveSheet();
 var rowSpec = sheet.getRange("A3:A4");
 sheet.moveRows(rowSpec, 1);
}

実行前

f:id:rokuni62:20171026232727p:plain

実行後

f:id:rokuni62:20171026232734p:plain

結果検証

3,4 行目が 1,2 行目に移動していますね。 やはり moveColumn と同じ仕様と考えてよいでしょう。

移動方向 移動先
destinationIndex で指定した行位置
「destinationIndex - columnSpec の行数」の行位置

さいごに

以上で moveColulmnmoveRow の検証は終了です。

簡単そうに見えても実際に検証してみると意外とややこしく、試してみるのは大切だな…と感じました。

と、検証したのは良いものの、これらのメソッドがどういう場面で効果的に使えるのかが思いつきません…。また思いついたら書いてみたいと思います。