ラベル SpreadSheet の投稿を表示しています。 すべての投稿を表示
ラベル SpreadSheet の投稿を表示しています。 すべての投稿を表示

2024年11月29日金曜日

GoogleSpreadSheetで月ごとに色を分ける方法

GoogleSpreadSheetで月ごとに色を分ける方法

概要

特定のカラムで日時を管理している場合に月ごとにセルの色を変更する方法を紹介します
条件付き書式ではできないので GoogleAppScript を使います

環境

  • GoogleSpreadSheet (2024/11/29時点)
  • GoogleAppScript (2024/11/29時点)

特定の色に変更する方法

事前に30色分(30ヶ月分)用意しています
何度実行しても同じ色になるようにしています

B2 カラムで日時を管理している想定です
B2 カラムの1行目はヘッダで2行目から日時データの想定です
B2 カラムの日時はフォーマットが Date になっていることが条件です

function colorRowsByMonth() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastRow = sheet.getLastRow(); // シート内の最終行を取得
  const range = sheet.getRange(2, 2, lastRow - 1, 1); // B列の2行目から最終行まで取得
  const values = range.getValues(); // データを2次元配列で取得
  const colors = {}; // 月ごとの色を保持するオブジェクト
  const colorPalette = getLargeFixedColorPalette(); // 固定された30色の薄い色パレット
  let paletteIndex = 0;

  for (let i = 0; i < values.length; i++) { // ヘッダーをスキップ
    const date = values[i][0]; // 日時が入力されているカラム (A列の場合)
    if (date instanceof Date) { // 日付形式か確認
      const monthKey = Utilities.formatDate(date, Session.getScriptTimeZone(), "yyyy/MM");
      // 月ごとの色を設定(未登録なら新しい色を割り当て)
      if (!colors[monthKey]) {
        colors[monthKey] = colorPalette[paletteIndex % colorPalette.length];
        paletteIndex++;
      }
      // B2から下に行の背景色を設定
      sheet.getRange(i + 2, 2, 1, 1).setBackground(colors[monthKey]);
    }
  }
}

// 固定された30個の薄い色のパレットを生成する関数
function getLargeFixedColorPalette() {
  return [
    "#FFCCCC", "#FFEECC", "#FFFFCC", "#CCFFCC", "#CCE5FF",
    "#CCCCFF", "#FFCCE5", "#FFE4B5", "#D8BFD8", "#B0E0E6",
    "#F0E68C", "#E6E6FA", "#F5DEB3", "#FFDAB9", "#F0FFF0",
    "#FFF0F5", "#FFFACD", "#E0FFFF", "#FAFAD2", "#D3D3D3",
    "#FFC0CB", "#B0C4DE", "#ADD8E6", "#DDA0DD", "#D9F2E6",
    "#F2E2D2", "#F5F5DC", "#FBE5D6", "#EBF4FA", "#FAEBD7"
  ];
}

月分だけ色を用意する方法

例えば 2024/01 と 2025/01 は同じセルの色にしたい場合などはこちらを使います
こちらの方法は12色準備すれば OK なので色の追加などは不要です

function colorRowsByMonth() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastRow = sheet.getLastRow(); // シート内の最終行を取得
  const range = sheet.getRange(2, 2, lastRow - 1, 1); // B列の2行目から最終行まで取得
  const values = range.getValues(); // データを2次元配列で取得
  const monthColors = getMonthColors(); // 月ごとの色を取得

  for (let i = 0; i < values.length; i++) { // ヘッダーをスキップ
    const date = values[i][0]; // 日時が入力されているカラム (A列の場合)
    if (date instanceof Date) { // 日付形式か確認
      const month = date.getMonth(); // 月を取得(0: 1月, 11: 12月)
      const color = monthColors[month]; // 月に対応する色を取得
      // B2から下に行の背景色を設定
      sheet.getRange(i + 2, 2, 1, 1).setBackground(color);
    }
  }
}

// 1月から12月までの固定色を返す関数
function getMonthColors() {
  return [
    "#FFCCCC", // 1月 - 薄い赤
    "#FFEECC", // 2月 - 薄いオレンジ
    "#FFFFCC", // 3月 - 薄い黄色
    "#CCFFCC", // 4月 - 薄い緑
    "#CCE5FF", // 5月 - 薄い青
    "#CCCCFF", // 6月 - 薄い紫
    "#FFCCE5", // 7月 - 薄いピンク
    "#FFE4B5", // 8月 - 薄いベージュ
    "#D8BFD8", // 9月 - 薄いモーブ
    "#B0E0E6", // 10月 - 薄い水色
    "#F0E68C", // 11月 - 薄いカーキ
    "#E6E6FA"  // 12月 - 薄いラベンダー
  ];
}

