見出し画像

スプレッドシートに挿入した図形(ボタン)をクリックしたら指定のWebサイトを開きたい(GASでハイパーリンクボタンは作れるか?)

2025年最初のnoteです。今年も mirのnoteをよろしくお願いいたします。

2025年一発目のnoteでなにをやろうかな?

と考えましたが、実は過去のnoteでチラッと触れて、「別の機会に詳しく書きたい」としたまま放置しているネタが色々あるんですよねw

今回は、その中から人気のハイパーリンクの回で触れた

こちら、Googleスプレッドシートに図形描画で挿入した図形(ボタン)にGASを設定して 指定したURLのページを開く方法(ハイパーリンクボタンの作成方法)を書きたいと思います。

ちなみに、このハイパーリンクの記事がどれくらい人気だったかというと

2024年の1年間で 約4万6千ビューで よく読まれた記事の TOPとなった超人気記事です。

ありがたいことです。<(_ _)>

2024年の最後、前回のnoteは REDUCE関数やLET関数をフル活用した 年間カレンダーを1つの数式で生成するネタを書きました。




Googleスプレッドシートは 図形や画像にハイパーリンクを設定できない

「図形をクリックしたら、指定したWebサイトが開く」なんていうExcelだったら超普通に出来ることを、なぜわざわざ noteにまとめているか?

それはExcelと違って、Googleスプレッドシートは 挿入した図形や画像にハイパーリンクを設定できないからです。



Excelは挿入した図形や画像にハイパーリンクを設定できる

インストール版のExcelの場合、挿入した図形や画像は、

このように右クリックから普通にリンクを設定することが出来て、

クリックすれば指定した外部リンク(Excelの場合はローカルのファイル指定なども可能)を開くボタンを簡単に作成することができます。

ただ、無料のWeb版Excelの場合は同じようにいきません。

挿入した図形は右クリックに リンクのメニューはなく、図形を選択した状態だと リボンメニューの 挿入 > リンクもグレーアウトして使えません。

ローカルのインストール版Excelで ハイパーリンクを仕込んだ図形を設置したExcelファイルを OneDriveにアップロードしてWeb版で開くことで、

このようにインストール版で事前に設定すれば、Web版Excelでも 図形をクリックして指定したWebサイトを開くことが実現できます。

ただし、無料Web版で開いた状態ではこのリンクURLの変更やリンクの削除が出来ません。

かなり限定的な利用となりますね。



Googleスプレッドシートは 図形や画像にリンクを設定できない

Excelと違ってGoogleスプレドシートの図形描画は非常に貧弱で扱いづらいんですが、メニューもこの通り 

「編集」・・・ ダブルクリックと同様に図形描画ダイアログが開く
「削除」・・・Deleteと同様に図形を削除する
「スクリプトを割り当て」・・・ GASの実行ボタンとして設定できる
「代替テキスト」 ・・・ 閲覧できない人用にテキストを設定

非常にシンプルでハイパーリンクの設定が出来ません。

ちなみにメニューバーの リンクボタンは アクティブになっているように見えますが、

これは、Googleスプレッドシートは図形を選択した状態でも、その前に選択していたセルの選択状態が保持されているので、

リンクを挿入で機能するのは、セルの方になってしまう仕様だからです。

ちなみに「編集」で開いた図形描画ダイアログ内にも リンクを挿入するメニューやボタンはありません。

また、Excelと同じように ハイパーリンクを設定したボタン入りのExcelファイルをGoogleドライブにアップロードした場合でも

図形のハイパーリンクは機能せず、ちょっと編集しようとするとこのように「一部のExcel要素が破棄される可能性があります」という警告メッセージが出ます。

どうやっても、Googleスプレッドシートでは図形や画像にハイパーリンクを設定することは出来ません。



Googleドキュメント、Googleスライド、図形描画は 図形にリンクを設定できる

やっぱりWebブラウザベースのオフィスツールは勝手が違うから、図形や画像にリンクを設定するのは難しいのか?というと、別にそんなこともなさそうで

普通にGoogleドキュメント

Googleスライド

Google図形描画

いずれも 図形でも画像でも ハイパーリンクを設定することが出来ます。

ほんとGoogleスプレッドシートだけがダメなんです。

ちなみにハイパーリンクを設定した図形を Googleスプレッドシートで立ち上げた図形描画のダイアログにコピペすることは出来ますが、貼り付けた時点でハイパーリンクの機能は失われます

また、この中でGoogleドキュメントの図形、画像のハイパーリンクだけは特殊な仕様になっています。

もう少し詳しく見ておきましょう。



Googleドキュメントの図形、画像は「行内」設定の時だけハイパーリンクが設定できる

