![](/img/trans.png)
[英]Error: function is not defined when calling a function returned by another function
[英]Google Scripts - Error When Calling Function in Another Function
我發布了我在下面的全部代碼。
我正在使用 Google Scripts,從不斷變化的工作表中提取一些數據,執行計算,然后重新填充工作表。
數據正在被調用到應用程序中,因此我正在嘗試盡快進行計算(因此,如果有人能告訴我更有效的方法來執行此操作,那也會有所幫助)。
當我嘗試調用invoicePrice()
函數或tiers()
函數,我得到一個類型錯誤:功能不能被發現。
function invoicePrice() {
// define row to do calculations on
var AVals = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange("A1:A1000").getValues();
var ALast = AVals.filter(String).length;
// Set order No. here
var orderNoPrev = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast - 1, 3).getValue();
var orderNo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 3).setValue(orderNoPrev + 1);
var total = 0;
// invoicePrice the total number of items
var itemRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 4, 1, 14).getValues()[0];
// set the values of the constants on the Products page
var priceRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("F1:F1000").getValues();
var pLast = priceRange.filter(String).length;
var pGrab = priceRange.splice(0,pLast);
var invoicePrice = 0;
// set weight of case values
var weightRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("V1:V1000").getValues();
var wLast = weightRange.filter(String).length;
var wGrab = weightRange.splice(0,wLast);
for (var i = 0, len = 13; i <= len; i++) {
// SUBTOTAL THE ORDER AMOUNT
var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();
total += orderAmount;
// SET/KG PRICES
var perKGInvoice = pGrab[i + 1].map(Number);
// SET WEIGHTS
var weights = wGrab[i + 1].map(Number);
// SET CASE PRICE
var casePrice = perKGInvoice * weights;
// SUM OF PRODUCT PRICE * ORDER AMOUNT * WEIGHT OF CASE
invoicePrice += orderAmount * perKGInvoice * weights;
}
Logger.log(invoicePrice, ALast, pGrab, wGrab);
return [invoicePrice, ALast, pGrab, wGrab];
}
function tiers() {
var invoicePriceCall = invoicePrice();
var invoicePrice = invoicePriceCall[0];
var ALast = invoicePriceCall[1];
var beefDiscount = 0;
var sfDiscount = 0;
var currentTier = ""
// Set the invoice order value required ($ amount)
var tier1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 3).getValue();
var tier2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 3).getValue();
var tier3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 3).getValue();
var tier4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 3).getValue();
var tier5 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 3).getValue();
var minNotmet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(10, 3).getValue();
// Set the discount tier levels for beef (% discount)
var tier1BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 4).getValue();
var tier2BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 4).getValue();
var tier3BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 4).getValue();
var tier4BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 4).getValue();
var tier5BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 4).getValue();
var tier1SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 5).getValue();
var tier2SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 5).getValue();
var tier3SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 5).getValue();
var tier4SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 5).getValue();
var tier5SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 5).getValue();
if (invoicePrice < tier1) {
beefDiscount = tier1BeefDiscount;
sfDiscount = tier1SfDiscount;
currentTier = "Minimum Not Met"
}
else if (invoicePrice < tier2) {
beefDiscount = tier1BeefDiscount;
sfDiscount = tier1SfDiscount;
currentTier = "Tier 1"
}
else if (invoicePrice < tier3) {
beefDiscount = tier2BeefDiscount;
sfDiscount = tier2SfDiscount;
currentTier = "Tier 2"
}
else if (invoicePrice < tier4) {
beefDiscount = tier3BeefDiscount;
sfDiscount = tier3SfDiscount;
currentTier = "Tier 3";
}
else if (invoicePrice < tier5) {
beefDiscount = tier4BeefDiscount;
sfDiscount = tier4SfDiscount;
currentTier = "Tier 4";
}
else {
beefDiscount = tier5BeefDiscount;
sfDiscount = tier5SfDiscount;
currentTier = "Tier 5";
}
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 20).setValue(beefDiscount);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 21).setValue(sfDiscount);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 22).setValue(currentTier);
return [beefDiscount, sfDiscount, tier1];
}
function calcsOnColumns2() {
// call price range and weight from previous function
var invoicePriceCall = invoicePrice();
var invoicePrice = invoicePriceCall[0];
var ALast = invoicePriceCall[1];
var priceRange = invoicePriceCall[2];
var weightRange = invoicePriceCall[3];
// call tiers function
var tiers = tiers();
var beefDiscount = tiers[0];
var sfDiscount = tiers[1];
var tier1 = tiers[2];
// set sums to 0
var beefSum = 0;
var sfSum = 0
for (var i = 0, len = 13; i <= len; i++) {
// SUBTOTAL THE ORDER AMOUNT
var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();
// SET/KG PRICES
var perKGInvoice = priceRange[i + 1].map(Number);
// SET WEIGHTS
var weights = weightRange[i + 1].map(Number);
// SET CASE PRICE
var casePrice = perKGInvoice * weights;
// Split up seafood and beef with if statement:
if (i < 9) {
// set discount case price
var discountCaseBeef = perKGInvoice - (perKGInvoice * beefDiscount);
// set the total price of the discounted cases in the order (ie, order price * discount)
var beefCaseOrder = discountCaseBeef * orderAmount * weights;
beefSum += beefCaseOrder;
// Nice and Formatted sheet
var casePrice = perKGInvoice * weights;
if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseBeef.toFixed(2) + "/kg = ~$" + beefCaseOrder.toFixed(2)); }
}
else {
var discountCaseSF = perKGInvoice - (perKGInvoice * sfDiscount);
// set the total price of the discounted cases in the order (ie, order price * discount)
var sfCaseOrder = discountCaseSF * orderAmount * weights;
sfSum += sfCaseOrder;
// Nice and Formatted sheet
var casePrice = perKGInvoice * weights;
if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseSF.toFixed(2) + "/kg = ~$" + sfCaseOrder.toFixed(2)); }
}
if (i == len) {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 24).setValue(beefSum);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 25).setValue(sfSum);
// if statement to go here if min order size not met
var sumOfSums = beefSum + sfSum;
// swap out 75 with referenced value
if (sumOfSums > tier1) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue(sumOfSums) }
// swap out phrase with changable phrase
else { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue("Minimum order size not met") }
var totalDiscount = invoicePrice - sumOfSums
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 29).setValue(totalDiscount);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 30).setValue(invoicePrice);
}
}
}
問題
甲正確聲明函數( invoicePrice
),從另一個函數(調用時calcsOnColumns2
)是undefined
。
重現步驟
假設您有三個名為A
、 B
、 C
函數,然后調用B
會導致您的錯誤:
function A() {
var A = 0;
return [A];
}
function C() {
var a = A();
var A = a[0];
}
function B() {
A();
C();
}
您可能已經注意到,這就是您的功能歸結為 - 行為是由於提升:
B
調用A
,它返回一個第一個元素為0
的Array
;C
調用函數A
和覆蓋A
到的輸出A
; 相反,在第二步A
被聲明為等於a
第一個元素,然后才調用A
由於a
從對A
調用中獲取其值,因此A
將是undefined
,因此: [undefined]()
->“不是函數”
優化
getRange()
、 getValue()
)放入循環中 - 輸入/輸出總是很慢,因此通常最好將所有內容加載到內存中並在那里處理數據。if...else
聲明兩個同名的變量,將它移到外部作用域)。 我已經對您的腳本進行了一些優化,請看一下(請在使用前檢查,因為我們沒有示例數據,我無法對其進行測試)。 你可以做的還有很多(特別是關於calcsOnColumns2
的循環),但這應該是一個開始:
/** * [Your decription here] * @returns {Number[]} */ function invoicePrice() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var subtotalDisplaySheet = ss.getSheetByName('SubtotalDisplay'); // define row to do calculations on var AVals = subtotalDisplaySheet.getRange("A1:A1000").getValues(); var ALast = AVals.filter(String).length; // Set order No. here var orderNoPrev = subtotalDisplaySheet.getRange(ALast - 1, 3).getValue(); var orderNo = subtotalDisplaySheet.getRange(ALast, 3).setValue(orderNoPrev + 1); // invoicePrice the total number of items var itemRange = subtotalDisplaySheet.getRange(ALast, 4, 1, 14).getValues()[0]; // set the values of the constants on the Products page var productsSheet = ss.getSheetByName("Products"); var priceRange = productsSheet.getRange("F1:F1000").getValues(); var pLast = priceRange.filter(String).length; var pGrab = priceRange.splice(0, pLast); var outputInvoicePrice = 0; var weightRange = productsSheet.getRange("V1:V1000").getValues(); var wLast = weightRange.filter(String).length; var wGrab = weightRange.splice(0, wLast); var orderAmounts = subtotalDisplaySheet.getRange(Alast, 17).getValues(); var total = 0; for (var i = 0, len = 13; i <= len; i++) { var nextI = i + 1; var orderAmount = orderAmounts[0][i + 4]; total += orderAmount; var perKGInvoice = pGrab[nextI].map(Number); var weights = wGrab[nextI].map(Number); var casePrice = perKGInvoice * weights; outputInvoicePrice += orderAmount * casePrice; } Logger.log(outputInvoicePrice, ALast, pGrab, wGrab); return [outputInvoicePrice, ALast, pGrab, wGrab]; } /** * Gets values from 5 rows in * a column starting from row 3 * @param {Sheet} sheet * @param {Number} column * @returns {*[]} */ function getGridValues(sheet, column) { var range = sheet.getRange(3, column, 5, 1); return range .getValues() .map(function (row) { return row[0]; }); } /** * [Your decription here] * @returns {Number[]} */ function tiers() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var discountGridSheet = ss.getSheetByName("DiscountGrid"); var invoicePriceCall = invoicePrice(); var outputInvoicePrice = invoicePriceCall[0]; var ALast = invoicePriceCall[1]; var beefDiscount = 0; var sfDiscount = 0; var currentTier = ""; var tierValues = getGridValues(discountGridSheet, 3); var tier1 = tierValues[0]; var tier2 = tierValues[1]; var tier3 = tierValues[2]; var tier4 = tierValues[3]; var tier5 = tierValues[4]; var minNotmet = discountGridSheet.getRange(10, 3).getValue(); var tierBeefDiscountValues = getGridValues(discountGridSheet, 4); var tier1BeefDiscount = tierBeefDiscountValues[0]; var tier2BeefDiscount = tierBeefDiscountValues[1]; var tier3BeefDiscount = tierBeefDiscountValues[2]; var tier4BeefDiscount = tierBeefDiscountValues[3]; var tier5BeefDiscount = tierBeefDiscountValues[4]; var tierSfDiscountValues = getGridValues(discountGridSheet, 5); var tier1SfDiscount = tierSfDiscountValues[0]; var tier2SfDiscount = tierSfDiscountValues[1]; var tier3SfDiscount = tierSfDiscountValues[2]; var tier4SfDiscount = tierSfDiscountValues[3]; var tier5SfDiscount = tierSfDiscountValues[4]; if (outputInvoicePrice < tier1) { beefDiscount = tier1BeefDiscount; sfDiscount = tier1SfDiscount; currentTier = "Minimum Not Met"; } else if (outputInvoicePrice < tier2) { beefDiscount = tier1BeefDiscount; sfDiscount = tier1SfDiscount; currentTier = "Tier 1"; } else if (outputInvoicePrice < tier3) { beefDiscount = tier2BeefDiscount; sfDiscount = tier2SfDiscount; currentTier = "Tier 2"; } else if (outputInvoicePrice < tier4) { beefDiscount = tier3BeefDiscount; sfDiscount = tier3SfDiscount; currentTier = "Tier 3"; } else if (outputInvoicePrice < tier5) { beefDiscount = tier4BeefDiscount; sfDiscount = tier4SfDiscount; currentTier = "Tier 4"; } else { beefDiscount = tier5BeefDiscount; sfDiscount = tier5SfDiscount; currentTier = "Tier 5"; } var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay"); var subtotalDisplayRange = subtotalDisplaySheet.getRange(ALast, 20, 3, 1); subtotalDisplayRange.setValues([ [beefDiscount], [sfDiscount], [currentTier] ]); return [beefDiscount, sfDiscount, tier1]; } /** * Foramts amount string * @param {Number} amount * @returns {Function} */ function formatAmount(amount) { return function (discount, caseOrder) { return amount + " cases @" + discount.toFixed(2) + "/kg = ~$" + caseOrder.toFixed(2); }; } /** * Counts sum by discount, amount and weights * @param {Number} amount * @param {Number} weights * @returns {Number} */ function countSum(amount, weights) { return function (discount) { return discount * amount * weights; }; } /** * Counts discount case per Kg * @param {Number} perKG * @returns {Number} */ function countDiscountCase(perKG) { return function (discount) { return perKG - (perKG * discount); }; } /** * [Your decription here] */ function calcsOnColumns2() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay"); var invoicePriceCall = invoicePrice(); var outputInvoicePrice = invoicePriceCall[0]; var ALast = invoicePriceCall[1]; var priceRange = invoicePriceCall[2]; var weightRange = invoicePriceCall[3]; var tiers = tiers(); var beefDiscount = tiers[0]; var sfDiscount = tiers[1]; var tier1 = tiers[2]; var beefSum = 0; var sfSum = 0; var orderAmounts = subtotalDisplaySheet.getRange(ALast, 17).getValues(); for (var i = 0, len = 13; i <= len; i++) { var orderAmount = orderAmounts[0][i + 4]; var nextI = i + 1; var perKGInvoice = priceRange[nextI].map(Number); var weights = weightRange[nextI].map(Number); var casePrice = perKGInvoice * weights; var subtotalRange = subtotalDisplaySheet.getRange(ALast, i + 32); var formatAmountOrder = formatAmount(orderAmount); var countDisountSum = countSum(orderAmount, weights); var countPerKGCase = countDiscountCase(perKGInvoice); // Split up seafood and beef with if statement: if (i < 9) { var discountCaseBeef = countPerKGCase(beefDiscount); var beefCaseOrder = countDisountSum(discountCaseBeef); beefSum += beefCaseOrder; } else { var discountCaseSF = countPerKGCase(sfDiscount); var sfCaseOrder = countDisountSum(discountCaseSF); sfSum += sfCaseOrder; } if (orderAmount) { subtotalRange.setValue( i < 9 ? formatAmountOrder(discountCaseBeef, beefCaseOrder) : formatAmountOrder(discountCaseSF, sfCaseOrder) ); } if (i == len) { subtotalDisplaySheet.getRange(ALast, 24).setValue(beefSum); subtotalDisplaySheet.getRange(ALast, 25).setValue(sfSum); // if statement to go here if min order size not met var subtotalRange = subtotalDisplaySheet.getRange(ALast, 27); var sumOfSums = beefSum + sfSum; subtotalRange.setValue(sumOfSums > tier1 ? "Minimum order size not met" : sumOfSums); var totalDiscount = outputInvoicePrice - sumOfSums; subtotalDisplaySheet.getRange(ALast, 29).setValue(totalDiscount); subtotalDisplaySheet.getRange(ALast, 30).setValue(outputInvoicePrice); } } }
筆記
i++
是一個例子,但是函數式風格會說即使這是有問題的)。invoicePrice
undefined
說明了更多)。參考
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.