🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

Q&A

解決済

2回答

3077閲覧

特定セルを参照し、全シートで一致するデータを書き換える

yukitorte

総合スコア9

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

0グッド

0クリップ

投稿2019/12/06 10:53

GSS上の特定セルを参照し、全シートで一致するデータを書き換える

お世話になります。
500件ぶんの案件管理表x4の書き換えを一括で行いたいと思っています。

ちょっとややこしい説明で申し訳ありませんが……
1つのスプレッドシートの中に
・マスターシート(500件程度、重複なしのユニークデータがある)
・シートA
・シートB
・シートC
があり、シートA~Cのレコードはマスターのコピーです。
すべて同一の内容ではありますが、書式(背景色)で差別化があり
例えばセルC5は、シートAはクリアだけどBとCはグレーアウト……というような感じです。
シートA~Cはそれぞれ外部公開用としてimportrangeで別SSから参照します。

プロジェクトが進行していく上で、作業が終了したレコードを塗りつぶす必要があるのですが
500件x4シートを手動で繰り返すのは、地味に手間もかかるしミスもありえるので
マスターシート上のみの操作で全シート反映させられないかと考えています。

###希望する動作
マスターシートの特定のセルXに修正したいレコードをコピペしてからGASを実行すると
Xのレコードを取得し、シートA・B・Cの中で一致するデータセルを一括でグレーにする。
それにより、外部公開用の各SSも一括で書式変更を反映できるようにする。


ただし、importrangeで呼び出したデータに書式が反映されないそうなので、
コピペ→GAS実行で、例えば同一レコード文末に「.」などを挿入し、
条件付き書式で「.」を含むセルに色をつける……といった強引な方法もアリかなと思っています。
(方法としては美しくはないでしょうが、最終目的は外部公開用のSSに反映させるためなので……)

こちらの場合デフォルトの置換使えばいいのでは?という話が出てくるかと思いますが
操作に不慣れなスタッフもいるため、所定の場所にコピペしたら
その隣にある(トリガーをつけた)ボタンをポチっとするだけ、という形にしたいなと思っています。


プログラミング超初心者のため、ネットで公開されているソースコードを
いじくる形であれやこれや試してみましたが、力不足でした……。
お力をお貸しいただければと思います。

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

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

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

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

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

guest

回答2

0

ベストアンサー

###回答
プログラム修正できました.
おそらく、仕様通りになっていると思います.
前回のプログラムをベースに作っていましたが、処理時間が500件で2分くらいかかっていたので、ロジックを見直しました.

GASはExcelと違って、セルの値の取得やセットの処理がめちゃくちゃ遅いので、値の取得とセットを1回で実施するようにしました。(外部SSも同じ方式にしました.)この方法だと、データ量が増えても処理時間は大きくは伸びないと思います.
前回:セルの数だけ、値の取得とセットをしていた。
今回:初めに一括でシート内のデータを取得して、書式を変数上で変更して、一括でセルにセットしています.(getBackgroundsとsetBackgroundsの箇所です)

###メインSSのGAS

GAS