Googleドキュメントは、図形や画像に「リンクを挿入」できる(ハイパーリンクを設定できる)と書きましたが、実はこれが出来るのは 画像の配置を「行内」に設定している時のみに限定されます。

「行内」以外の配置設定では、図形や画像にハイパーリンクを設定することが出来ません。

さらに「行内」でハイパーリンクを設定していた画像を、別の配置に変更した場合、設定していたハイパーリンクは消失し 再び「行内」に変更したとしてもハイパーリンク機能は復活しません。

この点は注意です。


とりあえず、Googleスプレッドシートで挿入した図形や画像には ハイパーリンクは設定できないけど、GAS(スクリプト)は設定できるで、GASでなんとか解決できないか?を考えてみましょう。



GASでハイパーリンクのような挙動は実現できるのか?

実は「GASでハイパーリンクのような挙動は実現できるのか?」は、回答が難しい問いなんですが、正しく回答すると

GASでは指定したURLのWesサイトを別タブで開くハイパーリンク機能のような動作は出来ません。

となります。


サーバーサイドのGASではブラウザを開くことはできない

GAS(GoogleAppsScript)は、JavaScriptベースではありますが、あくまでもサーバー側で動作するスクリプトです。

スプレッドシート、ドキュメント、スライド、フォーム、ドライブ、さらに GmailやGoogleカレンダー といったGoogleのサービスと連携、自動化するには便利ですし、Web上のデータを取得したり、簡易的なWebアプリケーションを作成することは出来ますが、

ローカル(PC内)にあるファイルを取得したり
逆にGoogleドライブ内のファイルを自動的にダウンロードさせたり

といった、ローカルの処理を実行する権限はありません。

今回の「指定したリンクのWebページを開く」という動作も、あくまでもWebブラウザ(ローカル)の処理である為、GASからこれを操作することは出来ないわけです。

ただし別ページではありませんが、スプレッドシートのスクリプトエディタに記述したGAS(コンテナバインドスクリプト)を(ボタンなどから)実行して サイドバーやダイアログを立ち上げることは出来ます。

サイドバー
モーダルダイアログ

これらは Uiクラスのメソッドを使います。

このサイドバーとダイアログは、同じUiクラスの prompt や BrowserクラスのmsgBox と違って、中身をHTMLで記述できるという特徴があります。

そして HTML内の JavaScriptであれば、ローカルサイドのスクリプトとなる為「別タブで指定したWebページを開く」ことが出来ます。

つまり

GASで ダイアログ を起動させ、そのダイアログで JavaScriptを実行させて 指定したWebページを開く

これだったら出来るっていうことです。



AIチャットでも希望のコードを得られるか?

では、具体的にどんなコードを書いたらよいか?

自分でコード書けるんですが、ためしにAIチャット4種に 

GASで指定したURLのWebサイトを別タブで開くコードを教えてください

こんな質問を投げかけてみました。

Gemini(無料版)

正直、Geminiさんは一番ダメな回答ですね。単なるJavaScriptのコードで、これはGASでは動きません。

Geminiはコードレビューに強いってネット上の記事も多いんですが、どうも自分の環境だといい回答を返してくれることが少ない印象。


Copilot

Copilotさんは説明もコードも非常にあっさりしていますが、きちんとダイアログをGASで立ち上げJavaScriptで Webサイトを開くコードになっています。

きちんと動作するんですが、Webサイトを開いた後のスプレッドシートに

このようにダイアログが残っちゃうのがイマイチ。

追加リクエストをすれば、きちんと ダイアログを閉じる処理を追加したコードを回答してくれます。



ChatGPT

ChatGPTさんも、ダイアログを立ち上げてHTMLファイル内のJavaScriptを使って別タブでWebを開く、きちんと動作するコードを返してくれました。

やや日本語に違和感がありますが、説明は丁寧です。

Webサイトを開いた後、ダイアログを閉じる処理が入ってるのも良いです。

HTMLファイルを別で記述するのはやや面倒ですが、さすがですね。


Claude

Claudeさんは、ChatGPTさんの関数をさらにまとめてくれた感じで理想的です。

ただHTML部分の記述が丁寧すぎて長いですね。

違うパターンのコードも提示してくれる点と解説が丁寧な点は良いです。


生成AIによって回答が違うんで、やはり複数を活用した方が良さそうです。

そして、ある程度自分で回答が理解できる基礎知識は合った方がよいですね。



スプレッドシートに挿入した図形(ボタン)をクリックしたら指定のWebサイトを開く

最もシンプルな、Copilotのコードに、ChatGPTやClaudeで使われているダイアログを閉じるコード

google.script.host.close()

これを追加したコードを使ってみましょう。



