I wrote a simple Google Apps Script to select an Excel file, convert it to Google Sheets via Blob, and then copy some cells from that to another Google Sheet. It doesn't work. 3 Questions:
Does Drive.Files.insert return a file object? I get an error saying
source.getSheetByName() is not a function right after setting source
to a Drive.Files.insert. (See below)
Whenever I try to put breakpoints in this section of code, they never break there, even though the code runs. How do I use the debugger/breakpoints here?
How would I specify a different location for the created Google Sheet ?
Thanks!
function convertExceltoGoogleSpreadsheet(e) {
var blob = Utilities.newBlob(e.bytes, e.mimeType, e.filename);
var excelFile = DriveApp.createFile(blob);
var fileName = e.filename;
var excelFile = DriveApp.getFilesByName(fileName).next();
var fileId = excelFile.getId();
var folderId = Drive.Files.get(fileId).parents[0].id;
var blob = excelFile.getBlob();
var resource = {
title: excelFile.getName(),
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: folderId}],
};
var source = Drive.Files.insert(resource, blob);
var sourceSheet = source.getSheetByName('Sheet1');
var target = SpreadsheetApp.getActiveSpreadsheet();
var targetSheet = target.getSheetByName("Sheet10");
Logger.log("The values are " + sourceSheet.getRange(1, 1, 10, 1).getValues());
Logger.log("The values are " + targetSheet.getRange(1, 1, 10, 1).getValues());
var targetrange = targetSheet.getRange(1, 1, 3, 5); //sourceSheet.getLastColumn());
var rangeValues = sourceSheet.getRange(1,1, 3,5).getValues(); //sourceSheet.getLastRow()-3, sourceSheet.getLastColumn()).getValues();
targetrange.setValues(rangeValues);
}
Related
Hoping someone can help me out with handling 'errors' in my script when there is no message/thread found. I thought I had done that with the IF statement based on message.lengh but its not working and still errors when no email is found matching the inputted search criteria (e). It works perfectly every time a message IS found.
Many thanks.
Moz
function ImportCDWFiles(e){
var Threads = GmailApp.search(e,0,1);
var Message = Threads[0].getMessages()[0];
var Attachment = Message.getAttachments()[0];
if (Threads.length >0){
Logger.log(Threads.length);
Logger.log(Attachment.getName())
var SourceFile = Folder.createFile(Attachment.copyBlob())
var SourceID = SourceFile.getId();
var XlsxBlob = Attachment[0]; //
var ConvertedSpreadsheetId = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS}, SourceFile).id; //XlsxBlob
Logger.log("Converted File ID= "+ ConvertedSpreadsheetId)
var Sheet = SpreadsheetApp.openById(ConvertedSpreadsheetId).getSheets()[0]; // There is the data in 1st tab.
var Data = Sheet.getDataRange().getValues();
//var Data = Sheet.getDataRange().offset(headerRowNumber, 0, sheet.getLastRow() - headerRowNumber).getValues();
var sheet = SpreadsheetApp.openById('SheetIDHere').getSheetByName('SheetName');
var range = sheet.getRange(LastRow+1, 1, Data.length, Data[0].length);
range.setValues(Data);
Drive.Files.remove(ConvertedSpreadsheetId); // Remove the converted file.
}
}
Modification points:
At var Message = Threads[0].getMessages()[0], when the length of Threads is 0, an error occurs.
If the attachment files are not included, an error occurs.
In your script, Folder and LastRow are not declared.
When these points are reflected in your script, how about the following modification?
Modified script:
function ImportCDWFiles(e) {
var Folder = DriveApp.getFolderById("###"); // Please set your folder ID.
var Threads = GmailApp.search(e, 0, 1);
if (Threads.length == 0) return;
var Message = Threads[0].getMessages()[0];
var Attachment = Message.getAttachments();
if (Attachment.length == 0) return;
Attachment = Attachment[0];
Logger.log(Attachment.getName())
var SourceFile = Folder.createFile(Attachment.copyBlob());
var ConvertedSpreadsheetId = Drive.Files.insert({ mimeType: MimeType.GOOGLE_SHEETS }, SourceFile).id;
Logger.log("Converted File ID= " + ConvertedSpreadsheetId);
var Sheet = SpreadsheetApp.openById(ConvertedSpreadsheetId).getSheets()[0];
var LastRow = Sheet.getLastRow();
var Data = Sheet.getDataRange().getValues();
var sheet = SpreadsheetApp.openById('###').getSheetByName('###'); // Please set your values.
var range = sheet.getRange(LastRow + 1, 1, Data.length, Data[0].length);
range.setValues(Data);
Drive.Files.remove(ConvertedSpreadsheetId);
}
Note:
Unfortunately, from your question, I cannot know the mimeType of the attachment file. So, I couldn't implement checking the mimeType of the attachment file. If you can know, when this check is implemented, the error related to the mimeType might be able to be avoided.
I have multiple spreadsheets in a folder, for each spreadsheet and I would like to get the matching data from an external file.
For example if my spreadsheet is called 'iphone 7' I would like to get in that sheet all the records from my external file containing 'iphone 7'
Here is how far I got (I am pretty new to scripting !) :
function myfunction()
{
var root = DriveApp.getFoldersByName("Produits");
while (root.hasNext())
{
var folder = root.next(); //If the folder is available, get files in the folder
var files = folder.getFiles();
while(files.hasNext()) //For each file,
{
var spreadsheet = SpreadsheetApp.open(files.next());
//import data from URL
var csvUrl = "https://incensy.tempurl.host/test-ct-flux.csv";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var sheets = spreadsheet.getSheets()
var sheetIndex=0
var sheet = sheets[sheetIndex]
sheet.getRange(2, 1, csvData.length, csvData[0].length).setValues(csvData);
//Only keep data that contains the file name
var name = spreadsheet.getName();
let range = sheet.getDataRange(),
maxRows = sheet.getMaxRows(),
srchCol_1 = 2,
srchPatt_1 = new RegExp(name, "i"),
newRangeVals = range.getValues().filter(r => r[0] && srchPatt_1.exec(r[srchCol_1])),
numRows = newRangeVals.length;
range.clearContent();
sheet.getRange(2,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
console.log('myfunction')
sheet.deleteRows(numRows + 1, maxRows - numRows);
}
}
}
There is something wrong in the second part of the code I cannot figure out.
In your situation, how about the following modification?
Modified script:
function myfunction() {
var keywords = ["sample1", "sample2"]; // Please set the keywords you want to filter to the column "C".
// Retrieve CSV data.
var csvUrl = "https://incensy.tempurl.host/test-ct-flux.csv";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent, ";");
// Retrieve Spreadsheet and put the CSV data.
var root = DriveApp.getFoldersByName("Produits");
while (root.hasNext()) {
var folder = root.next();
var files = folder.getFiles();
while (files.hasNext()) {
var spreadsheet = SpreadsheetApp.open(files.next());
var name = spreadsheet.getName().toUpperCase();
var values = csvData.reduce((ar, r) => {
if (!keywords.some(e => r[2].includes(e)) && r.join("").toUpperCase().includes(name)) {
ar.push(r);
}
return ar;
}, []);
if (values.length == 0) continue;
var sheet = spreadsheet.getSheets()[0];
sheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
}
}
In this modification, the CSV data is retrieved at the outside of the while loop. Using the retrieved CSV data and each Spreadsheet name, the data is put to the 1st tab of each Spreadsheet.
References:
reduce()
toUpperCase()
includes()
I am trying to import data from a specific URL into all sheets that are in a Google drive folder, then only keep the data that contains the name of the file.
Getting the files from the folder seems to be working but I cannot manage to have SpreasheetApp working (I think this is where the problem comes from). Maybe there is something wrong with how I manage to get ranges.
Here is what I have done so far :
function myfunction()
{
var root = DriveApp.getFoldersByName("Produits");
while (root.hasNext())
{
var folder = root.next(); //If the folder is available, get files in the folder
var files = folder.getFiles();
while(files.hasNext()) //For each file,
{
var spreadsheet = SpreadsheetApp.open(files.next());
//import data from URL
var csvUrl = "myURL";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var activeSpreadSheet = SpreadsheetApp.open(files);
var sheets = activeSpreadSheet.getSheets();
var sheet = sheets[sheetIndex]
sheet.getRange(2, 1, csvData.length, csvData[0].length).setValues(csvData);
// Always show 3 decimal points
var cell = sheet.getRange("D2:D");
cell.setNumberFormat("00");
//Only keep data that contains the file name
var name = sheet.getName();
let range = sheet.getDataRange(),
maxRows = sheet.getMaxRows(),
srchCol_1 = 2,
srchPatt_1 = new RegExp(name)
newRangeVals = range.getValues().filter(r => r[0] && srchPatt_1.exec(r[srchCol_1])),
numRows = newRangeVals.length;
range.clearContent();
sheet.getRange(2,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
sheet.deleteRows(numRows + 1, maxRows - numRows);
//Clean headers
var cell = sheet.getRange(1,1);
cell.setValue("Marchand");
var cell = sheet.getRange(1,2);
cell.setValue("Image");
var cell = sheet.getRange(1,3);
cell.setValue("Titre de l'offre");
var cell = sheet.getRange(1,4);
cell.setValue("Prix");
var cell = sheet.getRange(1,5);
cell.setValue("Lien");
var cell = sheet.getRange(1,6);
cell.setValue("Categorie");
}
}
}
Change
var activeSpreadSheet = SpreadsheetApp.open(files);
var sheets = activeSpreadSheet.getSheets();
to (spreadsheet has already been defined previously)
var sheets = spreadsheet.getSheets()
and give a value to sheetIndex, for instance
var sheets = spreadsheet.getSheets();
var sheetIndex=0
var sheet = sheets[sheetIndex]
In the below code, I'm getting the URL of a file in my Drive and using that in the formula =IMAGE(). However, the image isn't being displayed in the cell. I copied and pasted the URL that was being retrieved into my browser and it pulls up the image file. I also tried entering a different URL (from a Google image search) and it displayed the image in the cell. Here is a snippet of my code that isn't working:
//Function to populate Packing Instructions sheet
function createPackingInstructions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entryFormSheet = ss.getSheetByName('Entry Form');
var packingInstructionsSheet = ss.getSheetByName('Packing Instructions');
var poNumber = entryFormSheet.getRange(2, 2).getValue();
var drive = DriveApp;
var proofHorizontal = drive.getFilesByName('PO ' + poNumber + ' Proof Horizontal.png');
var proofRange = packingInstructionsSheet.getRange(1, 7);
Logger.log(poNumber);
//Starts by clearing the Instructions sheet
packingInstructionsSheet.getRange(11, 1, 30, 11).clear();
proofRange.clearContent();
Logger.log(proofHorizontal.hasNext());
//Gets image file URL
while (proofHorizontal.hasNext()) {
var file = proofHorizontal.next();
var proofName = file.getName();
var proofUrl = file.getUrl();
Logger.log(proofName);
Logger.log(proofUrl);
proofRange.setFormula('IMAGE("' + proofUrl + '", 1)');
}
}
I adjusted the code based on the advice in here to use the permalink version of the URL, but it has the same behavior; it inputs the formula correctly and the URL works when entered into my browser, but the image won't display in the cell. Here is the updated code:
//Function to populate Packing Instructions sheet
function createPackingInstructions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entryFormSheet = ss.getSheetByName('Entry Form');
var packingInstructionsSheet = ss.getSheetByName('Packing Instructions');
var poNumber = entryFormSheet.getRange(2, 2).getValue();
var drive = DriveApp;
var proofHorizontal = drive.getFilesByName('PO ' + poNumber + ' Proof Horizontal.png');
var proofRange = packingInstructionsSheet.getRange(1, 7);
var baseUrl = "http://drive.google.com/uc?export=view&id=";
Logger.log(poNumber);
//Starts by clearing the Instructions sheet
packingInstructionsSheet.getRange(11, 1, 30, 11).clear();
proofRange.clearContent();
Logger.log(proofHorizontal.hasNext());
//Gets image file URL
while (proofHorizontal.hasNext()) {
var file = proofHorizontal.next();
//file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
var proofId = file.getId();
var proofUrl = baseUrl+proofId;
Logger.log(proofUrl);
proofRange.setFormula('IMAGE("' + proofUrl + '", 1)');
}
}
Necro-ing my own questions, since I found a working solution:
My second code example above was close, but you need to use the "download" version of the URL, not the "view" version. See below:
var baseUrl = "https://drive.google.com/uc?export=download&id=";
//Gets image file URL
while (proofHorizontal.hasNext()) {
var file = proofHorizontal.next();
//This line may be necessary, depending on permissions
//file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
var proofId = file.getId();
var proofUrl = baseUrl+proofId;
}
Here is a link to some info on this: https://blog.appsevents.com/2014/04/how-to-bypass-google-drive-viewer-and.html
I am trying to write a google script that will allow me to go into my google drive folder called "MeadJohsnon" and pull 'Temperature Calibration.csv' to google sheets. I have never used google script before. Currently I have the "Save Email and Attachment" Add-ons. This add-on is pulling .cvs files that my team is sending me from the field. They use "TapForms" and then send the form via email to my gmail. So, I got the email sending that attachment to my google drive but I need help with the script, so Drive will automatically get those .cvs files and put the information into one google sheet. I say ONE google sheet because although I have a team sending in forms, all the forms have the same information on them.
This is what I have done so far. The fourth line gives me a
function loadingCSV() {
var ss=SpreadsheetApp.getActiveSpreadsheet()
var sht=ss.getActiveSheet();
sht.clearContents();
var data = loadFile();
var dataA =Utilities.parseCsv(data);
var rng = sht.getRange(1, 1, dataA.length, dataA[0].length);
rng.setValues(dataA);
}
I would just like feedback on how to fix my error or what I could do instead. As stated this is my first time using google script, my specialty is ASP.net lol not script. Thank you.
function loadingCSV() {
var ss=SpreadsheetApp.getActiveSpreadsheet()
var sht=ss.getActiveSheet();
sht.clearContents();
var data = loadFile();
var dataA =Utilities.parseCsv(data);
var rng = sht.getRange(1, 1, dataA.length, dataA[0].length);
rng.setValues(dataA);
}
function loadFile(filename,folderID)
{
var filename = (typeof(filename) !== 'undefined')? filename : 'Temperature Calibration.csv';
var folderID = (typeof(folderID) !== 'undefined')? folderID : '0B8m9xkDP_TJxUUlueHhXOWJMbjg';
var fldr = DriveApp.getFolderById(folderID);
var file = fldr.getFilesByName(filename);
var s = '';
while(file.hasNext())
{
var fi = file.next();
var target = fi.getName();
if(target == filename)
{
s = fi.getBlob().getDataAsString();
}
}
return s;
}
Okay this will append the files to the active spreadsheet you'll probably have to open the spreadsheet by id and use getSheetByName to get the sheet you want because this spreadsheet probably won't be active all the time when the trigger is running. I assume the the files all end in .csv. I rename them to .old after reading the data so that the program won't read them multiple times.
function appendingCSV() {
var ss=SpreadsheetApp.getActiveSpreadsheet()
var sht=ss.getActiveSheet();
var drng = sht.getDataRange();
var lastRow = drng.getLastRow();
var data = loadFiles();
var dataA =Utilities.parseCsv(data);
if(dataA.length>0)
{
var rng = sht.getRange(lastRow + 1, 1, dataA.length, dataA[0].length);
rng.setValues(dataA);
}
else
{
SpreadsheetApp.getUi().alert('No Data Returned from LoadFiles');
}
}
function loadFiles(folderID)
{
var folderID = (typeof(folderID) !== 'undefined')? folderID : '0B8m9xkDP_TJxUUlueHhXOWJMbjg';
var fldr = DriveApp.getFolderById(folderID);
var files = fldr.getFiles();
var s='';
var re = /^.*\.csv$/i;
while (files.hasNext())
{
var file = files.next();
var filename = file.getName();
if(filename.match(re))
{
s += file.getBlob().getDataAsString() + '\n';
file.setName(filename.slice(0,-3) + 'old');
}
}
return s;
}