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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Google スプレッドシート

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

Google Apps Script

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

Q&A

解決済

1回答

694閲覧

Googleスプレッドシートのシート1にある複数の時系列グラフがある。GASでシート2に直近1時間分のグラフを描かせたい。

Aki1000

総合スコア78

Google スプレッドシート

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

Google Apps Script

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

0グッド

0クリップ

投稿2024/01/14 13:35

編集2024/01/14 13:37

実現したいこと

Googleスプレッドシートのシート1に複数の時系列グラフがある。Google Apps Script(GAS)でシート2に直近1時間分のグラフを描かせたい。
シート1の単数グラフの直近一時間のグラフをシート2に描かせるScriptは人に書いて貰って問題なく動くので、これを改造して、複数のグラフを描かせたい。

前提

シート1のA列に時間、B列、C列、D列、E列にデータが入っている。データはGASで行末に十秒に一度追加される。
問題なく動くシート1の単数のグラフの直近一時間のデータをシート2にグラフで書かせる為のGASは以下の通りである。

Google

1// 既存のグラフのデータ範囲を更新 2function updateChartRange() { 3 // 初期設定 4 const ss = SpreadsheetApp.getActiveSpreadsheet(); 5 const sheet1 = ss.getSheetByName('シート1'); 6 const sheet2 = ss.getSheetByName('シート2'); 7 8 // シート1の最終行を取得し、その60秒×60分÷10秒(1時間)分の360行を遡った行番号を取得 9 const lastRow = sheet1.getLastRow(); // 最終行 10 const firstRow = lastRow <= 360 ? 1 : lastRow - 360; // 1時間前の行(1時間経過していないなら最初の行) 11 12 // A列の遡った行からB列の最終行までのセル範囲を取得 13 const rangeAdd = sheet1.getRange('A' + firstRow + ':B' + lastRow); 14 15 // シート2の既存のグラフを取得 16 // ※ グラフは1つしかないが、配列で取得されるので1番目[0] 17 let chart = sheet2.getCharts()[0]; 18 19 // 既存のグラフをベースとするグラフ作成ツールを取得 20 const chartBuilder = chart.modify(); 21 22 // グラフ作成ツールからデータのセル範囲を全て取得 23 // ※ 実際には、セル範囲は1つしかないが配列で取得される 24 const ranges = chartBuilder.getRanges(); 25 26 // グラフ作成ツールにより、 27 // 設定されているセル範囲を削除し、 28 // 新たなセル範囲を追加してからグラフを生成 29 chart = chartBuilder 30 .removeRange(ranges[0]) // 取得したセル範囲の配列の最初のセル範囲[0]を削除 31 .addRange(rangeAdd) // 前もって取得しておいたセル範囲を追加 32 .build(); // 変更を反映したグラフを生成 33 34 // 生成したグラフで既存のグラフを更新 35 sheet2.updateChart(chart); 36} 37 38// ファイルを開いたときにメニューを追加 39function onOpen() { 40 SpreadsheetApp.getUi() 41 .createMenu('グラフ') 42 .addItem('更新', 'updateChartRange') 43 .addToUi(); 44}

これを改造して、複数のグラフに対応させたい。

試したこと

以下の通り、レンジ指定を変えてA列とB列だけでなく、A列とC列、A列とD列、A列とE列のグラフに拡張しようとスクリプトを改造した。

Google

1 2function updateChartRange() { 3const ss = SpreadsheetApp.getActiveSpreadsheet(); 4const sheet1 = ss.getSheetByName('シート1'); 5const sheet2 = ss.getSheetByName('シート2'); 6const lastRow = sheet1.getLastRow(); 7const firstRow = lastRow <= 360 ? 1 : lastRow - 360; 8const range0Add = sheet1.getRange('A' + firstRow + ':B' + lastRow); 9const range1Add = sheet1.getRange('A' + firstRow + ':A' + lastRow + ',' + 'C' + firstRow + ':C' + lastRow ); 10const range2Add = sheet1.getRange('A' + firstRow + ':A' + lastRow + ',' + 'D' + firstRow + ':D' + lastRow ); 11const range3Add = sheet1.getRange('A' + firstRow + ':A' + lastRow + ',' + 'E' + firstRow + ':E' + lastRow ); 12 13let chart0 = sheet2.getCharts()[0]; 14let chart1 = sheet2.getCharts()[1]; 15let chart2 = sheet2.getCharts()[2]; 16let chart3 = sheet2.getCharts()[3]; 17 18const chartBuilder0 = chart0.modify(); 19const chartBuilder1 = chart1.modify(); 20const chartBuilder2 = chart2.modify(); 21const chartBuilder3 = chart3.modify(); 22 23const ranges0 = chartBuilder0.getRanges(); 24const ranges1 = chartBuilder1.getRanges(); 25const ranges2 = chartBuilder2.getRanges(); 26const ranges3 = chartBuilder3.getRanges(); 27 28chart0 = chartBuilder0 29chart1 = chartBuilder1 30chart2 = chartBuilder2 31chart3 = chartBuilder3 32 33.removeRange(ranges0[0]) 34.removeRange(ranges1[0]) 35.removeRange(ranges2[0]) 36.removeRange(ranges3[0]) 37 38.addRange(range0Add) 39.addRange(range1Add) 40.addRange(range2Add) 41.addRange(range3Add) 42 43.build(); 44sheet2.updateChart(chart0); 45sheet2.updateChart(chart1); 46sheet2.updateChart(chart2); 47sheet2.updateChart(chart3); 48 49} 50// ファイルを開いたときにメニューを追加 51function onOpen() { 52 SpreadsheetApp.getUi() 53 .createMenu('グラフ') 54 .addItem('更新', 'updateChartRange') 55 .addToUi(); 56}

