« FLECT OSS Libraryが公開になりました。 | メイン | herokuにSQLを実行するプラグインを作成する »

2013年7月 2日 (火)

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」を指定する)方法があるらしいことはわかってはいたんです。

が、これ途中でも試してたんですが何故かうまく動きません。検索結果にも「動かねー」という怨嗟の声が山ほどあるし、公式ドキュメントにもそれができるという記述が見つけられないので結局この方向もあきらめました。。。(--

 

★できないはずがないとあがく

手詰まりです。

絶対に必要と言う機能でもないし、もうあきらめようかとも思ったんですがこんな簡単なことができないということがどうしても信じられず検索を続けました。

そして。。。ついに、見つけた解答がこれです。

http://stackoverflow.com/questions/11290337/how-to-convert-google-spreadsheets-worksheet-string-id-to-integer-index-gid

一番最後にコード例が載っていますが、要約するとこうです。

 

  1. WorksheetEntry#getIdから最後の「/」以降の3桁を取得する
  2. その文字列を36進数として数値に変換する
  3. その数値と31578のXORを取るとgidが取得できる

 

。。。(--

。。。。。(--;;;

。。。できた。。。できたけどっ!

36進数って何だよ?!31578は一体どこから出てきた???

長くこの業界にいるけど、こんなの初めて見たよ!!!

動きはしたけどなんだか全然釈然としない。誰かこのアルゴリズムの根拠の分かる人がいたら教えてください。m(_ _)m

コメント

36進数ということは、大文字小文字を区別しない英数字ということですかね。
昔大文字小文字を区別する英数字による62進数を使ったことはあります。

ありがとうございます。まったく同じことを考えていました。
http://webapps.stackexchange.com/questions/24924/link-to-specific-sheet-in-google-spreadsheet とか

http://www.faqoverflow.com/webapps/24924.html 

を参考にして作ってみましたが、
やはりUIから得ることができず、手書きで一覧を作りvlookupで表示させて UIにリンク貼る方法にしました。こちら参考にして、また考えてみます。

google script では、 getId()というのが、gid= 以下の数字の部分を取得できるスクリプトでした!

どうやればよいのかわからなかったので、勉強になりました!

この記事生きてますか?
少し違うかも知れませんが、同じようなことを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が完成します。
以上参考までに。

コメントを投稿

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart