0

I currently have a GoogleSheet, with 2 GoogleApp Scripts that work more or less how I want them too, but I could use a little help in refining them to get them working perfectly.

I have 1 script that scans through my email, looks for a mail's subject and then pulls it to my Google Drive if it matches.

Script 1: Pull from Gmail to GDrive

function importData() {
  var fSource = DriveApp.getFolderById('0B3h9TQiHV_rjR04xTlctb2s2Qms'); // reports_folder_id = id of folder where csv reports are saved
  var fi = fSource.getFilesByName('CR Logs this week.csv'); // latest report file
  var ss = SpreadsheetApp.openById('1OuEXVjZzPwfdcEW8eIOtNAeS4HJeTn_rw8w5o5Ja-Fo'); // data_sheet_id = id of spreadsheet that holds the data to be updated with new report data

  if ( fi.hasNext() ) { // proceed if "CR Logs this week.csv" file exists in the reports folder
    var file = fi.next();
    var csv = file.getBlob().getDataAsString();
    var csvData = CSVToArray(csv); // see below for CSVToArray function
    var newsheet = ss.insertSheet('NEWDATA'); // create a 'NEWDATA' sheet to store imported data
    // loop through csv data array and insert (append) as rows into 'NEWDATA' sheet
    for ( var i=0, lenCsv=csvData.length; i<lenCsv; i++ ) {
      newsheet.getRange(i+1, 1, 1, csvData[i].length).setValues(new Array(csvData[i]));
    }
    /*
    ** report data is now in 'NEWDATA' sheet in the spreadsheet - process it as needed,
    ** then delete 'NEWDATA' sheet using ss.deleteSheet(newsheet)
    */
    // rename the CR Logs this week.csv file so it is not processed on next scheduled run
    file.setName("CR Logs this week.csv-"+(new Date().toString())+".csv");
  }
};


// http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm
// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.

function CSVToArray( strData, strDelimiter ) {
  // Check to see if the delimiter is defined. If not,
  // then default to COMMA.
  strDelimiter = (strDelimiter || ",");

  // Create a regular expression to parse the CSV values.
  var objPattern = new RegExp(
    (
      // Delimiters.
      "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +

      // Quoted fields.
      "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +

      // Standard fields.
      "([^\"\\" + strDelimiter + "\\r\\n]*))"
    ),
    "gi"
  );

  // Create an array to hold our data. Give the array
  // a default empty first row.
  var arrData = [[]];

  // Create an array to hold our individual pattern
  // matching groups.
  var arrMatches = null;

  // Keep looping over the regular expression matches
  // until we can no longer find a match.
  while (arrMatches = objPattern.exec( strData )){

    // Get the delimiter that was found.
    var strMatchedDelimiter = arrMatches[ 1 ];

    // Check to see if the given delimiter has a length
    // (is not the start of string) and if it matches
    // field delimiter. If id does not, then we know
    // that this delimiter is a row delimiter.
    if (
      strMatchedDelimiter.length &&
      (strMatchedDelimiter != strDelimiter)
    ){

      // Since we have reached a new row of data,
      // add an empty row to our data array.
      arrData.push( [] );

    }

    // Now that we have our delimiter out of the way,
    // let's check to see which kind of value we
    // captured (quoted or unquoted).
    if (arrMatches[ 2 ]){

      // We found a quoted value. When we capture
      // this value, unescape any double quotes.
      var strMatchedValue = arrMatches[ 2 ].replace(
        new RegExp( "\"\"", "g" ),
        "\""
      );

    } else {

      // We found a non-quoted value.
      var strMatchedValue = arrMatches[ 3 ];

    }

    // Now that we have our value string, let's add
    // it to the data array.
    arrData[ arrData.length - 1 ].push( strMatchedValue );
  }

  // Return the parsed data.
  return( arrData );
};

The second script then looks through my Google Drive for a matching file name, then imports it to the Google Sheet.

Script 2: Import from GDrive to GSheet

