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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

Google

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

Q&A

1回答

1282閲覧

別ファイルにテンプレートを使用した請求書を作成

fihoooo

総合スコア0

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

Google

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

0グッド

1クリップ

投稿2021/11/09 09:16

前提・実現したいこと

元ファイルにある「テンプレート」シートを使用し会社別請求書を作成してます。
スプレッドシートを指定したフォルダに複製し、会社別にシートを作成します。
シートは設定、データ、テンプレートが存在しています。
設定:日付データを入力
データ:A2〜Dまで一覧表
テンプレート:A3に会社名、A11〜Dのデータ最終行まで転記。

テンプレートシートをコピーし、シート名を会社名に変更、
会社名毎のデータをA11〜Dのデータ最終行まで転記したいです。
以下の通り作成しましたが、エラーとなりご教授ください。

ここに質問の内容を詳しく書いてください。
(例)PHP(CakePHP)で●●なシステムを作っています。
■■な機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

TypeError: Cannot read property 'length' of undefined myFunction @ XXXXX.gs:71

該当のソースコード

function myFunction() { const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); const sht_setting = spreadsheet.getSheetByName('x');  const vare = sht_setting.getRange('C2').getValue(); var OutputFileName = ('請求書(')+Utilities.formatDate(new Date(vare), 'JST', 'yyyy年M月)') //保存先となるフォルダの取得 const folder = DriveApp.getFolderById('XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); //複製するファイル(スプレッドシート)の取得 const file = DriveApp.getFileById('XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); let new_spreadsheet_id = file.makeCopy(OutputFileName, folder).getId(); let new_spreadsheet = SpreadsheetApp.openById(new_spreadsheet_id); //複製したスプレッドシートの内にあるシート(TEMPLATE)の取得 let template = new_spreadsheet.getSheetByName('テンプレート'); //複製したスプレッドシートの内にあるシート(DATA)の取得 let sheet = new_spreadsheet.getSheetByName('データ'); //プログラムA-1|スプレッドシートを設定 var myRange = sheet.getDataRange().getValues();//スプレッドシートのデータを二次元配列として取得 //プログラムA-2|変数templateに「請求書フォーマット」シートを設定 var start= template.getRange('F3').getValue();//「テンプレート」の日付を取得 var startdate = dayjs.dayjs(start);//開始日設定 var end= template.getRange('F4').getValue();//「テンプレート」の日付を取得 var enddate = dayjs.dayjs(end);//終了日設定 //プログラムA-3|空の配列を設定 var torihiki = []; //プログラムA-4|プログラム2の取引先(E列)をプログラム3の空配列に取得 for (var i=1; i<myRange.length; i++){ torihiki.push(myRange[i][1]);//配列torihikiにmyRange[i][]を追加 } //プログラムA-5|プログラム4の取引先名の重複を削除 var torihiki_list = torihiki.filter(function(value, i, self){ return self.indexOf(value) === i; }); //プログラムA-6|商品名ごとに繰り返す for (var i=0; i<torihiki_list.length; i++){ //プログラムA-6-1|空の配列を設定 var myID = [];//シート1のA列「ID」格納用 var myTekiyo = [];//シート1のB列「摘要」格納用 var myNouhin = [];//シート1のC列「納品日」格納用 var myKingaku = [];//シート1のD列「取引金額」格納用 //プログラムA-6-2|取引先ごとに、プログラム6-1で設定した配列に格納 for (var k=0; k<myRange.length; k++){ if (dayjs.dayjs(myRange[k][0]).isAfter(startdate) && dayjs.dayjs(myRange[k][0]).isBefore(enddate)){//myRange[k][2](納品日)がstartdateより後、かつenddateより前ならば if (myRange[k][1] == torihiki_list[i]){ //myRange[k][4](取引先)とtorihiki_list[i]が一致すれば myID.push([myRange[k][0]]);//配列myIDにmyRange[k][0]を追加 myTekiyo.push([myRange[k][2]]);//配列myTekiyoにmyRange[k][1]を追加 myNouhin.push([myRange[k][3]]);//配列myNouhinにmyRange[k][2]を追加 myKingaku.push("個");//配列myKingakuにmyRange[k][3]を追加 } } } //プログラムA-6-3|シートを追加して、シート名を各取引先に変更 var newsheet = template.copyTo(spreadsheet);//「請求書フォーマット」のシートをコピーする deleteSheetIfExist(spreadsheet,torihiki_list[i]); newsheet.setName(torihiki[i]);//コピーしたシートの名前を「torihiki[i]」にする //プログラムA-6-4|ID,摘要,納品日,取引金額を新しいシートの14行目以下に貼り付け console.log(newsheet); newsheet.getRange(11,1,myID[0].length,1).setValues(myID);//セルB14以下に「ID」情報を貼り付け newsheet.getRange(11,2,myTekiyo[0].length,1).setValues(myTekiyo);//セルC14以下に「摘要」情報を貼り付け newsheet.getRange(11,3,myNouhin.length,myNouhin[0].length).setValues(myNouhin);//セルF14以下に「納品日」情報を貼り付け newsheet.getRange(11,4,myKingaku.length,myKingaku[0].length).setValues(myKingaku);//セルG14以下に「取引金額」情報を貼り付け } } function deleteSheetIfExist(spreadsheet, name) { const sheet = spreadsheet.getSheetByName(name); if(sheet === null) return; spreadsheet.deleteSheet(sheet); }

