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

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

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

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

Q&A

解決済

2回答

3020閲覧

GASで指定スプレットシートの全シートをアクテイブシートにコピーしたい

ishikoro.1234

総合スコア14

Google Apps Script

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

0グッド

0クリップ

投稿2019/05/17 08:52

編集2019/05/20 11:38

前提・実現したいこと

Google AppScriptで別のフォルダにあるスプレットシートを一つのスプレットシートにまとめたいので、スプレットシートのIDで当該のスプレットシートにある全シートを指定したいコピー先にコピーするコードを書きたいです。
もし可能であれば、シートをコピーしたあとにシート名にある(コピー)を削除し、スプレットシートの頭に新しいシートを作成し、全てシートの名前の一覧を作成したいです。
しかし、全シートをコピーしたかったので、自分なりにコードを変えてみましたが、今度はコードを起動しても何も起こらなかったです。
説明がわかりにくくて申し訳ございません。
まだまだ初心者なので、ご教授頂ければ幸いでございます。

該当のソースコード

function function_name() { var source = SpreadsheetApp.openById('元のファイルID'); var ss_num = new Array(); if (source.length >= 1) { for(var i = 0;i < source.length; i++) var sheet = source.getSheets()[i]; var destination = SpreadsheetApp.openById('コピー先ID'); sheet[i].copyTo(destination); } }

###シート名取得コード

function getname(sheet_no) { var name= SpreadsheetApp.getActive().getSheets()[sheet_no - 1].getName(); return name; }

###現在のコード

function q189933() { const destination = SpreadsheetApp.openById('コピー先ID'); SpreadsheetApp.openById('元のファイルID').getSheets().forEach( function(e) { e.copyTo(destination); } ); } function q189933_() { SpreadsheetApp.openById('コピー先ID').insertSheet('Sheet List', 0); var sheetlist = SpreadsheetApp.openById('コピー先ID'); var movesheet = sheetlist.getSheetByName('Sheet List'); sheetlist.setActiveSheet(movesheet); sheetlist.moveActiveSheet(1); } function q189933__() { const sheet = SpreadsheetApp.openById('コピー先ID').getSheetByName('Sheet List'); sheet.clear(); const dat = SpreadsheetApp.openById('コピー先ID').getSheets().map(function(e){return [e.getSheetName(), e.getSheetId()];}).filter(function(e){return e[0] !== 'Sheet List';}); sheet.getRange(1, 1, dat.length, 2).setValues(dat); }

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

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

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

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

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

papinianus

2019/05/17 10:35

シートidを得てもそれだけでシートを指定して開けるわけでもなくなんのためにそんなことがしたいのか書いていただけませんか? あと、コードは1シートだけコピーできていた、動くものでお願いしたいです。
ishikoro.1234

2019/05/20 03:37 編集

