Google Apps ScriptでDocumentのテーブルの値を読み書き【GAS】
Googleドキュメントのテーブルの値を書き換えたい。そんな要望はちょっとだけあります。とりわけ差込印刷をしてしまうと元の差込コードが消えてしまう為、それを復元したいのに復元するとドキュメントのレイアウトが崩れる。そんな時に思いついたのがこの手法。
予めテーブル構造の値をJSONなどで取っておいて、初期化時には復元する手法として使えれば、ドキュメントを上書きなんてトリッキーな手法を使わずに済むわけです。
今回利用するドキュメント
- テーブルの値を取得する - Google Document
Google Documentのテーブルの値を読み書きするスクリプトです。もともとはPDFを生成する際にドキュメントの中身を元に戻す手段として考案したもので、テーブルで構成されたドキュメント内の様々なテーブルの中身を取得したり、復元したりを考えています。
※わざわざドキュメントでやってる理由は、印刷時の余白の制御がスプレッドシートでは出来ない点。レイアウトの自由はスプレッドシートのほうが遥かに高いのですが、ドキュメントのほうが印刷時の見た目どおりに印刷してくれるので帯に短したすきに長しなのです。
ソースコード
テーブルの中身を取得する
取得するコード
getTablesにて上から順番にテーブル単位で取得。その後、テーブルの中身の行数と列数を取得し、それぞれを複数のループにてgetTextで値を取得する。非常に単純なのですが、ドキュメントでは値の場所を特定する手段がとても難しいので、この手法があれば値を簡単に入れたり出したりが可能になります。
スプレッドシートよりも複雑ですが利用する価値は大いにあるのでは?
※セルの結合をした場合、例えば一番左列だけ縦に結合をした場合、その値は1行目だけに入っており、2行目以降はその列の値は空で出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
//複数のテーブルの値を取得してみる function getTableValues() { //ドキュメントとテーブルを取得する var doc = DocumentApp.getActiveDocument(); var body = doc.getBody(); var tables = body.getTables(); //テーブルを回していく for(var i = 0;i<tables.length;i++){ //テーブルを取得する let table = tables[i]; //対象テーブルのレコード件数を取得する let numRows = table.getNumRows(); let numColumns = table.getNumChildren(); //2行目から値を取得して表示 let array = []; //行を精査 //タイトル行はスルーするので1から開始 for(var j = 1;j<numRows;j++){ //行用の配列を用意 let temparr = []; //列を精査 for(var k = 0;k<numColumns;k++){ //セル値を取得する let val = table.getCell(j, k).getText() //値をtemparrに追加する temparr.push(val); } //temparrの値をarrayにpush array.push(temparr) } //arrayの値を表示 console.log(array) } } |
図:テーブルのデータの事例
図:取得してみた様子
注意点
これもバグなのか、1行だけのテーブルや複雑な結合をしてる場合正しいカラム数が取れない症状があるので、自分の場合特定のテーブルだけカラム数補正を入れるようにしています(getNumChildrenがその原因)。
以下の図のような表形式がそれになります。なるべく複数行でセルの結合を使用しないようにしましょう。
図:トラブルの原因となる表の形式
テーブルの中身を書き換える
配列で用意しておいた値の塊を持って、ドキュメントのテーブルの中身を書き換えます。同じ形式同じ数だけ用意しておく必要があります。changemanという配列データを使って既存のテーブルの値をsetTextでリプレースします。restoreというデータに変えれば元通り。
1行目はタイトル行なのでそれをスキップしつつであるため、配列用のカウンターを別途用意しています。
※フォントや書式(センタリングなど)は変更されないので、変更前の状態を保持します。
※但しセルの文字部分だけじゃなくそのセル全体に書式設定をする必要があり、していない場合書式が解除されることがあります。また、一部の文字だけ書式設定しても解除されたり前の文字のフォントが継承されます。複雑な書式設定はしないようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
//テーブルの値を1個目テーブルだけ書き換える function setTableValue(){ //ドキュメントとテーブルを取得する var doc = DocumentApp.getActiveDocument(); var body = doc.getBody(); var tables = body.getTables(); //テーブルを回していく for(var i = 0;i<tables.length - 1;i++){ //テーブルを取得する let table = tables[i]; //対象テーブルのレコード件数を取得する let numRows = table.getNumRows(); let numColumns = table.getNumChildren(); //利用するデータを選択 let array = changeman; //行を精査 //カウンタを初期化 let counter = 0; //タイトル行はスルーするので1から開始 for(var j = 1;j<numRows;j++){ //列を精査 for(var k = 0;k<numColumns;k++){ //セル値をセットする table.getCell(j, k).setText(array[counter][k]) } //カウンタを加算 counter = counter + 1; } } //ドキュメントを保存する doc.saveAndClose(); } //セット用テーブル値 var changeman = [ ["1006","バナナ","フルーツ","200","絶滅危機らしい"], ["1007","しいたけ","キノコ","150","苦手"], ["1008","ターサイ","野菜","130","中国産"], ["1009","マンゴスチン","フルーツ","320","女王様"] ] //復元用 var restore = [ [ '1001', 'たまご', '一般食品', '250', '高くなった' ], [ '1002', 'パイン', 'フルーツ', '380', '台湾産が良い' ], [ '1003', 'たまねぎ', '野菜', '150', 'しんたま' ], [ '1005', 'ドリアン', 'フルーツ', '700', '臭い' ] ] |
図:1つ目のテーブルの中身だけ書き換えてみた