試したこと

https://fastclassinfo.com/entry/gas_seikyusho/#Google_Apps_ScriptGAS
上記のサイトを参考にしました

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

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

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

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

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

takaD

2021/11/09 10:10

エラーでは、 myFunction @ XXXXX.gs:71 1行目から貼り付けていくと、71行目は newsheet.getRange(11,2,myTekiyo[0].length,1).setValues(myTekiyo);//セルC14以下に「摘要」情報を貼り付け なのですが、その行でエラーが発生しているとの認識でいいのでしょうか?
fihoooo

2021/11/10 00:33

はい。そちらの認識の通りです。
guest

回答1

0

関係のありそうなところをピックアップしてみます。

GAS

1//最初、myRangeに シート内のデータを格納する。 2 var myRange = sheet.getDataRange().getValues();//スプレッドシートのデータを二次元配列として取得 3 4 5//次に myTekiyoのスペースを確保する。 6var myTekiyo = [];//シート1のB列「摘要」格納用 7 8 9//次にFor文内で必要な情報を格納していく。 10 for (var k=0; k<myRange.length; k++){ 11 if (dayjs.dayjs(myRange[k][0]).isAfter(startdate) && dayjs.dayjs(myRange[k][0]).isBefore(enddate)){//myRange[k][2](納品日)がstartdateより後、かつenddateより前ならば 12 if (myRange[k][1] == torihiki_list[i]){ //myRange[k][4](取引先)とtorihiki_list[i]が一致すれば 13 myID.push([myRange[k][0]]);//配列myIDにmyRange[k][0]を追加 14 myTekiyo.push([myRange[k][2]]);//配列myTekiyoにmyRange[k][1]を追加 15 myNouhin.push([myRange[k][3]]);//配列myNouhinにmyRange[k][2]を追加 16 myKingaku.push("個");//配列myKingakuにmyRange[k][3]を追加 17 } 18 } 19 } 20 21 22//最後、myID[0].lengthではエラーとならず、myTekiyo[0].lengthでエラーとなる。 23 newsheet.getRange(11,1,myID[0].length,1).setValues(myID);//セルB14以下に「ID」情報を貼り付け newsheet.getRange(11,2,myTekiyo[0].length,1).setValues(myTekiyo);//セルC14以下に「摘要」情報を貼り付け 24

まず、データ内の内容が解らないのではっきりとは言えないですが、
[myRange[k][2]]が本当に存在するのか見てみてください。
もしかしたらDataRangeで取得した範囲に、[k][2](k行、C列)が無いのかもしれません。

console.log(myID,myTekiyo,myNouhin,myKingaku)

等をいれて、各種配列内にデータがしっかりと格納されているのか確認してみてください。

また、

console.log(myRange[0])
console.log(myRange[1])

等をやって、myRange内のデータがどうなっているのかも確認してみてください。

明確な答えは出せないですが、所感では、

sheet.getDataRange().getValues()

で取得した範囲と、

myTekiyo.push([myRange[k][2]]);

で格納している範囲にギャップが発生している可能性が高いです。
以上頑張ってみてください。

投稿2021/11/10 00:55

takaD

総合スコア315

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

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

fihoooo

2021/11/11 00:42

ご回答ありがとうございます。 console.logを追加したら配列の中身が空でした。 データの取得自体ができてないってことですね。 ギャップですか。難しいですね。
takaD

2021/11/12 02:14

配列が空ならfor文内をconsole.logとかで見てみるとなにか解るかもですね。 2種類のIF文に一致しないと配列の中にデータを入れない様な構成ですから、 if (dayjs.dayjs(myRange[k][0]).isAfter(startdate) && dayjs.dayjs(myRange[k][0]).isBefore(enddate)) と if (myRange[k][1] == torihiki_list[i]){ の中身をよく見てみると良いでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問