GASでハイパーリンクボタンを作るコード

というわけでAIの いいとこ取りなコードです。

function openUrl() {
  cost url = "https://www.yahoo.co.jp/"; // 開きたいURLを指定
  const html = HtmlService.createHtmlOutput(
    `<script>
      window.open('${url}', '_blank');
      google.script.host.close();
    </script>`
  );
  SpreadsheetApp.getUi().showModalDialog(html, url+"を開くよ・・・");
}

こちらのコードをコピーして、スプレッドシートの メニューから

拡張機能 > Apps Script でエディタを開き、もともと入ってた

function myFunction() {
}

👆これを削除して貼付けして保存(保存ボタンを押す)

図形描画で適当な図形を挿入してボタンとして、三点リーダーから「スクリプトを割り当て」を開き、先ほど保存した関数名 openUrl を貼付け。

※大文字、小文字を区別するので注意
※() はつけない

ボタンを押すと 初回だけはスクリプトの認証が必要となるので、自分のアカウントを選択して「許可」しましょう。

これで準備はOK。実際にボタンを押すと

別タブで指定したURLのWebサイト(Yahoo)が開きましたね。完成です。

ちなみに 別タブではなく、別ウィンドウで開きたい場合や別ウィドウのサイズなどを指定する場合は、windows.open の第3引数で指定できます。

サイズ等の細かい指定を気にしなければ

function openUrl() {
  const url = "https://www.yahoo.co.jp/"; // 開きたいURLを指定
  const html = HtmlService.createHtmlOutput(
    `<script>
      window.open('${url}',null,'popup');
      google.script.host.close();
    </script>`
  );
  SpreadsheetApp.getUi().showModalDialog(html, url+"を開くよ・・・");
}

window.open() の第2、第3引数を null, 'popup'  指定でOK



コード解説 少しだけ(AI活用)

コード解説もAIに聞けば済むんで少しだけ。

まず、AI回答だと 別ファイルでHTMLを用意するコードもありましたが、モーダルダイアログで使う HTMLはぶっちゃけJavaScriptだけあればいいんで、別ファイルにするほどでもないってことでGASのコード内に記述

それが

    `<script>
      window.open('${url}', '_blank');
      google.script.host.close();
    </script>`

この部分ですね。

このコード内の文字列をHTMLとして読み込む場合は、HTMLServie クラスのcreateHtmlOutput() を使います。

幾つかあるHTMLServie のメソッドの使い分けも AIに聞いちゃうのが簡単です。

で、HTML部分をGAS内でテキストで記述する必要があるんで、scriptタグの前後をクォートで括る必要があるんですが、 windows.open の第1引数 URLも シングルクォートかダブルクォートで 括る必要があります。

'<script>window.open("' + url + '", "_blank");</script>'

仮に全体をシングルクォートで括って変数urlを使う場合、このようにちょっと煩雑になっちゃいます。

