mms02
@mms02 (航 渡邉)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

TypeError: Cannot read property 'length' of undefined エラーが解決できない。

Q&A

解決したいこと

GASで請求書のPDF化を試みていますが、
エラーを解決できずにいます。

発生している問題・エラー

TypeError: Cannot read property 'length' of undefined

該当するソースコード

newsheet.getRange(33,1,myTekiyo.length,myTekiyo[0].length).setValues(myTekiyo)

ソースコード全体

function Seikyusho() {

  //プログラムA-1|スプレッドシートを設定
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();//変数spreadsheetに「アクティブなスプレッドシート」を設定
  var sheet = spreadsheet.getSheetByName('シート4');//変数sheetに「シート4」シートを設定
  var myRange = sheet.getDataRange().getValues();//スプレッドシートのデータを二次元配列として取得

  //プログラムA-2|変数templateに「請求書フォーマット」シートを設定
  var template = spreadsheet.getSheetByName('請求書');//変数sheetに「請求書フォーマット」シートを設定  
  var start= template.getRange('S4').getValue();//「請求書フォーマット」のセルS4の日付を取得
  var startdate = dayjs.dayjs(start).subtract(1, 'd');//変数startの日付をMomentで設定(1日前を設定)
  var end= template.getRange('S5').getValue();//「請求書フォーマット」のセルS5の日付を取得
  var enddate = dayjs.dayjs(end).add(1, 'd');//変数endの日付をMomentで設定(1日後を設定)

  //プログラムA-3|空の配列を設定
  var torihiki = [];

  //プログラムA-4|プログラム2の取引先(E列)をプログラム3の空配列に取得
  for (var i=1; i<myRange.length; i++){ 
    torihiki.push(myRange[i][4]);//配列torihikiにmyRange[i][4]を追加
  }

  //プログラム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 myTekiyo = [];//シート4のH列「ご注文の時間〜」格納用
    var mySuryo = [];//シート4のN列「取引金額」格納用

    //プログラムA-6-2|取引先ごとに、プログラム6-1で設定した配列に格納
    for (var k=0; k<myRange.length; k++){ 
      if (dayjs.dayjs(myRange[k][4]).isAfter(startdate) && dayjs.dayjs(myRange[k][4]).isBefore(enddate)){//myRange[k][2](納品日)がstartdateより後、かつenddateより前ならば
        if (myRange[k][4] == torihiki_list[i]){ //myRange[k][4](取引先)とtorihiki_list[i]が一致すれば
          myTekiyo.push([myRange[k][7]]);//配列myTekiyoにmyRange[k][7]を追加
          mySuryo.push([myRange[k][9]]);//配列mySuryoにmyRange[k][9]を追加
        }
      }
    }

    //プログラムA-6-3|シートを追加して、シート名を各取引先に変更
    var newsheet = template.copyTo(spreadsheet);//「請求書フォーマット」のシートをコピーする
    newsheet.setName(torihiki[i]);//コピーしたシートの名前を「torihiki[i]」にする

    //プログラムA-6-4|ID,摘要,納品日,取引金額を新しいシートの33行目以下に貼り付け
    newsheet.getRange(33,1,myTekiyo.length,myTekiyo[0].length).setValues(myTekiyo);//セルC14以下に「摘要」情報を貼り付け
    newsheet.getRange(33,9,mySuryo.length,mySuryo[0].length).setValues(mySuryo);//セルF14以下に「納品日」情報を貼り付け

    //プログラムA-6-5|変数goukeiを0リセット
    // var goukei = 0;

    //プログラムA-6-6|14行目以降のC~Eを結合して、取引金額の合計値を算出
    // for (var j=0; j<myID.length; j++){
    //   var row = j+14;//行のカウントアップ
    //   newsheet.getRange('C'+ row + ':E' + row).merge();//セルC~セルEの結合
    //   goukei = goukei + Number(myKingaku[j]);//取引先ごとの取引金額を算出
    // }

    //プログラムA-6-7|シートに請求書情報を入力
    var today = dayjs.dayjs(new Date());
    var hiduke = dayjs.dayjs(start);
    var duedate = today.clone().add(15, 'd').format('YYYY/MM/DD');//請求日の期限を設定
    var month = hiduke.clone().format('YYYY年MM月');//年月の取得
    var formatteddate = today.clone().format('YYYY/MM/DD');

    newsheet.getRange('A6').setValue(torihiki_list[i]);//請求書のセルB4に取引先を入力
    newsheet.getRange('L6').setValue(formatteddate + '_' + Number(i+1));//請求書のセルL6に請求書IDを入力
    newsheet.getRange('L8').setValue(new Date());//請求書のセルG4に請求日(今日の日付)を入力
    // newsheet.getRange('C9').setValue(goukei + '円');//請求書のセルC9に合計金額を入力
    newsheet.getRange('C17').setValue(duedate);//請求書のセルC11に請求日の期限を入力

    Utilities.sleep(1000); //1秒待機(待機中に情報を更新)
    SpreadsheetApp.flush(); //挿入したシートの情報更新

    //プログラムA-6-8|PDF化
    var ssId = spreadsheet.getId();//スプレッドシートIDを取得
    var sheetId = newsheet.getSheetId();//取引先のシートIDを取得
    var folderurl = newsheet.getRange('S3').getValue();//newsheetのセルJ2の値(PDF保管先のフォルダURL)
    var myArray= folderurl.split('/'); //folderurlを「/」で区切る
    var folderid = myArray[myArray.length-1];//変数folderidにフォルダIDを取得
    var folder = DriveApp.getFolderById(folderid);//PDF保管先のfolderを設定
    PDFexport(ssId, sheetId,torihiki_list[i],folder);//プログラムBを実行(5つの引数を渡す)
  }
}

