質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

ドキュメント

ドキュメントは、IT用語では、ソフトウェアやハードウェアに関する情報であり、意図された目的、機能性、メインテナンスを含みます。ドキュメントは、多くの様々なフォームとフォーマットに存在しますが、その目的は常に教育することにあります。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

Q&A

解決済

1回答

1836閲覧

GoogleドキュメントへGASのサイドバーから装飾済みの本文などをカーソル位置へ挿入したい

kikuchi33

総合スコア12

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

ドキュメント

ドキュメントは、IT用語では、ソフトウェアやハードウェアに関する情報であり、意図された目的、機能性、メインテナンスを含みます。ドキュメントは、多くの様々なフォームとフォーマットに存在しますが、その目的は常に教育することにあります。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

0グッド

0クリップ

投稿2020/07/19 13:16

編集2020/07/19 14:17

##やりたいこと

Googleドキュメントを使っています。

GASで作ったサイドバーに設置した画像やテキストのリンクをクリックすることで

●装飾設定もした見出し1&本文のセット
●装飾設定もした表(表内に本文などの値も含む)
●指定した描画ファイル

これらの予めセットしておいた情報を
カーソルの置かれている場所へ挿入したいと考えています。

##試したこと

https://tonari-it.com/gas-sidebar-document-cursor-insert/
こちらを元にGASで作ったサイドバーのテキストフィールドに
入力したテキスト情報をカーソル位置に挿入はできました。

##知りたいこと

1.予め登録しておいた装飾済みの見出し・本文セットや表等の情報をGASサイドバーからカーソル位置へ挿入する方法
2.そもそも上記が技術的に可能なのかどうか

GASを使ったサイドバーの情報が
とにかく日本語に少なくてこれ以上自分で調べられないため
質問をさせていただきました。

ご存じの方がいらっしゃればお知恵をお貸しいただければ幸いです。
よろしくお願いいたします。

###追伸 2020/07/19 23:16
関連する単語で検索を進めております。
英語が読めないので自動翻訳頼りですが、
https://stackoverrun.com/ja/q/11664878
こちらがなんとなく関係しそうかなと読み進めて、
https://developers.google.com/apps-script/guides/docs#structure_of_a_document
こちらのページに辿り着きましたが、やはり理解はできませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

draq

2020/07/20 06:11

サイドバーからドキュメンを操作する処理を起動する部分はわかるということでいいんでしょうか。 あとドキュメントのデータ構造についてはどこまでご存知ですか?
kikuchi33

2020/07/21 00:13

お返事ありがとうございます。 https://tonari-it.com/gas-sidebar-document-cursor-insert/ こちらで紹介されているコードをテストファイルへ追加し 上記記事の動作を確認した程度で、内容まで理解ができておりません。 そのためサイドバーからドキュメントを操作する処理を起動する部分や ドキュメントデータ構造については全く把握していない状況です。
draq

2020/07/21 03:14 編集

そこが理解できてないのにそれ以上の機能の実装方法を質問するのは、丸投げ(改造依頼)ではないでしょうか。 リッチテキストとして挿入する場合は、挿入先の要素別に処理を分岐させたりする必要があるので、たとえ回答したとしても理解できるとは思えません。実装も動作確認もかなり面倒ですし。 まずはリンク先の内容を読んで、理解できないことに絞って質問された方がいいと思います。 > 2.そもそも上記が技術的に可能なのかどうか 可能です。細かい組み合わせを無視しましたが一応簡単な実装はして確認しました。
guest

回答1

0

ベストアンサー

コメントでは厳し目なこと書きましたが、一応確認で書いた中途半端なコードは書いておきます。
メニューに「マクロ」が追加されるので、実行するとサイドバーが表示されます。

事前準備:

  • Google ドライブに挿入するテンプレートを保存するフォルダを作成する。
  • 上記フォルダにテンプレートとなるドキュメントを保存する。

制限事項:

  • Paragraph の中にカーソルがある場合は、正常に動作しません。
  • テキスト、テーブル、インラインイメージしか考慮してません。

JavaScript

