実現したいこと
特定の値がある列を含む行を削除したいのですが、
不要な箇所が削除されたり1行しか削除されない等うまくいきません。
プログラミング初心者で初めてGASを触ります。
ご助力をお願いします。
前提
ヘッダーが5行あります。
例としてB~C列に「1」がある行を削除したいです。
列1 | 列2 | 列3 |
---|---|---|
りんご | 0 | 1 |
みかん | 1 | 0 |
なし | 0 | 0 |
とまと | 0 | 1 |
該当のソースコード
function myFunction() {
let ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
let lastRow = ss.getLastRow();
let range = ss.getRange(6,2,lastRow-5,2).getValues().flat();
console.log(range);
for(let i = range.length -1; i >= 0; i--){
console.log(range[i]);
if(range[i] === 1){
console.log("ifに入ったよ");
ss.deleteRow(i + 1);
Logger.log(i);
}
}
}
試したこと
上記を実行したところ、
7行目が削除され、ヘッダーである4行目5行目も削除されました。
ヘッダーは削除されず、「1」がある行のみ削除したいです。
いろいろ調べて参考にしたのですが、おそらくif文が正しくないのだと思いますがどう修正したらいいかわかりません。
また、プログラミング初心者なのでfor文の「range.length -1」や「ss.deleteRow(i + 1)」の-1、+1が理解できていませんので、
こちらについても説明願いたいです。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
解説は最初の回答にコメントで付記しましたので、
追加の回答です。
初心者の方の質問でよくあるのが、例では列は2つだけでしたが、実際には多くの列があって、
B列とC列だけを比較するのではなく、データの全列を比較したいというものです。
念のためそういう場合のスクリプトを for(;;)文を使った形でお示しします。
なお、今回の例のように2列の比較でもそれ以上の列でも1列でも
同じように値が1の列があれば、その行を削除します。
GAS
1//ヘッダー行より下の行のうちヘッダー列より右の列が1の行を削除 2function deleteSpecifiedColumnRow() { 3 const numHeaderRow = 5;//←ヘッダーの行数 4 const numHeaderColumn = 1;//ヘッダーの列数 5 const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 6 const lastRow = sheet.getLastRow(); 7 const lastColumn = sheet.getLastColumn(); 8 const range = sheet.getRange(numHeaderRow + 1, numHeaderColumn + 1, lastRow - numHeaderRow, lastColumn - numHeaderColumn).getValues(); 9 // console.log(range); 10 //行数分繰り返す 11 for (let i = range.length - 1; i >= 0; i--) {//range.lengthは二次元配列の行(外側の要素)の数 12 console.log(range[i]); 13 //列数分繰り返す 14 for (let j = 0; j < range[0].length; j++) {//range[0].lengthは二次元配列の列(内側の要素)の数、ここは < で比較しているので1は引かない 15 if (range[i][j] == 1) {//値が 1 の列があるとき 16 console.log("ifに入ったよ"); 17 sheet.deleteRow(numHeaderRow + i + 1); 18 console.log((numHeaderRow + i + 1) + '行目を削除しました。'); 19 break;//1がある列をみつけたのでそれ以降の列は検索しない 20 } 21 } 22 } 23}
投稿2023/03/23 01:10
総合スコア789
0
コメントのプレーンテキストではわかりにくいと思い、こちらでご返事します。
>hogehoge.length == 10
なので1引くと「hoge8」からループが開始されるのかなと思いました
について
まず、前提として
for (①; ②; ③) {
④
}
と書いたときの実行順序ですが、
①→②→④→③→②→④→③→②→④→③→②→④→③と②→④→③が続き③のあとで②がfalseなら終了します。
そして、
range.length==10のときの
for (let i = range.length - 1; i >= 0; i--) {
console.log(range[i]);
}
での各値は、
何周目 | range.length の値 | renge.length - 1 の値 | i の値 | range[i]は何番目の要素 |
---|---|---|---|---|
1周目 | 10 | 9 | 9 | 10 |
2周目 | 10 | 9 | 8 | 9 |
3周目 | 10 | 9 | 7 | 8 |
4周目 | 10 | 9 | 6 | 7 |
5周目 | 10 | 9 | 5 | 6 |
6周目 | 10 | 9 | 4 | 5 |
7周目 | 10 | 9 | 3 | 4 |
8周目 | 10 | 9 | 2 | 3 |
9周目 | 10 | 9 | 1 | 2 |
10周目 | 10 | 9 | 0 | 1 |
11周目 | 10 | 9 | -1 | 該当なし |
となり、11週目は i >= 0がfalseで実行されません。
次に、
deleteRowの引数は削除したい行だと思っていたのですが、
この内容だとヘッダー分とi(range.length - 1)も削除されるのではないかと疑問が残りました。
についてですが、
deleteRow()の引数は、おっしゃるとおり削除したい行(1始まりの行番号)です。
for (let i = range.length - 1; i >= 0; i--) {
...
for (let j = 0; j < range[0].length; j++) {
...
sheet.deleteRow(numHeaderRow + i + 1);
}
}
のときのunmHeaderRow + i + 1 の値は、
(j の値は関係ないので省きます。)
何周目 | numHeaderRow の値 | i の値 | numHeaderRow + i + 1 の値 | 引数が表す行番号 |
---|---|---|---|---|
1周目 | 5 | 9 | 15 | 15 |
2周目 | 5 | 8 | 14 | 14 |
3周目 | 5 | 7 | 13 | 13 |
4周目 | 5 | 6 | 12 | 12 |
5周目 | 5 | 5 | 11 | 11 |
6周目 | 5 | 4 | 10 | 10 |
7周目 | 5 | 3 | 9 | 9 |
8周目 | 5 | 2 | 8 | 8 |
9周目 | 5 | 1 | 7 | 7 |
10周目 | 5 | 0 | 6 | 6 |
11周目 | 5 | -1 | 5 | ヘッダー行 |
となり11週目は実行されないのでヘッダー行は削除されません。
投稿2023/03/23 23:57
編集2023/03/24 00:06総合スコア789
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/03/24 14:50
2023/03/24 20:52
2023/03/24 21:25
2023/03/24 22:09
2023/03/26 11:50
2023/03/26 11:59
0
値を取得するセル範囲や削除すべき行番号が明確になるように
あらかじめヘッダーの行数を変数に代入しておくとコードが読みやすくなります。
セルの値を配列に取得して一次元配列に変換するコードになっていますが、
行単位で複数の列の値を比較したいので二次元配列のままにしておきます。
元のスクリプトに沿って、変数宣言や変数名を少し修正したコードの例です。
GAS
1//ヘッダー行より下の行のうちB列またはC列の値が1の行を削除 2function deleteSpecifiedRow() { 3 const numHeaderRow = 5;//←ヘッダーの行数 4 const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 5 const lastRow = sheet.getLastRow(); 6 const range = sheet.getRange(numHeaderRow + 1, 2, lastRow - numHeaderRow, 2).getValues();//←.flat()を削除 7 // console.log(range); 8 for (let i = range.length - 1; i >= 0; i--) { 9 console.log(range[i]); 10 if (range[i][0] == 1 || range[i][1] == 1) {//←2つの列を比較して行数を得たいので二次元配列のまま比較 11 console.log("ifに入ったよ"); 12 sheet.deleteRow(numHeaderRow + i + 1); 13 console.log((numHeaderRow + i + 1) + '行目を削除しました。'); 14 } 15 } 16} 17
投稿2023/03/22 23:59
総合スコア789
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/03/23 00:30
2023/03/23 05:24
2023/03/23 05:27
2023/03/23 13:02
2023/03/23 23:59
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。