これを回避してシンプルに記述する為に、バッククォート ` を使ったテンプレートリテラルを活用すると良いです。

Claudeの回答のコードもコレを使ってますね。

バッククォートで括ることで内部のシングルクォートやダブルクォートはそのまま機能しますし、${url} と記述することで 変数 url を呼び出すことも出来ます。

  windows.open で指定したURLのWebサイトを(別タブ)で開いたら、ダイアログは用済みなんで閉じたいので、

google.script.host.close()

これが必要になります。

とりあえず AIだけでも実現できるお題でしたが、ある程度自分に知識があれば、さらにいい感じにコードが修正出来て、コードの理解も深まるってわけです。

ちなみに mirは今回のコードは以前 teratail で見かけて知っていたんですが、AIの回答のベースもたぶんコレなんじゃないかと思います。



【応用】GASでスプレッドシートの範囲指定PDFダウンロードボタンが作れる

今回紹介した別タブで指定したURLを開くGAS、

そして、こちら👆の 以前のnoteで紹介したスプレッドシートのPDFダウンロードURLを生成するGAS(カスタム関数)

この2つのコードを ちょっと修正して組み合わせると、スプレッドシートの指定範囲をPDFでダウンロードするボタンが GASで実装できます。



スプレッドシートの指定範囲 PDFダウンロードボタン用コード

//指定したURLを別タブで開く(ダウンロードする)関数
function sheetPdfDownload() {
  const url = pdfLink(); //PDFダウンロード用のURLを取得
  const html = HtmlService.createHtmlOutput(
    `<script>
      window.open('${url}','_blank');
      google.script.host.close();
    </script>`
  );
  SpreadsheetApp.getUi().showModalDialog(html, "Download...");
}


//pdfリンク生成関数
function pdfLink(){
  //設定
  const range = "A1:K36"; //第1引数 セル範囲指定:省略時はデータ範囲
  const size = 'A4'; // 第2引数 用紙サイズ:省略時はA4
  const portrait = true; // 第3引数 用紙の向き:省略時はTRUE (縦)

  const ss = SpreadsheetApp.getActiveSpreadsheet(); //開いているスプレッドシート
  let url = ss.getUrl(); //スプレッドシートからURLを取得

  const sheet = ss.getActiveSheet(); //開いてるシート
  const sheetId = sheet.getSheetId(); //シートIDを取得

  //PDF化オプション設定
  let options ={

    'format': 'pdf',
    'gid': sheetId, //対象シート:関数が入ってるシート
    'range': range, //対象範囲:指定なしはデータ範囲
    'size': size, // 指定なしは:A4
    'portrait': portrait, // 用紙の向き:指定なしは縦
    'scale': 4, // 縮尺:ページに合わせる (1:標準100%、2:幅に合わせる、3:高さに合わせる、4:ページに合わせる)
    'horizontal_alignment': 'CENTER', // 水平方向:中央
    'gridlines': false, // 罫線:非表示
  
  }

  options = Object.keys(options).map(key => `${key}=${options[key]}`).join('&'); //オプションを連結

  //URL生成
  url = url.replace("edit","export?") + options ;

  return url;
}

今回の指定したWebサイトを開く関数を修正した sheetPdfDownload()、そして開いているシートの指定範囲をPDFにするURLを生成する pdfLink()、この 2つの関数を使います。

過去 noteで紹介した PDF化URL生成のカスタム関数 pdfLink() を少し修正して コード内で 範囲、用紙サイズ、向きを設定。

実際にURLを開く(ダウンロードする)関数 sheetPdfDownload() の方のURL指定の記述を

 const url = pdfLink(); //PDFダウンロード用のURLを取得

としています。

sheetPdfDownload を図形にスクリプト設定してGAS実行ボタンにして試してみましょう。

ボタンを押すだけで、開いているシートの指定範囲(提出用見積書の範囲)をPDF化したファイルがダウンロード出来ました~。

一瞬ダイアログ、別タブは開くものの、どちらも自動で閉じて開いていたスプレッドシートの画面に戻るのもいい感じです。

Chromeのダウンロード設定で、毎回保存先を確認する設定としている場合はも1アクション必要ですが、

とりあえず、こんな機能が欲しかったって人もいるんじゃないでしょうか?


ただし先ほども書きましたが、GASは実行ユーザー単位で初回に権限を求められる仕様です。

ユーザー毎に初回は必ず スクリプトの認証が必要となるので、そこは周知する必要があります。

というわけで、個人的には

GAS → ダイアログ起動 → JavaScript実行

で出来ることが広がるという知識は持っておいて損はないですが、

Webサイトを開いたり、ダウンロードしたりは、わざわざボタンにこだわらず、普通にハイパーリンク使えばよいんじゃない?と思います。

ボタンの画像をセル内画像に設定してハイパーリンクにする。こんな小技でそれっぽい感じにする方法もありますしね。



シンプルな処理のGASは、ある程度AIでなんとかなる。でもアレンジするには知識は必要

今回は、GASを使ってスプレッドシートのボタンで Webサイトを開いたり、ダウンロードしたりする方法を紹介しました。

ちなみに Webサイトを開くコードは、3つのAIが動作するコードを回答してくれましたが、応用で紹介した開いているシートの指定範囲をPDFダウンロードするコードは、いずれのAIも ダウンロードではなく Googleドライブに保存するコードを返してきました。

Claudeだけはローカルに保存する方法を教えてくれって言ったら、今回初回のコードに近いものを返してくれましたが。。(他のAIも複数回やりとりをすれば、目的のものにたどり着けるかもしれません)

まるで知識無くても、もちろん使えるケースはありますが、やぱり生成AIでプログラミングコードを作ってもらう時は

  • 複数使って回答を比較する

  • 数ターンやりとりして希望に近づけていく

  • コードのわからないところを解説してもらう

こんな使い方で自分自身のGASの知識も上げていくのがいいかなと思います。

2025年はさらに AI活用が加速しそうですが、上手に付き合っていきたいですね。

AIはラーメンを食ってるんじゃない情報を食ってるんだ!

この noteもAIに食われることになるんかなー・・・。

今回のような過去noteでチラッと触れて、機会があれば詳しく紹介したいで放置しているネタが幾つかあるので、ボチボチ伏線回収もしていきたいと思います。

とりあえず、来週のネタは未定です。


いいなと思ったら応援しよう!

mir
チップ大歓迎です。やる気がアップしますw