// GLOBALS
//File extension
var fileTypesToExtract = ['csv'];
//Name of the GDrive folder it will be placed
var folderName = 'Reports';
//Name of the label which will be applied after processing the mail message
var labelName = 'ReportToDrive';



function GmailToDrive(){
  //query to search mails
  var query = 'CR Logs this week';
  //filename:csv; //'after:'+formattedDate+
  for(var i in fileTypesToExtract){
  query += (query == '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
  }
  query = 'in:inbox has:nouserlabels ' + query;
  var threads = GmailApp.search(query);
  var label = getGmailLabel_(labelName);
  var parentFolder;
  if(threads.length > 0){
  parentFolder = getFolder_(folderName);
  }
  for(var i in threads){
  var mesgs = threads[i].getMessages();
  for(var j in mesgs){
      //get attachments
      var attachments = mesgs[j].getAttachments();
      for(var k in attachments){
      var attachment = attachments[k];
      var isFileType = checkIfCSV_(attachment);
      if(!isFileType) continue;
      var attachmentBlob = attachment.copyBlob();
        var file = DriveApp.createFile(attachmentBlob);
        parentFolder.addFile(file);
      }
  }
  threads[i].addLabel(label);
  }
}

//This function will get the parent folder in Google drive
function getFolder_(folderName){
  var folder;
  var fi = DriveApp.getFoldersByName(folderName);
  if(fi.hasNext()){
    folder = fi.next();
  }
  else{
    folder = DriveApp.createFolder(folderName);
  }
  return folder;
}

//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
  n = parseInt(n);
  var today = new Date();
  var dateNDaysBack = new Date(today.valueOf() - n*2);
  return dateNDaysBack;
}

function getGmailLabel_(name){
  var label = GmailApp.getUserLabelByName(name);
  if(label == null){
  label = GmailApp.createLabel(name);
  }
  return label;
}

//this function will check for filextension type.
// and return boolean
function checkIfCSV_(attachment){
  var fileName = attachment.getName();
  var temp = fileName.split('.');
  var fileExtension = temp[temp.length-1].toLowerCase();
  if(fileTypesToExtract.indexOf(fileExtension) != -1) return true;
  else return false;
}

The Goal

I have a piece of software that produces reports in a CSV format, these reports are emailed to me every night at midnight. What I would like to happen is this:

  1. Script 1 pulls CSV from email and imports it to GDrive
  2. Script 2 to import the data to the Google Sheet
  3. Repeat the above on the next night, replacing (and discarding) the previous imported data

Currently, it pulls from my GMail into my GDrive ok. But I can't get it to replace the old data / delete the old data and import the new data.

Would be grand if someone with more experience could help me out!

SL8t7
  • 617
  • 2
  • 9
  • 27
  • This [SO question](http://stackoverflow.com/questions/28997832/replace-entire-sheet-with-another-in-google-apps-scripts) may help you with replacing data using apps script. Or check this [tutorial](https://zapier.com/learn/google-sheets/google-apps-script-tutorial/) that will place data updates automatically at the bottom of the sheets. Hope it helps! – Mr.Rebot Sep 12 '16 at 14:29

1 Answers1

0

So, I managed to figure this out by myself in the end.

//function CopyData() {
       var source = SpreadsheetApp.openById('xxx');
       var sourcesheet = source.getSheetByName('NEWDATA');
       var target = SpreadsheetApp.openById('xxx')
       var targetsheet = target.getSheetByName('Data');
       var targetrange = targetsheet.getRange(2, 1, sourcesheet.getLastRow(), sourcesheet.getLastColumn());
       var rangeValues = sourcesheet.getRange(2, 1, sourcesheet.getLastRow(), sourcesheet.getLastColumn()).getValues();
       targetrange.setValues(rangeValues);
       ss.deleteSheet(newsheet)    

This copies the data from NEWDATA, the sheet the Script 2 above creates, and then duplicates it to the sheet Data, replacing whatever is already there.It then deletes the NEWDATA sheet, so that the script can run on the next night.

SL8t7
  • 617
  • 2
  • 9
  • 27