LoginSignup
18
25

More than 5 years have passed since last update.

RubyでGoogle Drive/スプレッドシートを扱う

Posted at

@koshi_life です。

GoogleDrive上で教師データ作成のためのラベル付作業を行いたく、
Rubyでフォルダやスプレッドシートの扱い方を調べたので備忘します。

利用ライブラリ

Rubyだと Google製の公式ライブラリ googleapis/google-api-ruby-client も提供されていますが、情報が比較的多く、シンプルで使いやすかったのを理由に gimite/google-drive-ruby を選びました。

前提

  • ruby: v2.6
  • google-drive-ruby: v3.0.2

利用準備

  • GCPの利用プロジェクトの APIコンソール画面で Drive APIGoogle Sheets API を有効化
  • 認証キー(OAuth クライアント ID)を作成 参考:Authorizationのページ
    • ドキュメントオーナーは個人にしたくなったので、コマンドラインでの実行ユーザも兼ねてGoogleユーザを作成。サービスアカウント認証も対応していたが、各ドキュメントのサービスアカウントに対してシェア設定が必要になるので OAuth クライアント IDでの認証とした。

client_id, client_secret を手に入れたら、以下キーを持つjsonを作成する。

config.json
{
    "client_id": "xxx.apps.googleusercontent.com",
    "client_secret": "xxx"
}

Gemファイルに以下、1行を追加して、bundle install でライブラリをインストールする。

gem 'google_drive'

使い方

少しづつコードに継ぎ足しをしながら理解を深めます。

Step1: 初回実行時に認可、リフレッシュトークンを取得

hello1.rb
require 'google_drive'

session = GoogleDrive::Session.from_config('config.json')

2行のみGoogleDrive::Sessionの初期化まで書きました。
実行してみます。

$ bundle exec ruby hello1.rb

1. Open this page:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=xxx.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/drive%20https://spreadsheets.google.com/feeds/

2. Enter the authorization code shown in the page: [★☆★☆★ここに貼り付け★☆★☆★]

ユーザ認証用のURLが表示されるのでブラウザで開き認可します。
auth-google.png
最後の画面のコードをコンソールに貼り付けてEnter押下で完了です。

実行後 config.json を見ると、
scoperefresh_token の項目が追加されていることがわかります。
スコープの内容はこちら参照。

config.json
{
  "client_id": "xxx.apps.googleusercontent.com",
  "client_secret": "xxx",
  "scope": [
    "https://www.googleapis.com/auth/drive",
    "https://spreadsheets.google.com/feeds/"
  ],
  "refresh_token": "xxx"
}

2回目の実行からはブラウザ開いて認証&認可は不要になります。
ライブラリ側でこのリフレッシュトークンを元にアクセストークンが作られ、APIアクセスしていると思われる。

Step2: 何も考えずファイル一覧

一旦動いている感を得たいので、session 取得後に1行追加して実行してみる。

hello2.rb
require 'google_drive'

session = GoogleDrive::Session.from_config('config.json')
session.files.each { |file| p file.title }
$ bundle exec ruby hello2.rb 
"a"
"b"
"c"
...

動いている感を得られました。

Step3: サブフォルダを作ってみる

hello3.rb
require 'google_drive'

session = GoogleDrive::Session.from_config('config.json')

# Google DriveでFolderを選択した時のURLの末尾のハッシュ値
# 例: https://drive.google.com/drive/folders/xxx_xxx_xxx
root_folder_id = 'xxx_xxx_xxx'
sub_folder_name = 'hello_sub_folder'

root_folder = session.collection_by_id(root_folder_id)
sub_folder = root_folder.create_subfolder(sub_folder_name)

puts "SUBFOLDER: #{sub_folder.human_url}"
$ bundle exec ruby hello3.rb 
SUBFOLDER: https://drive.google.com/drive/folders/yyy_yyy_yyy

表示されたURLを開くとフォルダが作られていることが確認できます。

Step4: 任意のファイルを指定フォルダにアップする

アップロード対象のファイル hello_upload.txt
指定のフォルダに配置するところまでやってみます。

$ cat hello_upload.txt
Hello Google Drive API
hello4.rb
require 'google_drive'

session = GoogleDrive::Session.from_config('config.json')

# Title 指定、Google Documentに変換しない でアップロード
file = session.upload_from_file('hello_upload.txt', 'hello.txt', convert: false)
puts "FILE: #{file.human_url}"

# サブフォルダへ配下に移動
sub_folder_id = 'yyy_yyy_yyy'
sub_folder = session.collection_by_id(sub_folder_id)
sub_folder.add(file)

Content-type 指定などもできるらしい。
詳細は Session:upload_from_file 参照

Step5: スプレッドシートのテンプレートをコピーして値を入れる

よくあるデータ加工業務のパターン。
テンプレートのスプレッドシートを用意しておき、シートをコピーして値を入れるといった内容。

例として、クラスごとの身体測定結果を管理するデータシートを作る業務をイメージして
テンプレートを作りました。

テンプレ データ投入後
Screen Shot 2019-04-07 at 0.37.28.png Screen Shot 2019-04-07 at 0.36.44.png
hello5.rb

# テンプレートデータシートから任意のシート名、任意フォルダにシートをコピー
def copy_sheets(sheets_name, template_sheets, root_folder, sub_folder)
  sheets = template_sheets.copy(sheets_name)
  sub_folder.add(sheets)
  # テンプレートファイルと同じフォルダにも新シートの参照が残るので削除しておく
  root_folder.remove(sheets)
  sheets
end

# シートのデータを更新
def update_sheets(sheets, rows)
  top = 10 # データ投入位置 top
  left = 2 # データ投入位置 left
  work_sheet = sheets.worksheets[0]
  work_sheet.update_cells(top, left, rows)
  work_sheet.save
end

# ランダムデータの作成
def generate_random_data
  rows = []
  (1..20).each do |index|
    sex = rand(1..2)
    height = rand(140..200)
    weight = rand(40..100)
    rows << [index, sex, height, weight]
  end
  rows
end

# テンプレートファイルの置いてあるフォルダ
root_folder_id = 'xxx_xxx_xxx'
root_folder = session.collection_by_id(root_folder_id)

# データを配置したいフォルダ
sub_folder_id = 'yyy_yyy_yyy'
sub_folder = session.collection_by_id(sub_folder_id)

# テンプレートシート
template_sheets_id = 'zzz_zzz_zzz'
template_sheets = session.spreadsheet_by_key(template_sheets_id)

# 3年A組のシート作成
sheets_3a = copy_sheets('2019_3年A組', template_sheets, root_folder, sub_folder)
data_3a = generate_random_data
update_sheets(sheets_3a, data_3a)

# 3年B組のシート作成
sheets_3b = copy_sheets('2019_3年B組', template_sheets, root_folder, sub_folder)
data_3b = generate_random_data
update_sheets(sheets_3b, data_3b)

参考

18
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
25