1const ui = DocumentApp.getUi(); 2 3function onOpen() { 4 ui.createMenu("マクロ").addItem("showSidebar", "showSidebar").addToUi(); 5} 6 7function showSidebar() { 8 const files = (() => { 9 const templateFolder = DriveApp.getFolderById( 10 "(テンプレートとなるドキュメントファイルを保存するフォルダID)" 11 ); 12 13 const iterator = templateFolder.getFilesByType( 14 "application/vnd.google-apps.document" 15 ); 16 const result = []; 17 while (iterator.hasNext()) { 18 const file = iterator.next(); 19 result.push({ id: file.getId(), name: file.getName() }); 20 } 21 return result; 22 })(); 23 24 const template = HtmlService.createTemplateFromFile("Sidebar"); 25 template.files = JSON.stringify(files); 26 const htmlOutput = template.evaluate(); 27 ui.showSidebar(htmlOutput); 28} 29 30function insertDocument(fileId) { 31 try { 32 const insertBody = DocumentApp.openById(fileId).getBody(); 33 34 const doc = DocumentApp.getActiveDocument(); 35 const position = doc.getCursor(); 36 const element = position.getElement(); 37 const parent = element.getParent(); 38 let index = parent.getChildIndex(element); 39 40 const parentType = parent.getType(); 41 const offset = position.getOffset(); 42 const surroundingText = position.getSurroundingText().getText(); 43 const surroundingTextOffset = position.getSurroundingTextOffset(); 44 45 46 if (parent.getType() === DocumentApp.ElementType.PARAGRAPH) { 47 const parentParagraph = parent.asParagraph(); 48 for (let i = 0; i < insertBody.getNumChildren(); i++) { 49 const child = insertBody.getChild(i); 50 if (child.getType() === DocumentApp.ElementType.PARAGRAPH) { 51 const paragraph = child.asParagraph().copy(); 52 if (paragraph.getNumChildren() !== 0) 53 parentParagraph.insertParagraph(index++, paragraph); 54 } else if (child.getType() === DocumentApp.ElementType.INLINE_IMAGE) { 55 parentParagraph.insertInlineImage( 56 index++, 57 child.asInlineImage().copy() 58 ); 59 } else if (child.getType() === DocumentApp.ElementType.TABLE) { 60 parentParagraph.insertTable(index++, child.asTable().copy()); 61 } 62 } 63 } else { 64 for (let i = 0; i < insertBody.getNumChildren(); i++) { 65 const child = insertBody.getChild(i).copy(); 66 if (child.getType() === DocumentApp.ElementType.PARAGRAPH) { 67 const paragraph = child.asParagraph(); 68 if (paragraph.getNumChildren() !== 0) 69 parent.insertParagraph(index++, paragraph); 70 } else if (child.getType() === DocumentApp.ElementType.INLINE_IMAGE) { 71 parent.insertInlineImage(index++, child.asInlineImage().copy()); 72 } else if (child.getType() === DocumentApp.ElementType.TABLE) { 73 parent.insertTable(index++, child.asTable().copy()); 74 } 75 } 76 } 77 78 step = "complete"; 79 } catch (ex) { 80 ui.alert("error = " + JSON.stringify(ex, null, 2)); 81 } 82}

HTML

1<!DOCTYPE html> 2<html> 3 <head> 4 <base target="_top"> 5 <title>Sidebar</title> 6 <style> 7 body { text-align:center; } 8 button[type=button] { 9 width: 250px; 10 height: 50px; 11 margin-bottom: 10px; 12 } 13 </style> 14 <script> 15 window.addEventListener("DOMContentLoaded", () => { 16 const body = document.querySelector("body"); 17 const files = JSON.parse("<?=files?>"); 18 files.forEach(file => { 19 const button = document.createElement("button"); 20 button.setAttribute("type", "button"); 21 button.textContent = file.name; 22 button.value = file.id; 23 button.addEventListener("click", () =>{ 24 google.script.run 25 .withSuccessHandler(() => {}) 26 .withFailureHandler(error => console.log(error)) 27 .insertDocument(file.id); 28 } ); 29 body.appendChild(button); 30 }); 31 }); 32 </script> 33 </head> 34 <body> 35 <h3>テンプレート挿入</h3> 36 </body> 37</html>

投稿2020/07/21 03:44

draq

総合スコア2577

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kikuchi33

2020/07/21 09:15

お忙しいところご回答いただき、 誠にありがとうございました。 日本語で検索しても、 装飾込みのテキストや表などの サイドバーからワンクリックで挿入することが そもそも技術的に可能かどうかすら分からなかったため、 こちらに質問を投稿させていただきました。 日頃から実装させたいことを検索して 出てきたサンプルコードを一部編集したりカスタマイズするなどしているため おっしゃる通りまだまだ技術がなく、 このような質問の仕方しかできず、大変申し訳ございませんでした。 回答いただいたコードを使わせていただきました。 まさにイメージ通りの動きをしております。 技術的に可能なのですね。 質問の仕方も悪かったのにも関わらず お忙しいところ誠にありがとうございました。 技術的に可能ということを教えていただきましたので 投稿いただいたコードを元にどのような処理をしているかを勉強させていただきます。 誠にありがとうございました。
draq

2020/07/21 18:25 編集

イメージ通りとのことですが、回答にも書いたように実装は中途半端です。 1行文字列の中にカーソルがある場合はエラーになります。未確認ですが、リストに対しても対応してませんので利用には注意してください。 完璧に実装する場合は、(カーソル位置にあり得るオブジェクトの種類数)×(テンプレートに存在しうるオブジェクトの種類数)の組み合わせの実装が必要になるため、割と大変です。 回答のコードでは、カーソル位置にあり得るオブジェクトを Paragraph とそれ以外しか分岐してませんが、本当にそれで十分かもよく検討が必要です。
kikuchi33

2020/07/22 00:24

ありがとうございます。 はい、段落内にカーソルがある場合などいくつかのケースでエラーが出ておりました。 段落内にカーソルがある場合は、カーソルのある段落の終了箇所(次の段落との間)に 挿入ができないかと考えております。 仕様上、技術的に可能であることがわかっただけでとてもありがたいです。 可能性が見えました。 誠にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問