上のスクリプトでは、sheet1.getRangeで('A' + firstRow + ':B' + lastRow);
として、もし現在のデータ数が660個だとすると、グラフの範囲(A300:B660)を指定している。C列のデータ範囲が'シート1'!A300:A360,'シート1'!C300:C360なので、指定にsheet1.getRange('A' + firstRow + ':A' + lastRow + ',' + 'C' + firstRow + ':C' + lastRow )としてみたが、こういう使い方は Range not foundといわれるので書式が良くないらしい。

他にもBuild周りでちゃんと動かない気がする。

どうやったら、複数のグラフでシート2にグラフを書かせることが出来るでしょうか?
よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

前回と異なり、複数のグラフでB列以外ではセル範囲が連続していないので、
B列も含め、セル範囲を2つ(X軸とY軸の1系列)設定してグラフが作成されていることが前提になります。
4つのグラフを個別にではなく、繰り返し処理でセル範囲を更新しています。
なお、4つのグラフの更新中に10秒後のデータがシート1に追記された場合
最新のセル範囲にならず、その後自動的にセル範囲が広がっていくことには
ならない場合があります。(厳密には前のグラフ1つの例でもあり得ました。)

JavaScript

1// X軸にA列と系列としてB-E列の2つの列がセル範囲に 2// 設定されたグラフがあることを前提としているので 3// 既存のグラフのセル範囲が'シート1'!A1:B360なら 4// X軸:'シート1'!A1:A360 5// 系列(Y軸):'シート1'!B1:B360 と設定して 6// セル範囲を'シート1'!A1:A360;'シート1'!B1:B360 7// とするグラフに変更しておく必要があります。 8// C列、D列,E列のグラフも同様です。 9function updateChartRange() { 10 // 初期設定 11 const ss = SpreadsheetApp.getActiveSpreadsheet(); 12 const sheet1 = ss.getSheetByName('シート1'); 13 const sheet2 = ss.getSheetByName('シート2'); 14 const xAxis = 'A'; // X軸の列 15 const yAxes = [ // 系列(Y軸)の列 16 'B', // グラフ1 17 'C', // グラフ2 18 'D', // グラフ3 19 'E', // グラフ4 20 ]; 21 22 // 最終行と1時間分遡った行を取得 23 const lastRow = sheet1.getLastRow(); 24 const firstRow = lastRow <= 360 ? 1 : lastRow - 360; 25 26 // X軸のセル範囲 27 const rangeX = sheet1.getRange(xAxis + firstRow + ':' + xAxis + lastRow); 28 29 // Y軸のセル範囲を順次配列に蓄積 30 const rangeAdd = []; 31 for (const yAxis of yAxes) { 32 rangeAdd.push(sheet1.getRange(yAxis + firstRow + ':' + yAxis + lastRow)); 33 } 34 35 // シート2のグラフを全て取得 36 const charts = sheet2.getCharts(); 37 38 // それぞれのグラフごとに繰返し処理 39 const newCharts = []; // 生成したグラフを蓄積する配列 40 for (let chart of charts) { 41 // グラフ作成ツールを取得 42 const chartBuilder = chart.modify(); 43 44 // 設定されているセル範囲を取得 45 const ranges = chartBuilder.getRanges(); 46 47 // セル範囲を全て削除 48 for (const range of ranges) { 49 chartBuilder.removeRange(range); 50 } 51 52 // X軸及びY軸のセル範囲を追加してグラフを生成し配列に蓄積 53 chart = chartBuilder 54 .addRange(rangeX) 55 .addRange(rangeAdd.shift()) 56 .build(); 57 newCharts.push(chart); 58 } 59 60 // タイミングをあわせるため更新処理は分離 61 for (const chart of newCharts) { 62 // 生成したグラフで既存のグラフを更新 63 sheet2.updateChart(chart); 64 } 65} 66 67// ファイルを開いたときにメニューを追加 68function onOpen() { 69 SpreadsheetApp.getUi() 70 .createMenu('グラフ') 71 .addItem('更新', 'updateChartRange') 72 .addToUi(); 73}

投稿2024/01/15 03:30

YellowGreen

総合スコア861

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

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

Aki1000

2024/01/15 13:16

ありがとうございました!! 本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問