最後に

レコードが増えたら再度 GAS を実行する必要があるのが不便です
(条件付き書式でもできる方法があるのだろうか)

2022年12月22日木曜日

Google App Script で使用している列の一覧を取得する方法

Google App Script で使用している列の一覧を取得する方法

概要

例えば A から AB まで列を広げている場合に A から AB までを持つ配列を取得する方法を紹介します

環境

  • Google App Script 2022/12/16 時点

サンプルコード

// 数字情報を列のアルファベットに変換するメソッド
function columnToLetter(column) {
  var temp, letter = '';
  while (column > 0)
  {
    temp = (column - 1) % 26;
    letter = String.fromCharCode(temp + 65) + letter;
    column = (column - temp - 1) / 26;
  }
  return letter;
}

// 指定の配列を number 個ずつ分割するメソッド
function sliceByNumber(array, number) {
  const length = Math.ceil(array.length / number)
  return new Array(length).fill().map((_, i) =>
    array.slice(i * number, (i + 1) * number)
  )
}

// メイン
function main() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var activeCols = sliceByNumber([...Array(sheet.getLastColumn()).keys()].map(i => columnToLetter(i+1)), 3);
}

ちょっと解説

[...Array(sheet.getLastColumn()).keys()] で最初の列からアクティブになっている最後の列までの数字配列を取得します

その結果に対して map で columnToLetter を実行し数字 -> アルファベットの変換をしています
数字状態の配列は0から始まっているので1から始めるために+1しています (A列は1に割り当てているので)

あとは sliceByNumber で配列を更に3つずつに分割しています
分割が必要ない場合は sliceByNumber の実行は不要です

最後に

これでどんどん列が増えていっても自動で列情報を取得することができます

2021年11月19日金曜日

AppScript「Logging output too large. Truncating output.」対策

AppScript「Logging output too large. Truncating output.」対策

概要

console.log だと出力の長さに制限があります
一番てっとり早いのは適当なセルに結果を出力してあげることです

環境

  • macOS 11.6
  • Chrome 91.0.4472.106
  • Google SpreadSheet
  • Apps Script

サンプルスクリプト

一部抜粋ですが console.log の箇所をセルに setValue するように変更するだけです

// console.log("var labels = ['" + labels.reverse().join("','") + "']");
// console.log("var amountData = [" + data.reverse().join(",") + "]");
// console.log("var calData = " + JSON.stringify(calData));
var labelResult = sheet.getRange("G12");
labelResult.setValue("var labels = ['" + labels.reverse().join("','") + "']");
var amountDataResult = sheet.getRange("G13");
amountDataResult.setValue("var amountData = [" + data.reverse().join(",") + "]");
var calDataResult = sheet.getRange("G14");
calDataResult.setValue("var calData = " + JSON.stringify(calData));

参考サイト

2021年7月2日金曜日

Google SpreadSheet でカーソルを移動する方法

Google SpreadSheet でカーソルを移動する方法

概要

例えばスプレッドシートを開いたときに特性のセルにカーソルを移動したい場合などに使えます

環境

  • macOS 11.4
  • Chrome 91.0.4472.106
  • Google SpreadSheet
  • Apps Script

サンプルコード

例えば一番左上にカーソルを合わせる場合は以下のような感じになります ポイントは Range に対して activate() する点です

function setCursorToStart() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange("A1").activate();
  // var range = sheet.getRange(1, 1).activate(); こっちでも OK
}

ちょっと応用1: 起動時に移動させる

onOpen というイベントハンドラが用意されているのでそれを実行してあげます

function onOpen(e) {
  setCursorToStart();
  Browser.msgBox("Automatically moved cursor to today's cell.");
}

ダイアログはテストのために入れているので実際は消してください

ちょっと応用2: 特定の条件に合致したセルに移動する

例えば日付を管理しているカラムがある場合に今日の日付のセルに移動したりもできます

以下のサンプルでは A 列で日付を管理しています new Date() で今の時刻を取得できるのであとは年月日を照らし合わせているだけです