1 2function myFunction() { 3 4 var start = new Date(); 5//======================================================================================= 6 var SheetMaster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('マスターシート'); 7 var SheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートA'); 8 var SheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートB'); 9 var SheetC = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートC'); 10 11 var LastRow = SheetMaster.getDataRange().getLastRow(); //シート内の最終行(データ次第) 12 var LastCol = SheetMaster.getDataRange().getLastColumn(); //シート内の最終列(12列) 13 var colorsM = SheetMaster.getDataRange().getBackgrounds(); //Mシート内の色データ(2次元配列) 14 var colorsB = SheetB.getDataRange().getBackgrounds(); //Bシート内の色データ(2次元配列) 15 var colorsC = SheetC.getDataRange().getBackgrounds(); //Cシート内の色データ(2次元配列) 16 17 //AシートにMシートの書式を完全コピー 18 SheetA.getRange(1,1,LastRow,LastCol).setBackgrounds(colorsM); 19 20 //Mシートのカラー情報の中で、白のセルにはBシートのセルの書式をコピー 21 for(var col = 0; col <= LastCol-1; col++) { 22 for(var row = 0; row <= LastRow-1; row++) { 23 if(colorsM[row][col] == "#ffffff"){ 24 colorsM[row][col] = colorsB[row][col]; 25 } 26 } 27 } 28 SheetB.getRange(1,1,LastRow,LastCol).setBackgrounds(colorsM);//書式セット 29 30 //Bシートのカラー情報の中で、白のセルにはCシートのセルの書式をコピー 31 for(var col = 0; col <= LastCol-1; col++) { 32 for(var row = 0; row <= LastRow-1; row++) { 33 if(colorsM[row][col] == "#ffffff"){ 34 colorsM[row][col] = colorsC[row][col]; 35 } 36 } 37 } 38 SheetC.getRange(1,1,LastRow,LastCol).setBackgrounds(colorsM);//書式セット 39//======================================================================================= 40 var end = new Date(); 41 var time_past = (end - start) / 1000; 42 Browser.msgBox(time_past + "SEC"); 43} 44

###外部公開用のGAS
外部公開用はA,B,Cをそれぞれ完全コピーしています.
メインSSは書式のみ反映させるプログラムにしましたが、外部SSは値と書式をコピーしてくるようにしました.書式だけ反映する場合は、プログラム内の「値を取得・セット」と書いてある行を削除してください.

function FormLoad() { Browser.msgBox("マスタースプレッドシートを参照します。"); //参照先スプレッドシート var MasterSS = SpreadsheetApp.openById('12JYHXv-tRlfMNZBv1LeScqB5PurAQDP-fyw0HurZ5ho');//参照先のSSのID var MasterSS_A = MasterSS.getSheetByName('シートA') //参照先のシートA var MasterSS_B = MasterSS.getSheetByName('シートB') //参照先のシートB var MasterSS_C = MasterSS.getSheetByName('シートC') //参照先のシートC //外部用スプレッドシート var SheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートA'); //外部SSのシートA var SheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートB'); //外部SSのシートB var SheetC = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートC'); //外部SSのシートC var row var col var values var colors var start = new Date(); //================================================================================================= //外部SSの各シートへ値と書式をコピー //シートA row=MasterSS_A.getDataRange().getLastRow(); col=MasterSS_A.getDataRange().getLastColumn(); values = MasterSS_A.getDataRange().getValues(); //値を取得 colors = MasterSS_A.getDataRange().getBackgrounds(); SheetA.getRange(1,1,row,col).setValues(values); //値をセット SheetA.getRange(1,1,row,col).setBackgrounds(colors); //シートB row=MasterSS_B.getDataRange().getLastRow(); col=MasterSS_B.getDataRange().getLastColumn(); values = MasterSS_B.getDataRange().getValues(); //値を取得 colors = MasterSS_B.getDataRange().getBackgrounds(); SheetB.getRange(1,1,row,col).setValues(values); //値をセット SheetB.getRange(1,1,row,col).setBackgrounds(colors); //シートC row=MasterSS_C.getDataRange().getLastRow(); col=MasterSS_C.getDataRange().getLastColumn(); values = MasterSS_C.getDataRange().getValues(); //値を取得 colors = MasterSS_C.getDataRange().getBackgrounds(); SheetC.getRange(1,1,row,col).setValues(values); //値をセット SheetC.getRange(1,1,row,col).setBackgrounds(colors); //================================================================================================= var end = new Date(); var time_past = (end - start) / 1000; Browser.msgBox(time_past + "SEC"); }

###処理時間遅いプログラム
メインSSだけ、処理時間遅いバージョンも作成しましたので、一応UPします.
タイム計測のコードも書いておきましたので、処理時間比較すると面白いかもしれません.
こちらのプログラムはデータ量に比例して、処理時間が伸びると思います.
動きは同じです.

//処理時間遅い function myFunction1() { var start = new Date(); //======================================================================================= var SheetMaster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('マスターシート'); var SheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートA'); var SheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートB'); var SheetC = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートC'); //A~L列までループ for(var col = 1; col <= 12; col++) { var LastRow = SheetMaster.getRange(1, col).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); //各列の行数を取得 for(var row = 1; row <= LastRow; row++) { var color = SheetMaster.getRange(row,col).getBackground(); //背景色取得 //書式に色がついている場合(白じゃない場合) if(color != "#ffffff"){ SheetA.getRange(row,col).setBackground(color); //Aの特定セルに背景色設定 SheetB.getRange(row,col).setBackground(color); //Bの特定セルに背景色設定 SheetC.getRange(row,col).setBackground(color); //Cの特定セルに背景色設定 } } } //======================================================================================= var end = new Date(); var time_past = (end - start) / 1000; Browser.msgBox(time_past + "SEC(1)"); }

###補足
色の指定は、テーマ欄にある色を設定すると黒色が反映されるため、使わない方がいいです.(画像参照)
イメージ説明

以上です.仕様通りでない場合やバグありましたら、教えてください.

投稿2019/12/09 14:41

KazuSaka

総合スコア640

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

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

yukitorte

2019/12/10 09:42

こちらのコードで期待どおりの動作となりました!! 本当にありがとうございました……! 情報が足りなかったりややこしかったりと、お手を煩わせてしまう事が多く申し訳ありません また機会がありましたらどうぞよろしくお願いします!
guest

0

###回答
案件データがどのような形で入力されているかわからなかったので、A列に案件1~案件500まで入っていると仮定して、プログラムを作ってみました。
マスターシートのイメージはこんな感じです(画像参照)
イメージ説明

###マスターシートのデータをA~Cに反映

■プログラムの流れ
1.完了した案件を全て塗りつぶす.
2.マスターシート内のボタンをクリック.
3.マスターシートのA列の各セルの背景色を取得.
4.シートA、B、Cに背景色を反映.
※A、B、Cの背景色はすべて同じにしています.詳細がわからなかったため.

プログラムを参考までに以下にUPします.

gas

1function myFunction() { 2 3 var SheetMaster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('マスターシート'); 4 var SheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートA'); 5 var SheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートB'); 6 var SheetC = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートC'); 7 const FValues = SheetMaster.getRange('A:A').getValues(); //A列の値を全て取得 8 const LastRow = FValues.filter(String).length; //空白の要素を除いた長さを取得(A列に入っているデータ数) 9 10 //マスターのA列に入っているデータの数だけ処理する 11 for(var i = 1; i <= LastRow; i++) { 12 //処理 13 var color = SheetMaster.getRange(i,1).getBackground(); //背景色取得 14 SheetA.getRange(i,1).setBackground(color); //Aに背景色設定 15 SheetB.getRange(i,1).setBackground(color); //Bに背景色設定 16 SheetC.getRange(i,1).setBackground(color); //Cに背景色設定 17 } 18}

###外部公開用のSSについて
importrange関数では書式が反映されないので、こちらもGASで書いてみました。

■プログラムの流れ
1.外部公開用のスプレッドシートが開いた時に、プログラム起動.
(ファイル起動時にGASを自動起動する設定ができます.)
2.参照先のデータを取得(マスター、A、B、C).
3.外部SSのシート(マスター、A、B、C)に値と書式をセット.

プログラムを参考までに以下にUPします。

gas

1 2function FormLoad() { 3 Browser.msgBox("マスタースプレッドシートを参照します。"); 4 //参照先スプレッドシート 5 //以下のIDは参照先のスプレッドシートのIDを入力してください. 6 //https://docs.google.com/spreadsheets/d/【ここがIDの文字列です】/ 7 var MasterSS = SpreadsheetApp.openById('12YHdfXv-tRlfMdZBLscqBsPusaQDP-fyd0s1sdfsd');//参照先のSSのID 8 var MasterSS_M = MasterSS.getSheetByName('マスターシート') //参照先のシート(マスター) 9 var MasterSS_A = MasterSS.getSheetByName('シートA') //参照先のシートA 10 var MasterSS_B = MasterSS.getSheetByName('シートB') //参照先のシートB 11 var MasterSS_C = MasterSS.getSheetByName('シートC') //参照先のシートC 12 const FValues = MasterSS_M.getRange('A:A').getValues(); //A列の値を全て取得 13 const LastRow = FValues.filter(String).length; //空白の要素を除いた長さを取得 14 15 //外部用スプレッドシート 16 var SheetMaster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('マスターシート'); //外部SSのマスターシート 17 var SheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートA'); //外部SSのシートA 18 var SheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートB'); //外部SSのシートB 19 var SheetC = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シートC'); //外部SSのシートC 20 21 22 //マスターのA列に入っているデータの数だけ処理する 23 for(var i = 1; i <= LastRow; i++) { 24 //マスター 25 var value = MasterSS_M.getRange(i,1).getValue(); //参照先の値取得 26 var color = MasterSS_M.getRange(i,1).getBackground(); //参照先の背景色取得 27 SheetMaster.getRange(i,1).setValue(value); //外部SSのマスターシートに値設定 28 SheetMaster.getRange(i,1).setBackground(color); //外部SSのマスターシートに背景色設定 29 //A 30 value = MasterSS_A.getRange(i,1).getValue(); //参照先の値取得 31 color = MasterSS_A.getRange(i,1).getBackground(); //参照先の背景色取得 32 SheetA.getRange(i,1).setValue(value); //外部SSのマスターシートに値設定 33 SheetA.getRange(i,1).setBackground(color); //外部SSのマスターシートに背景色設定 34 //B 35 value = MasterSS_B.getRange(i,1).getValue(); //参照先の値取得 36 color = MasterSS_B.getRange(i,1).getBackground(); //参照先の背景色取得 37 SheetB.getRange(i,1).setValue(value); //外部SSのマスターシートに値設定 38 SheetB.getRange(i,1).setBackground(color); //外部SSのマスターシートに背景色設定 39 //C 40 value = MasterSS_C.getRange(i,1).getValue(); //参照先の値取得 41 color = MasterSS_C.getRange(i,1).getBackground(); //参照先の背景色取得 42 SheetC.getRange(i,1).setValue(value); //外部SSのマスターシートに値設定 43 SheetC.getRange(i,1).setBackground(color); //外部SSのマスターシートに背景色設定 44 } 45} 46

以上です。不明点ありましたら、お気軽にどうぞ。

投稿2019/12/06 22:07

編集2019/12/06 22:11
KazuSaka

総合スコア640

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

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

yukitorte

2019/12/09 07:06

KazuSakaさんご回答ありがとうございます! マスターシートの形式も記載しておけばよかったですね。 不明瞭な質問となってしまい、申し訳ないです。 1月 2月 3月・・・・・ 件A 件D 件F 件B 件E 件G 件C    件H といったように、各月の案件名を並べた表という感じです。 列は12ヶ月固定なのでL列までで大丈夫です。 行数(案件数)は月によって若干変動があります。 --- 私の質問内容が不適切だったため、データの形状の不一致はあったのですが ご教示いただきましたコードの動作は素晴らしかったです……! コピペする手間も省かれていて、一気に処理できるので むしろ理想より上をゆく形になっていて感動です……! 公開用SSのコードもありがとうございます! こちらも動作自体は理想的なものでした……! (同期中のダイアログもありがたかったです) --- getRange('A:A')をgetRange('A2:L51')などにすると、 (gsの実行時間が長くなったので)値の取得のほうはできたような気配はするのですが、 各シートへ反映されるのはA列のみだったので おそらくfor以降も調整が必要そうな感じでしょうか……。 かなり初歩的な質問だとは思うので、お恥ずかしい限りですが 反映範囲を調整するにはどうしたらいいかお教えいただけますとありがたいです。
yukitorte

2019/12/09 07:25

すみません、追記です! こちら、データが含まれる全セルをマスターシートの色状態に同期させる、 といった動作になるかと思いますが、 マスターで色をつけたセルのみ反映させる、色のついていないセルは何のアクションもしない ということは可能でしょうか? 運用したいデータが >すべて同一の内容ではありますが、書式(背景色)で差別化があり >例えばセルC5は、シートAはクリアだけどBとCはグレーアウト……というような感じです。 という状態ですが、上記の例でいいますと マスターのC5がクリアだと、本gs実行後BとCもクリアになってしまう(上書き)ため データの状態が変わってしまうなと気づいたので……! 重ね重ね申し訳有りませんが、引き続きご指導いただけますでしょうか><;
KazuSaka

2019/12/09 09:01

喜んでもらえてよかったです! 確認です。 以下でよろしいですか? シートAはすべてのデータが白背景. シートB、Cはマスターシートの書式を完全コピー. 外部SSも同じ仕様ですか? 以上
yukitorte

2019/12/09 10:37

わかりにくくて申し訳ありません……! 各シートの、運用開始前の『初期状態』は マスターは、すべて白背景(塗りなし) シートAは、すべて白背景(塗りなし) シートBは、一部グレーのセルがある シートCは、Bのグレーセル+さらにグレーのセルが増える です。 ◆マスター 1月 2月 3月・・・・・ 件A 件D 件F 件B 件E 件G 件C    件H ◆シートA 1月 2月 3月・・・・・ 件A 件D 件F 件B 件E 件G 件C    件H ◆シートB 【】が初期状態からグレー 1月 2月 3月・・・・・ 件A【件D】件F 件B 件E 【件G】 件C    件H ◆シートC 【】が初期状態からグレー  1月 2月 3月・・・・・  件A【件D】件F 【件B】件E 【件G】  件C   【件H】 上記が初期状態として、マスターで指定したセルのみ反映していく想定なので 例えば件Cをグレーにするようgsを実行したとき 現状ですと、すべてのシートが  1月 2月 3月・・・・・  件A 件D 件F  件B 件E 件G 【件C】   件H になってしまうため、B・Cのシートの塗りを維持したまま (シートCの場合)  1月 2月 3月・・・・・  件A【件D】件F 【件B】件E 【件G】 【件C】  【件H】 となるのが期待する動作になります……! 運用イメージとしては、 マスター=案件難易度易~難まで順不同で、案件発生順に並んでいるデータ シートA=超絶スペシャリストの外注さんにお渡しする一覧(どれでも選べる) シートB=納品実績のある外注さんにお渡しする一覧(超難易度案件をグレーにした状態) シートC=初心者外注さんにお渡しする一覧(中難易度以上をグレーにした状態) という感じで、アサインが決まった案件をマスターから一括で全シート塗りつぶす……です。 余談ですが、初期グレーとgsで付ける色は同色でも別色でも問題ありません。 もし情報の不足がありましたら、お声がけください。 お手数おかけしますが、どうぞよろしくお願いします!
KazuSaka

2019/12/09 11:19 編集

仕様は理解できたと思います! 3点教えてください! ・運用中に塗潰した案件は、A,B,Cに反映しますよね? 初期状態だけ、A、B、Cの書式が異なるという事ですよね? ・運用途中に案件を追加することはありますか? ・外部SSはマスターファイルのマスターシート、シートA,B,Cと同じ内容でいいですか?
yukitorte

2019/12/09 11:44

・運用中に塗潰した案件は、A,B,Cに反映しますよね?  →そのとおりです! ・運用途中に案件を追加することはありますか?  →ありません ・外部SSはマスターファイルのマスターシート、シートA,B,Cと同じ内容でいいですか?  →マスターは社内用なので外部用には不要ですが、A~Cは同じ内容で大丈夫です!   こちらは前回頂いていたコードの、データ反映範囲が   A~L列までにできれば問題ないかと思います。 どうぞよろしくお願いします……!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問