//プログラムB-0|PDF化
function PDFexport(ssId, sheetId, torihiki, row, folder) {

  //プログラムB-1|PDF化の条件設定
  var url = 'https://docs.google.com/spreadsheets/d/'+ ssId +'/export?';
  var opts = {
    exportFormat: 'pdf',      // ファイル形式の指定
    format:       'pdf',      // ファイル形式の指定
    size:         'A4',       // 用紙サイズの指定
    portrait:     'true',     // true縦向き、false 横向き
    fitw:         'true',     // 幅を用紙に合わせるか?
    sheetnames:   'false',    // シート名を PDF 上部に表示するか?
    printtitle:   'false',    // スプレッドシート名をPDF上部に表示するか?
    pagenumbers:  'false',    // ページ番号の有無
    gridlines:    'false',    // グリッドラインの表示有無
    fzr:          'false',    // 固定行の表示有無
    range :       'A1%3AG' + row,  // 対象範囲「%3A」 = : (コロン)  
    gid:           sheetId    // シート ID を指定 (省略する場合、すべてのシートをダウンロード)
  };

  //プログラムB-2|PDF化のurl作成
  var PDFurl = [];//urlという空配列を設定
  for(optName in opts){
    PDFurl.push(optName + '=' + opts[optName]);//opts配列の各要素を=でつないだものをurl配列に格納
  }
  var options  = PDFurl.join('&');//urlの配列の各要素を&でつなぐ

  //プログラムB-3|PDF化の条件設定
  var token    = ScriptApp.getOAuthToken();//アクセストークンを取得
  var response = UrlFetchApp.fetch(url + options, {headers: {'Authorization': 'Bearer ' +  token}}); //PDFのURLからアクセスする
  var blob = response.getBlob().setName(torihiki + '.pdf');//PDFの名前を「取引先+.pdf」とする
  var newFile = folder.createFile(blob);//PDFを所定のフォルダに保管する
  newFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);//共有設定をする:「リンクを知っている人」が「閲覧可能」
}

自分で試したこと

newsheet.getRange(33,1,myTekiyo.length,myTekiyo[0].length).setValues(myTekiyo)
上記のセルの取得を"A1"のように直接指定を試みましたが、別のエラーが発生し解決に至っておりません。

調べた時にでてきた記事
https://techacademy.jp/magazine/26836
https://teratail.com/questions/264325
https://teratail.com/questions/135221

0

1Answer

配列?
myTekiyo[0].length

ここ要素指定しているのに、length があるとは思えないんですが、Debuggerでデータ見てみたらいかがです?

0Like

Your answer might help someone💌