Google Spreadsheetで特定のシートに直リンクする
こんにちは
昨日からGoogle Spreadsheet APIで作成したシートに直リンクするURLを生成したくて色々調べてました。
「API使うならそれくらい簡単にできるんじゃないの?」って思うでしょ?えぇ、僕もそう思いました。
しかし、これが。。。(--
一応最終的にはできたんですが、その方法が「マジですか?!」とかなり愕然とするものだったのでここにメモとして残しておきます。
★Google SpreadsheetのURL
実際にシートを作ってみながらブラウザのアドレスバーを確認するとすぐにわかりますが、GoogleSpreadsheetのURLは以下のような形式となっています。
https://docs.google.com/spreadsheet/ccc?key=xxxxxxxx#gid=1
アカウントが組織に属している場合は若干URLのパスが変わりますが、ここで重要なのは
- URLパラメータの「key」がスプレッドシートを特定するキーとなっている
- URLパラメータの「gid」がワークシートを特定するキーとなっている
という点です。ちなみにgidはおそらく単純にシートの作成順による連番です。途中でワークシートの削除や移動があった場合でもgidが振り直されることはなく単純なインクリメントで生成されます。
要するにAPIでこのkeyとgidが取得できれば、URLを組み立てることができるわけです。楽勝です。
★Google Spreadsheet APIを使う
今回アプリはPlay2で作成しているのでJavaのAPIを使用しました。Google Spreadsheet APIの使い方については良記事がたくさんあるので割愛しますが、スプレッドシート、ワークシートの情報はそれぞれ、
- SpreadsheetEntry
- WorksheetEntry
というクラスから取得できます。
これらのAPIリファレンスを眺めると目的とする情報はそれぞれ
- SpreadsheetEntry#getSpreadsheetLink
- WorksheetEntry#getId
というメソッドから取得できそうです。楽勝です。
★gidが取れないことに気がつく
さて、ここまで来たら後は試すだけですがまず、SpreadsheetEntry#getSpreadsheetLinkは完全に目的にマッチするものでした。keyだけでなくスキームから始まる完全なURLとして取得できます。楽勝楽勝(^^v
が、WorksheetEntry#getIdの方はgidではなく、こちらも「https://...」で始まるURIでした。そもそもgetIdメソッドはWorksheetEntryクラスのメソッドではなく、その基底クラスであるBaseEntryクラスのメソッドなのでSpreadsheetだけでなく他のGoogle Appsオブジェクトまで全部含めたIdentifierになっているわけです。同一のスプレッドシート内でのみユニークとなるgidとは意味合いが異なります。
それではgidはどうやって取得するのかと言うと。。。これはいろいろと試行錯誤したんですが、どうもそのためのメソッドは無いようでした。(--
最終的にはRESTのレスポンスXMLの中にそれっぽい値が入っていないことから、どうやら本当に無いらしいと結論しました。
★シート名でのリンクを試みる
APIでgidが取れないとなると、どうやって直リンクすれば良いのでしょうか?シートの削除や移動があるのでgidは単純な連番とはなりません。世の中にGoogleSpreadsheetの特定シートに直リンクしたい人は山ほどいるはずです。
。。。と、あおってはみたものの実際のところはここまでにさんざん検索をかけているのでシート名でリンクする( = URLパラメータに「sheet=xxxxx」を指定する)方法があるらしいことはわかってはいたんです。
が、これ途中でも試してたんですが何故かうまく動きません。検索結果にも「動かねー」という怨嗟の声が山ほどあるし、公式ドキュメントにもそれができるという記述が見つけられないので結局この方向もあきらめました。。。(--
★できないはずがないとあがく
手詰まりです。
絶対に必要と言う機能でもないし、もうあきらめようかとも思ったんですがこんな簡単なことができないということがどうしても信じられず検索を続けました。
そして。。。ついに、見つけた解答がこれです。
一番最後にコード例が載っていますが、要約するとこうです。
- WorksheetEntry#getIdから最後の「/」以降の3桁を取得する
- その文字列を36進数として数値に変換する
- その数値と31578のXORを取るとgidが取得できる
。。。(--
。。。。。(--;;;
。。。できた。。。できたけどっ!
36進数って何だよ?!31578は一体どこから出てきた???
長くこの業界にいるけど、こんなの初めて見たよ!!!
動きはしたけどなんだか全然釈然としない。誰かこのアルゴリズムの根拠の分かる人がいたら教えてください。m(_ _)m
36進数ということは、大文字小文字を区別しない英数字ということですかね。
昔大文字小文字を区別する英数字による62進数を使ったことはあります。
投稿: ophidian | 2014年5月23日 (金) 11:28
ありがとうございます。まったく同じことを考えていました。
http://webapps.stackexchange.com/questions/24924/link-to-specific-sheet-in-google-spreadsheet とか
http://www.faqoverflow.com/webapps/24924.html
を参考にして作ってみましたが、
やはりUIから得ることができず、手書きで一覧を作りvlookupで表示させて UIにリンク貼る方法にしました。こちら参考にして、また考えてみます。
投稿: さいき | 2014年10月25日 (土) 22:08
google script では、 getId()というのが、gid= 以下の数字の部分を取得できるスクリプトでした!
投稿: さいき | 2014年10月26日 (日) 06:56
どうやればよいのかわからなかったので、勉強になりました!
投稿: passo | 2016年6月 6日 (月) 11:04
この記事生きてますか?
少し違うかも知れませんが、同じようなことをGoogle Apps Scriptで
実現しようとして、この記事に当たりました。
結論としては、Google Apps Scriptにてシートの直リンクURLの
生成が可能でした。
方法は以下の通りです。
// アクティブスプレッドシートオブジェクト
var Spread = SpreadsheetApp.getActive();
// URLを取得したいスプレッドシートオブジェクト
var Sheet = Spread.getSheetByName('シート名');
// アクティブスプレッドシートのeditまでのURLを取得できます。
Logger.log(Spread.getUrl());
// URLを取得したいシートのgidが取得できます。
Logger.log(String(Sheet.getSheetId()));
// 最後に、スプレッドシートのURLとシートのgidをの間に【#gid=】を結合させます。
Logger.log(Spread.getUrl()+'#gid='+String(Sheet.getSheetId()));
これで、指定シートの直リンクURLが完成します。
以上参考までに。
投稿: GAS使い | 2016年7月26日 (火) 17:03