row と col が String になっているので parseInt で変換してから Range を取得しましょう

function moveCursorToToday() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange("A:A");
  var a_values = range.getValues();
  var date = new Date();
  for (var row in a_values) {
    for (var col in a_values[row])
    if (checkToday(date, a_values[row][col])) {
      var range = sheet.getRange(parseInt(row) + 1, parseInt(col) + 1).activate();
      return;
    }
  }
}

function checkToday(day, oday) {
  if (day.getFullYear() == oday.getFullYear() && day.getMonth() == oday.getMonth() && day.getDate() == oday.getDate()) {
    return true
  }
  return false
}

参考サイト

2021年7月1日木曜日

TypeError: Cannot read property 'getBody' of null

TypeError: Cannot read property 'getBody' of null

概要

SpreadSheet でドキュメントオブジェクトを取得する際に発生しました 原因と対策を紹介します

環境

  • macOS 11.4
  • Chrome 91.0.4472.106
  • Google SpreadSheet
  • Apps Script

原因

SpreadSheet を扱おうとしているのに Documents を取得しようとしているのが原因です

対策

var doc = DocumentApp.getActiveDocument();

↓

var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

SpreadSheet にはちゃんと SpreadSheet を扱うための関数があります サンプルに DocumentApp.getActiveDocument() を使うのが多いのでごっちになるのかもしれません

2021年6月28日月曜日

Google SpreadSheet で Apps Script に入門してみた

Google SpreadSheet で Apps Script に入門してみた

概要

Apps Script は Google のいろいろなサービスに JavaScript でアクセスできるサービスです 当然 SpreadSheet にも触れるので今回は SpreadSheet から Apps Script に入門してみました

環境

  • macOS 11.4
  • Chrome 91.0.4472.106
  • Google SpreadSheet
  • Apps Script

Apps Script を起動する

まずは SpreadSheet にアクセスしましょう そして

ツール -> スクリプトエディタ

と選択します

すると別画面で Apps Script の Web エディタが開きます ここで SpreadSheet 用のスクリプトを JavaScript で記載することでセルの操作などができます

サンプルコード

ではスクリプトを作成します すでにいろいろ書いてありますがデフォルトだと何もしないからの function が 1 つ用意されているだけです

今回は 3 つほどサンプルの関数を用意したので貼り付けてみましょう

function hello() {
  console.log("hello macro")
}

function getCell() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange("A2");
  var cell_a1_value = range.getValue();
  console.log(cell_a1_value);
}

function getCells() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange("A7:A");
  var a_values = range.getValues();
  for (var row in a_values) {
    for (col in a_values[row]) {
      console.log(a_values[row][col]);
    }
  }
}

それぞれ以下のようなサンプル関数になっています

  • hello・・・ログにメッセージを出力するだけの関数
  • getCell・・・特定のセルの値をログに出力する関数
  • getCells・・・複数の特性のセルをログに出力する関数

実行してみる

サンプルの関数を貼り付けたら実行してみましょう Apps Script のツールバーに「保存ボタン」があるのでスクリプトを保存しましょう

そしてその隣に「実行」と実行する関数名を選択できるプルダウンがあるので「hello」を選択してクリックしてみます

すると画面下にログ実行ログが表示されてメッセージが出力されているのが確認できると思います

アクセスを許可する

初回実行時やアプリがアクセスしたいスコープが変更になった場合はアクセス許可をする必要があります

Apps Script は新しいアプリとして登録されています アプリから SpreadSheet にアクセスするために許可を与える必要があります また今回作成したアプリはテスト用のアプリの設定になっており以下のように警告が出ますが気にせず許可しましょう

左下にある「詳細」をクリックすると以下のように表示されるので更に「無題のプロジェクト ( 安全ではないページ) に移動」をクリックします

他にも便利な機能がたくさんある

  • SpreadSheet 側にボタンなどを作成して関数を紐付ける
  • サードパティのライブラリの使用
  • doGet や doPost ハンドラを実行して GCP にデプロイして Web アプリとして動作させる
  • トリガーを使って定期的に実行させる

などなどたくさんの機能があります なお .gs スクリプトは基本的には GCP 上で動作させることができるスクリプトなのでローカルアプリとして動作させるのはできません

clasp などのツールを使えばローカルで開発することはできるようにはなりますがあくまでも動作させるのは GCP 上になります