简体   繁体   中英

Google Apps Script - Email stock notification?

Hi there!

I am a beginner both in JavaScript and in Google Sheets, but I am trying to find a way for Google Apps Script to basically scan the data I have brought in there from a Swedish Online Bank where they have some information about how the stocks go up and down.

Furthermore, I want to be notified by email when one of these on my list goes down by for example 5 % in a day.

I tried something like this:

let arrayRow = ["+" + 5.91 + "%", "+" + 5.22 + "%", "-" + 5.5 + "%"];
console.log(arrayRow);

function stockPricePlus() {
  if (arrayRow >= "+" + 5 + "%") {
    console.log("Yay! One of your stocks are going up by 5 % or more!");
  }
}
function stockPriceMinus() {
  if (arrayRow <= "-" + 5 + "%") {
    console.log("Oh noes! One of your stocks are going down by 5 % or more!");
  }
}

stockPricePlus();
stockPriceMinus();

And this works in my JavaScript file, but I am not quite sure how to make it pull the data continuously from the Google Sheets and run through them like a loop?

I found something on the internet that seemed to kind of do the job, but I also see that there are some missing parts in the code.

function sendEmails () {
  var sheet = SpreadsheetApp.getActiveSheet();
  var Price = sheet.getRange("B34:B").getValues();

  var data = Price.getValues();

  var results = [];
  for (var i = 0; i < data.length; ++i) {
    var row = data[i];

    Logger.log(Price);
    if (Price >= "+" + 5 + "%") {
      MailApp.sendEmail("johnsmith@gmail.com", "Stock Price Alert from Stock Price Google Script", "One of your stocks are going up by 5 % or more!");
    }

    if (Price <= "-" + 5 + "%") {
      MailApp.sendEmail("johnsmith@gmail.com", "Stock Price Alert from Stock Price Google Script", "One of your stocks are going down by 5 % or more!");
    }

A ClientSide Timer for Collecting Periodic Stock Prices using GoogleFinance cell formulas

This code is a portion of code that I have used to check stocks. It has a timer function which runs clientside on your browser and you can adjust the sampling rate as you desire. I'd recommend no less that once every 5 minutes. That gives a good long time to get everything done. I also added a checkStats function which calculates percent change using the formula (max-min/max) * 100 and it compares this value with a value that you can set for each stock on the StockPrices page. It is also set up to send emails if the percent change is greater than a threshold and you can set. You can have as many stocks as you wish but you may need to adjust the sample rate if you try to get too many. You will have to add the email recipient address.

I have several other functions which chart the various stocks in different ways that I didn't include in this. I tried to keep this simple so I wouldn't be surprised if I have inadvently left some things out. Please note this script does not start automatically each day. In fact I hardly ever use it but I thought it would be an interesting thing to do and since then I've found the timer portion to be quite handy.

It's been my experience that GoogleFinance tags do not refresh regularly throughout the day. I've seen them not change at all for as long as 12 minutes while watching the stock prices change on another more elaborate system that runs on a personal computer.

datatimer.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <style>
      #my_block{border:2px solid black;background-color:rgba(0,150,255,0.2);padding:10px 10px 10px 10px;}
      #conv_block{border: 1px solid black;padding:10px 10px 10px 10px;}
      .bttn_block{padding:5px 5px 0px 0px;}
      .sndr_block {border:1px solid rgba(0,150,0,0.5);background-color:rgba(150,150,0,0.2);margin-bottom:2px;}
    </style>
  </head>
  <body>
  <form>
    <div id="my_block" class="block form-group">
      <div class="sndr_block">
        <div id="myClock" style="font-size:20px;font-weight:bold;"></div>
        <br />Timer Duration(minutes):
        <br /><input id="txt1" type="text" size="4" class="action"/>
        <select id="sel1" onChange="loadTxt('sel1','txt1');">
        </select>
        <div id="cntdiv"></div>
        <br /><strong>Timer Controls</strong>
        <div class="bttn_block"><input type="button" value="Start" name="startShow" id="startShow" onClick="startmytimer();changeData();" class="red" /></div>
        <div class="bttn_block"><input type="button" value="Stop" name="stopTimer" id="stopTimer" class="red" /></div>
        <div class="bttn_block"><input type="button" value="Single Ping" name="changedata" id="chgData" class="red" onClick="changeData();" /></div>
      </div>
      <div id="btn-bar">
        <br /><input type="button" value="Exit" onClick="google.script.host.close();" class="green" />
      </div>
    </div>
  </form>
    <script>
    var idx=1;
    var myInterval='';
    var cnt=0;
      $(function() {
        var select = document.getElementById('sel1');
        select.options.length = 0; 
        for(var i=1;i<61;i++)
        {
          select.options[i-1] = new Option(i,i * 60000);
        }
        select.selectedIndex=4;
        $('#startTimer').click(startmytimer);
        $('#stopTimer').click(stopTimer);
        $('#txt1').val(String(select.options[select.selectedIndex].value));
        startTime();
      });

      function startTime(){
        var today = new Date();
        var h = today.getHours();
        var m = today.getMinutes();
        var s = today.getSeconds();
        m = checkTime(m);
        s = checkTime(s);
        document.getElementById('myClock').innerHTML =
        h + ":" + m + ":" + s;
        var t = setTimeout(startTime, 500);
      }

      function checkTime(i){
        if (i < 10) {i = "0" + i};  // add zero in front of numbers < 10
        return i;
      }

      function startmytimer(){
        document.getElementById('cntdiv').innerHTML='<strong>Timer Started:</strong> ' + document.getElementById('myClock').innerHTML;
        myInterval=setInterval(changeData, Number($('#txt1').val()));
      }

      function stopTimer(){
        document.getElementById('cntdiv').innerHTML='Timer Stopped';
        clearInterval(myInterval);
      }

      function loadTxt(from,to){
        document.getElementById(to).value = document.getElementById(from).value;
      }

      function changeData(){
        $('#txt1').css('background','#ffffcc');
        google.script.run
        .withSuccessHandler(updateDisplay)
        .changeData();
      }

      function updateDisplay(t){
        $('#txt1').css('background','#ffffff');
        document.getElementById('cntdiv').innerHTML='<strong>Timer Running:</strong> Count= ' + ++cnt + ' <strong>Time:</strong> ' + t;
      }

     console.log('My Code');
   </script>
  </body>
</html>

Code.gs:

function onOpen(){
  SpreadsheetApp.getUi().createMenu('MyTools')
  .addItem('Show Timer SideBar', 'showTimerSideBar')
  .addToUi();
}

//This is the function driven by the clientside timer trigger It also creates new data sheets for each day.
function changeData(){
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('StockPrices');
  var rg=sh.getRange(3,1,1,sh.getLastColumn());
  var vA=rg.getValues();
  var n=new Date();
  var tmr=Utilities.formatDate(n, Session.getScriptTimeZone(), "HH:mm:ss");
  var ts=Utilities.formatDate(n, Session.getScriptTimeZone(), "E-MMddyy-HHmmss");
  var sheetTitle=Utilities.formatDate(n, Session.getScriptTimeZone(), "E-MMddyy");
  vA[0][0]=ts;
  if(isSheet(sheetTitle)){
     ss.getSheetByName(sheetTitle).appendRow(vA[0]);
  }else{
    var sht=ss.insertSheet(sheetTitle);
    var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues();
    hA[0][0]="TimeStamp";
    sht.appendRow(hA[0]);
    sht.appendRow(vA[0]);
  }
  checkStats(sheetTitle);
  return tmr;
}

function showTimerSideBar()
{
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('StockPrices');
  sh.getRange(5,2,1,sh.getLastColumn()-1).clearContent();//clears the sent row
  var ui=HtmlService.createHtmlOutputFromFile('datatimer').setTitle('Javascript Trigger Generator');
  SpreadsheetApp.getUi().showSidebar(ui);
}

function isSheet(sheetname){
  var r=false;
  var ss=SpreadsheetApp.getActive();
  var allSheets=ss.getSheets();
  for(var i=0;i<allSheets.length;i++){
    if(allSheets[i].getName()==sheetname){
      r=true;
      break;
    }
  }
  return r;
}

//This function checks stats and compares them to limits to determine if warning email messages should be sent
function checkStats(page) {
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName(page);
  var rg=sh.getRange(1,2,sh.getLastRow(),sh.getLastColumn()-1);
  var vA=rg.getValues();
  var minA=vA[1].slice(0);
  var maxA=vA[1].slice(0);
  var pchA=[];
  for(var i=2;i<vA.length;i++) {
    for(var j=0;j<vA[i].length;j++) {
      if(vA[i][j]>maxA[j]) {
        maxA[j]=vA[i][j];
      }
      if(vA[i][j]<minA[j]) {
        minA[j]=vA[i][j];
      }
    }
  }
  for(var i=0;i<minA.length;i++) {
    pchA.push(Number(((maxA[i]-minA[i])/maxA[i]) * 100).toFixed(2));
  }
  var spsh=ss.getSheetByName('StockPrices');
  var limitA=spsh.getRange(4,2,1,spsh.getLastColumn()-1).getValues();
  var nameA=spsh.getRange(1,2,1,spsh.getLastColumn()-1).getValues();
  var sentA=spsh.getRange(5,2,1,spsh.getLastColumn()-1).getValues();
  var msgA=[];
  for(var i=0;i<pchA.length;i++) {
    if(pchA[i]>limitA[i] && sentA[i]!="SENT") {
      msgA.push({name:nameA[i],change:pchA[i],limit:limitA[i],index:i});
    }
  }
  if(msgA.length>0){
    var html="<h1>Stocks Exceeding Change Limit</h1>";
    var text='Stocks Exceeding Change Limit\n';
    for(var i=0;i<msgA.length;i++) {
      html+=Utilities.formatString('<br />Stock Name: <strong>%s</strong><br />Limit: <strong>%s</strong><br />Change: <strong>%s</strong><hr width="100%"/><br />', msgA[i].name,msgA[i].limit,msgA[i].change);
      text+=Utilities.formatString('\nStock Name: %s\nLimit: %s\nChange: %s\n\n', msgA[i].name,msgA[i].limit,msgA[i].change);
      sentA[msgA[i].index]="SENT";
    }
    //GmailApp.sendEmail(recipient, 'Stocks Exceeding Change Limit', text, {htmlBody:html})
    spsh.getRange(5,2,1,spsh.getLastColumn()-1).setValues(sentA);
  }
}

This is what the Stock Prices page looks like:

在此处输入图片说明

This is what a daily data page looks like:

在此处输入图片说明

And this is what the timer sidebar looks like:

datatimer.html侧栏

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM