-1

I'm trying to use an array to get specific results from an API to display in a row in a spreadsheet using google script. This is a sample of what the API log looks like:

[20-06-07 22:38:53:839 BST] [ {   
"symbol" : "AMZN",   
"date" : "2020-03-31",  
"currentRatio" : 1.07870933748165254,   
"quickRatio" : 0.842142238837801593, 
},{...

The code written below seems to work fine until the forEach array, where I get this error:

"TypeError: results.forEach is not a function"

function callAPI(symbol) {

  // Call the api  
  var dataSheet = SpreadsheetApp.getActive().getSheetByName("Fundamental Analysis Model");   
  var url = 'https://financialmodelingprep.com/api/v3/ratios/'
  var apikey = '?period=quarter&apikey=x'
  var response = UrlFetchApp.fetch(url + symbol + apikey);

  // Parse the JSON reply
  var json = response.getContentText();
  var data = JSON.parse(json);  
  console.log(data)
  return JSON.parse(json)
  }

function displayFinancials(array) {

  var dataSheet = SpreadsheetApp.getActive().getSheetByName("Fundamental Analysis Model"); 

  var symbol = "AMZN"
  var api = callAPI(symbol);
  var results = api[0]
  var output = []

    results.forEach(function(elem) {
    output.push([elem["currentRatio"],elem["quickratio"]]);
     });

  dataSheet.appendRow([output])
}

If anyone can help correct the array so it will output the 2 example results that would be amazing. Thanks!

Log Data:

[20-06-07 23:46:12:257 BST] Logging output too large. Truncating output. [ { symbol: 'AMZN',
    date: '2020-03-31',
    currentRatio: 1.0787093374816525,
    quickRatio: 0.8421422388378016,
    cashRatio: 0.341245248460062,
    daysOfSalesOutstanding: 86.28187456926258,
    daysOfInventoryOutstanding: 155.51901394129743,
    operatingCycle: 241.80088851056001,
    daysOfPayablesOutstanding: 330.35316447115713,
    cashConversionCycle: -244.07128990189454,
    grossProfitMargin: 0.4134416582728092,
    operatingProfitMargin: 0.052868048560674334,
    pretaxProfitMargin: 0.04483645231405397,
    netProfitMargin: 0.03359751895244659,
    effectiveTaxRate: 0.21992314513745195,
    returnOnAssets: 0.011458248582973991,
    returnOnEquity: 0.03883748008334355,
    returnOnCapitalEmployed: 0.02390356610399429,
    netIncomePerEBT: 0.7493349098433343,
    ebtPerEbit: 1,
    ebitPerRevenue: 0.04483645231405397,
    debtRatio: 0.7049693090698704,
    debtEquityRatio: 2.3894778771908323,
    longTermDebtToCapitalization: 0.26420092662525785,
    totalDebtToCapitalization: null,
    interestCoverage: 8.41542288557214,
    cashFlowToDebtRatio: null,
    companyEquityMultiplier: 3.3894778771908323,
    receivablesTurnover: 4.230320699708455,
    payablesTurnover: 1.1048781705612143,
    inventoryTurnover: 2.346979901362889,
    fixedAssetTurnover: 0.9700818987130202,
    assetTurnover: 0.34104448602862075,
    operatingCashFlowPerShare: 6.152610441767068,
    freeCashFlowPerShare: -7.491967871485944,
    cashPerShare: 98.97991967871486,
    payoutRatio: 0,
    operatingCashFlowSalesRatio: 0.04060859884429836,
    freeCashFlowOperatingCashFlowRatio: -1.2176892950391645,
    cashFlowCoverageRatios: null,
    shortTermCoverageRatios: null,
    capitalExpenditureCoverageRatio: 0.45091979396615156,
    dividendPaidAndCapexCoverageRatio: null,
    dividendPayoutRatio: null,
    priceBookValueRatio: 18.875658781713444,
    priceToBookRatio: 18.875658781713444,
    priceToSalesRatio: 16.32895085617346,
    priceEarningsRatio: 486.0165680473373,
    priceToFreeCashFlowsRatio: -330.22031626909677,
    priceToOperatingCashFlowsRatio: 402.10574412532634,
    priceCashFlowRatio: 402.10574412532634,
    priceEarningsToGrowthRatio: 74.06250027159547,
    priceSalesRatio: 16.32895085617346,
    dividendYield: null,
    enterpriseValueMultiple: 131.35365201582718,
    priceFairValue: 18.875658781713444 },...

[20-06-07 23:46:12:265 BST] TypeError: results.forEach is not a function
    at displayFinancials(Stock Research & Analysis:123:13)

2 Answers2

2

The problem is api indeed is an array, but api[0] is an object, forEach method cannot iterate objects. for..in or Object.keys() methods will do the trick.

const results = [{ 
        symbol: 'AMZN',
        date: '2020-03-31',
        currentRatio: 1.0787093374816525,
        quickRatio: 0.8421422388378016,
        cashRatio: 0.341245248460062,
    },{ 
        symbol: 'AMZN',
        date: '2020-03-31',
        currentRatio: 2,
        quickRatio: 2,
        cashRatio: 0.341245248460062,
    },{ 
        symbol: 'AMZN',
        date: '2020-03-31',
        currentRatio: 3,
        quickRatio: 3,
        cashRatio: 0.341245248460062,
    }
];

const output = results.map( result => [ result.currentRatio, result.quickRatio ])

console.log(output); // Should print [ [ 1.0787093374816525, 0.8421422388378016 ], [ 2, 2 ], [ 3, 3 ] ]

Or if you only want the first result it's really simple:

const results = { symbol: 'AMZN',
    date: '2020-03-31',
    currentRatio: 1.0787093374816525,
    quickRatio: 0.8421422388378016,
    cashRatio: 0.341245248460062,
    daysOfSalesOutstanding: 86.28187456926258,
    daysOfInventoryOutstanding: 155.51901394129743,
    operatingCycle: 241.80088851056001,
};

const output = [results.currentRatio, results.quickRatio];

console.log(output); // will print [1.0787093374816525, 0.341245248460062]
Andrés Muñoz
  • 559
  • 3
  • 8
  • Could you please provide what is the ouput that your'e expecting? – Andrés Muñoz Jun 08 '20 at 00:09
  • Hi, thanks for your answer, I have attemped to rewrite it using your suggestions, however I'm new to javascript and don't know much about it, ,my adjustment is below however it still does not work, are you able to correct it? Thanks. ... for(var i in results) output.push(["currentRatio"], ["quickRatio"]); – George Bates Jun 08 '20 at 00:13
  • The output I am seeking is e.g. the "currentRatio" and "quickRatio" results from the API, then I would appendrow them together on the last row of the spreadsheet. – George Bates Jun 08 '20 at 00:15
  • Ok so you want `output` to be this array: `[ 1.0787093374816525, 0.8421422388378016]`, am I right? – Andrés Muñoz Jun 08 '20 at 01:04
  • I'm glad to help. If this or any answer has solved your question please consider [accepting it](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – Andrés Muñoz Jun 08 '20 at 14:49
1

As a supplementary answer: forEach method does not exist on Object.prototype, but only on the Array.prototype hence the error message "not a function". If you wanted to, you could define your own (although, it is not advisable).

Instead, you could define a subclass of Object with a forEach method, if you are more comfortable with it (another best practice would be not to use class):

class MyObject extends Object { 
  constructor(value) { 
    super(value); 
  }

  forEach(callback, thisArg) {
    const boundCbk = callback.bind(thisArg || this);

    Object.values(this).forEach((value,idx) => {
      boundCbk(value,idx,this);
    });
  }
}

const test = new MyObject();

test.one = 1;
test.two = 2;

test.forEach(value => console.log(value));