初めてこのサイトを使いましたので、至らない所が多くてすみません。 今回は異なるスプレットシートを一つのシートにまとめて、目次を作りたかったためのコードとなります。 この度は非常にわかりにくい説明にも関わらず、ご回答いただき誠にありがとうございます。 頂いた回答につきまして、自分なりに解析して見ましたが、理解できない箇所がございましたので、ご教授いただきたい箇所がございますので、回答頂ければ幸いでございます。 【自分なりの理解】 ご教授いただいたコードは3つの部分に分けており、1つ目はシートをコピー、2つ目はシート一覧を作成、3つ目はシート一覧にシート名及びIDを記入。 【不明な点】 ・function(e)の中にある「e」の意味はなんでしょうか、推測では何らかの変数だと思います ・map(function(e)...の部分について、推測では「e」の位置を特定するものだと思いますが、いまいち理解できなかったので、ご教授頂ければ幸いです。
papinianus

2019/05/20 09:51 編集

シートidはただの数字ですよ、確か。それのどこが目次として意味があるのですか? というかリンクにもならないそのidが目次に必要ですかね? (シート名の必要性は理解してます。これはteratail初心者とかプログラム初心者とか関係なく、ユーザ体験として聞きたい事項です)
ishikoro.1234

2019/05/20 10:02

お忙しい中、ご回答いただき誠にありがとうございます。 シートidは他のコードで使用する必要がある場合に備えて、シート一覧にまとめておきたいと思いました、たしかに必要がないかもしれません...。 業務上、翻訳するスプレットシートをいくついただくのですが、それらを一つのスプレットシートにまとめて、シート名の一覧及び文字数の統計が必要になります。 いつもは手作業でしたが、Google AppScriptの存在を知り、効率化を捗るために独学をしており、それでいくつのスプレットシートを一つのスプレットシートにまとめて、一覧表を作成するコードを書いてみました。 現在、コピーしたシート名には(コピー)の文字がついているので、そちらをを削除したいのですが、ご教授いただけないでしょうか。 コピーする際に名前を指定する関数は調べましたが、今回のように一括にコピーする場合はどのようにコピーの文字だけを削除できますか。 参考したコード:SpreadsheetApp.openById(コピー先ID).Copy("名前の指定")
papinianus

2019/05/20 10:20

例えばpdfにするとかだとidの出番があるかもしれません。あとはシートの場所を移動するとかなら。しかし移動するとidが変わる可能性があるのでこれも微妙。一般的にシート名がわかっているならそれに加えてidは不要に思えます。 コピーの、名前は調べて回答に追記します
guest

回答2

0

ベストアンサー

javascript

1function procedure() { 2 const dest = SpreadsheetApp.openById('コピー先ID'); 3 const sheetName = 'シート一覧'; 4 const folderName = '翻訳元_未コピー'; 5 pickSpreadsheetInFolderNamed(folderName).forEach(function (e) { copyAll(dest, SpreadsheetApp.open(e)); }); 6 resetSheetIndexSheet(dest, sheetName); 7} 8function pickSpreadsheetInFolderNamed(name) { 9 var files = []; 10 const folderIter = DriveApp.getFoldersByName(name); 11 while (folderIter.hasNext()) { 12 var folder = folderIter.next(); 13 var fileIter = folder.getFilesByType('application/vnd.google-apps.spreadsheet'); 14 while (fileIter.hasNext()) { 15 files.push(fileIter.next()); 16 } 17 } 18 return files; 19} 20function copyAll(destSpreadsheet, sourceSpreadsheet) { 21 sourceSpreadsheet.getSheets().forEach( 22 function (e) { 23 e.copyTo(destSpreadsheet).setName(e.getName()); 24 } 25 ); 26} 27function upsertSheet(spreadsheet, sheetName) { 28 const sheet = spreadsheet.getSheetByName(sheetName); 29 if (sheet !== null) { return sheet; } 30 return spreadsheet.insertSheet(sheetName, 0); //0が挿入位置を示しており、先頭。移動の必要はないと考えた(https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#insertSheet(String,Integer)) 31} 32function resetSheetIndexSheet(spreadsheet, sheetName) { 33 const sheet = upsertSheet(spreadsheet, sheetName); 34 sheet.clear(); 35 //const dat = spreadsheet.getSheets().map(function (e) { return [e.getSheetName(), e.getSheetId()]; }).filter(function (e) { return e[0] !== sheetName; }); 36 const dat = spreadsheet.getSheets().map(function (e) { return [e.getSheetName(),]; }).filter(function (e) { return e[0] !== sheetName; }); 37 sheet.getRange(1, 1, dat.length, dat[0].length).setValues(dat); 38}

投稿2019/05/18 18:03

編集2019/05/22 12:59
papinianus

総合スコア12705

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

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

papinianus

2019/05/20 10:00

質問者様の質問は3つの内容を含みます。一つずつしかできないので、分けて考えることを推奨します。 分け方はご推察の通りです。 無印の関数のeは具体的には各シートが入ります。シート1、シート2、などということです。なのでcopyToができます。 この書き方はforEachがcallbackを取るからですが、これを私の能力で平易に説明するのは不可能です。適宜参考書などを見てください。 __の関数のmapにあるeもシートが入ります。シートオブジェクトから名前とidを取り出して配列にしています。 さらにチェーンしたfilterでは直前で作った配列がeに入るのでそれの1つ目(0番)がシート一覧でないものにしています。目次に目次シートは含めないかなという想定です。 こちらもコールバックの概念が分からないと理解しづらいと思います。
ishikoro.1234

2019/05/20 11:38

お忙しい中、詳しく説明していただき誠に感謝致します。 機能につきましてはなんとなく把握していますがcallbackについての概念はまだないので、後ほど調べてみます。 詳しい説明を受けたあと、getsheetmynameなどで関数を使用できると思いますので確かにIDは不要と思いました。 また、いくつのスプレッドシートからシートをコピーする必要がありますので、作成したシート一覧をまとめ用のスプレッドシートの先頭に移動し、すべてのシート名の一覧を作成したいので、第2、第3部分を書き換える必要があると思いますので、コピーの名前も兼ねて、引き続きご教授いただければ幸いです。 第2部分は自分なりに、作成したシートを先頭に移動させるコードを作りましたので、質問欄の方に「現在のコード」の方に更新させていただきます。 第3部分につきましては、似たような関数を作ってましたが、それはシートの番号を指定する必要があるので、書き換えれば使えるかどう思いますので、「シート名取得コード」の方に記載させていただきます。 非常にわかり辛い説明及び何度もお手数をかけてしまい、誠に申し訳ございません。 引き続きご教授いただければ幸いと存じます。
papinianus

2019/05/21 00:31 編集

名前を元のシート名を引きつぐようにしました 移動は不要と考えます。もともと最初に入れる想定でインサート位置を指定しておりました 「シート名取得コード」ですがforでループすれば動くとは思います。しかし、google app scriptでは実行速度を気にする必要があるので採用できないです(どれくらいのシート数か分かりませんが、ここだけでタイムアウトはしないと思います。しかし他の処理も同時に実行するので)。 forを使ったパターンを考えて見ます
ishikoro.1234

2019/05/21 01:54

いつも大変お世話になっております。 お忙しい中、いつもご教授していただき、誠にありがとうございます。 早速、新しいコードを試してみましたが、コードが理解できなかったので、とりあえず順番に関数を起動して、効果を見ながら仕組むを理解しようと試みました。 コピー先のIDを入力し、「シート一覧」や「翻訳元_未コピ」は定数名だと思うので変えずに順番に関数を起動しました。 最初に1つ目はコピーするリストの方にシート一覧を作成しましたが、2つ目のシートだけIDがでなかったです。 IDは不要と思いましたので、 第5部分にある「e.getSheetId」を削除すればいいでしょうか。 2つ目の部分は正常に起動しましたが、シートに変化がなかったが、第3部分を起動した際にエラーがでました。 TypeError:undefinedな方法でgetSheetsをできません と表示されました。 もしかしたら起動する順番や何かを間違っていましたでしょうか また、翻訳シートは多いとき一つのスプレットシートで30枚ほどあります。 いままでの作業量から推測して、多くてスプレットシートが3枚で合計42枚ほどシートがあります。
papinianus

2019/05/21 04:22

# 概要 まず実行するのは`procedure()`のみです。順番などありません。人間が関数の実行を何度もクリックしたり、順番を気にするなんていうのはおかしな話です。コピペが手間だから自動化したいのに別の手間が発生したら意味がないです また順番に依存したプログラムを作ってはいけません ## procedure ### 変数 * dest:ご賢察の通りコピー先のシートをidで指定します * sheetName:リストを作るシートの名前です * folderName:コピーしたい(コピー元となる)複数のスプレッドシートを入れておくフォルダの名前です。コピー先のスプレッドシートとコピー済みのスプレッドシートが残らないように注意してください ### 処理 この関数は必要な変数を定義して、実際の処理コードを呼び出すだけです。独自の処理はありません ## pickSpreadsheetInFolderNamed ### 処理 引数で指定されたフォルダからスプレッドシートを取り出します お話からは、スプレッドシートが複数ありそうだったので、未コピーのものは特定のフォルダに入れておくのが簡便で実行しやすいと思いました (毎回スプレッドシートのidを調べるのはナンセンスなので) ## copyAll(旧q189933) ### 処理 元シートから先シートにコピーするものです。要件に適合させるため、引数を使うようにしました ## upsertSheet(旧q189933_) ### 処理 指定したシート名があればそのシートを、なければシートを作ってそのシートを取得します 要件に適合させるため、引数を使うようにしました また、既にあった場合にエラーにならないようにしました ## resetSheetIndexSheet(旧q189933__) ### 処理 指定されたシートに目次を作ります。要件に適合させるため、引数を使うようにしました また、idを入れないようにしました
ishikoro.1234

2019/05/21 06:04

お忙しい中、いつも詳しい説明をしてくださり、誠にありがとうございます。 新しいコードをコピーして、`procedure()`のみ実行しましたが、なぜかシート一覧のみ作成されて、指定したフォルダ名にあるスプレットシートはコピーされなかったです。 destの方にコピー先のスプレットシートのIDを入力して、folderNameのほうにコピー元のフォルダ名を入力しましたが、コピーされなかったのでいったいどこか間違っているのでしょうか。 もしかしたら、フォルダを特定できなかったじゃないかと思い、フォルダ名ではなく、フォルダIDの方がフォルダを特定するよう下記のコードに書き換えて見ましたが、今度は直接にエラー「ファイルが見つからない」が出ました。 const folderName = SpreadsheetApp.openById('フォルダIDを').getname(); 自分なりに消化してましたが、いまいち理解できなかったようです... 今度のコードの仕組みはfolderNameにあるスプレットシートをdestにコピーして、そこで予めにコピー前の名前を定数として保存して、シートの名前を変更している感じでしょうか。 また、名前をゲットする関数に関して、勉強用のコードまでいただいて、誠にありがたいです。 定数や関数、Arrayなどの概念がまだ弱いので、参考として別のコードを書きながら消化してみます。
papinianus

2019/05/22 13:09

1つミスがあって直しました。しかし仰る挙動になるのは「翻訳元_未コピー」相当のフォルダにスプレッドシートがない場合のように思えます。あるいはフォルダの下にフォルダがあるのでしょうか。多重階層の場合の確認はしていないです。 フォルダidには対応していません。どちらでも動くようにするのは無駄に大変なので。あとフォルダはDriveAppで操作します。イテレータが返されるので扱いが面倒です。そういう書き方は通用しないです 設計はご想像のとおりです。"定数"の使い方が変です。
papinianus

2019/05/22 13:14

対象となるスプレッドシートが「翻訳元_未コピー」相当のフォルダのなかにあるときは要件通り動作しましたが、さらにフォルダをはさんでその下にあると仰る挙動になりますね。
ishikoro.1234

2019/05/23 01:11

いつもお世話になっております。 コードの更新及び詳しい説明、誠にありがとうございます。 新しいコードは正常に使用できました。 この度はお忙しい中、何度もご教授してくださり、重ね重ね感謝致します。
guest

0

シート名取得コード

javascript

1function getNames() { 2 const sheetCounts = SpreadsheetApp.getActive().getNumSheets(); 3 const dat = []; 4 for (var i = 1; i <= sheetCounts; i++) { 5 dat.push([getname(i)]); 6 } 7 return dat; 8} 9 10function getname(sheet_no) { 11 return SpreadsheetApp.getActive().getSheets()[sheet_no - 1].getName(); 12}

質問者さまのコードを無視して近しいことをやるなら

javascript

1function re_getname() { 2 const sheets = SpreadsheetApp.getActive().getSheets(); 3 const dat = []; 4 for (var i = 1; i <= sheets.length; i++) { 5 dat.push([sheets[i].getName()]); 6 } 7 return dat; 8}

投稿2019/05/21 03:50

編集2019/05/21 04:28
papinianus

総合スコア12705

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

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

papinianus

2019/05/21 04:23

1つのスプレッドシートに最大30シートほどあるとのこと。これでも確かに時間制限にはかからないと思います。 しかしあえて遅くする理由がないので、こちらはお勉強用とご理解ください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問