Service Spreadsheets failed while accessing document with ID xxx - javascript

What is causing the error
"Exception: Service Spreadsheets failed while accessing document with ID ..."
in my Google Apps Script code?
How can I fix this error and successfully import an Excel sheet (at the moment that sheet is located on Google drive, can I load it from my hard drive, when I run the script) into existing Google Sheet using Google Apps Script?
Is there a specific configuration or permission that needs to be set in order for the code to access and read an Excel file from Google Drive?
I am not very familiar with Google Apps Script and any advices are welcomed.
Here is my script
function importExcelSheet() {
// Ask which Excel file to load
var file = DriveApp.getFilesByName(Browser.inputBox("Enter the name of the Excel file to load:")).next();
// Read the Excel file
var spreadsheet = SpreadsheetApp.open(file);
// Get the first sheet from the Excel file
var sheet = spreadsheet.getSheets()[0];
// Import the sheet into the active Google Sheet
var currentSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var newSheet = currentSpreadsheet.insertSheet(sheet, 0);
// Set the name of the new sheet in the format "YYYY.MMM"
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth();
var monthName = Utilities.formatDate(date, "GMT", "MMM");
newSheet.setName(year + "." + monthName);
}
// Add the function to the Custom Google Sheet menu
function onOpen() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [{name: "Import Excel Sheet", functionName: "importExcelSheet"}];
spreadsheet.addMenu("Custom Menu", menuEntries);
}
I added "Drive API" to the Apps Script from "Services" menu.

This should work (haven't tested it) but this is not perfect because creating a copy of your source file, in order to read it with SpreadsheetApp
And you need to activate Advanced Drive API : https://developers.google.com/apps-script/advanced/drive
// your code:
// Ask which Excel file to load
var file = DriveApp.getFilesByName(Browser.inputBox("Enter the name of the Excel file to load:")).next();
//then:
if (file.getContentType() == "application/vnd.ms-excel" || file.getContentType() == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
var id = Drive.Files.insert({title: "new", mimeType: MimeType.GOOGLE_SHEETS}, file.copyBlob()).id;
var ss = SpreadsheetApp.openById(id);
//back to your code
}

Related

Upload PDF file in Google sheet using Google apps script

I am trying to upload pdf file to a single cell in google sheet just like we insert image in a google sheet cell. I've searched for quite some time now, but haven't been able to find any solutions to this. I have tried the following code:
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "File...", functionName: "doGet"});
ss.addMenu("Attach ...", menuEntries);
}
function doGet(e) {
var app = UiApp.createApplication().setTitle("upload attachment into Google Drive");
SpreadsheetApp.getActiveSpreadsheet().show(app);
var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
var formContent = app.createVerticalPanel();
form.add(formContent);
formContent.add(app.createFileUpload().setName('thefile'));
formContent.add(app.createHidden("activeCell", SpreadsheetApp.getActiveRange().getA1Notation()));
formContent.add(app.createHidden("activeSheet", SpreadsheetApp.getActiveSheet().getName()));
formContent.add(app.createHidden("activeSpreadsheet", SpreadsheetApp.getActiveSpreadsheet().getId()));
formContent.add(app.createSubmitButton('Submit'));
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
app.createLabel('saving...');
var fileBlob = e.parameter.thefile;
var doc = DriveApp.getFolderById('0B0uw1JCogWHuc29FWFJMWmc3Z1k').createFile(fileBlob);
var label = app.createLabel('file uploaded successfully');
var value = 'hyperlink("' + doc.getUrl() + '";"' + doc.getName() + '")'
var activeSpreadsheet = e.parameter.activeSpreadsheet;
var activeSheet = e.parameter.activeSheet;
var activeCell = e.parameter.activeCell;
var label = app.createLabel('file uploaded successfully');
app.add(label);
SpreadsheetApp.openById(activeSpreadsheet).getSheetByName(activeSheet).getRange(activeCell).setFormula(value);
app.close();
return app;
}
Since UiApp has been deprecated so it shows the error "UiApp has been deprecated. Please use HtmlService instead". I have tried the following line to avoid UiApp error but of no use:
var app = HtmlService.createHtmlOutput();
Is there any workaround that we can get to avoid this error? Thank you.
I believe your goal is as follows.
From your following comments,
I have pdf file in local pc, I would have a google sheet add-on with an option "file upload". I would click on that, it will upload file in the Drive folder which we have specified in script and the active google sheet cell will show the confirmation message.
I want to put the message in currently active cell of the sheet
You wanted to upload a PDF file on the local PC to Google Drive. And you want to put the confirmation message to a current active cell. You want to achieve this by a sidebar using HTML and Google Apps Script.
In this case, how about the following sample script?
Sample script:
Google Apps Script side: Code.gs
Please copy and paste the following script to the script editor of Google Spreadsheet as the script file and save the script.
const openSidebar = _ => SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile("index"));
function upload(e){
const message = "sample confirmation message"; // Please set your confirmation message.
DriveApp.createFile(Utilities.newBlob(...e));
SpreadsheetApp.getActiveRange().setValue(message);
}
HTML&Javascript side: index.html
Please copy and paste the following script to the script editor of Google Spreadsheet as the HTML file and save the script.
<form>
<input type="file" name="file" onchange="upload(this.parentNode)" accept=".pdf,application/pdf" />
</form>
<script>
function upload(e){
const file = e.file.files[0];
const fr = new FileReader();
fr.onload = e => google.script.run.upload([[...new Int8Array(e.target.result)], file.type, file.name]);
fr.readAsArrayBuffer(file);
}
</script>
Testing:
When you run the function openSidebar, the sidebar is opened. And when you select the file from the input tag, the file is uploaded to the root folder of Google Drive, and the confirmation message is put to the active cell.
Note:
In this method, the maximum file size is 50 MB because of the specification of the Google Apps Script side. Please be careful about this.
This is a simple sample script for achieving the goal of your question. So please modify this for your actual situation.
Reference:
Dialogs and Sidebars in Google Workspace Documents

Copy a spreadsheet file to Google Drive and replace all the formulas with values

I have a script which copys/clones an Google Spreadsheet and all tabs, which works fine but it I would like it to paste as values.
Here is what i have at the moment
function cloneGoogleSheet() {
var destFolder = DriveApp.getFolderById("your_drive_folder_id");
DriveApp.getFileById("your_drive_source_file_id").makeCopy("particular_file_name", destFolder);
}
Solution:
The comments provide an explanation of each step:
function cloneGoogleSheet() {
// get the destination folder
const destFolder = DriveApp.getFolderById("your_drive_folder_id");
// make a copy of a spreadsheet file
const file = DriveApp.getFileById("your_drive_source_file_id")
.makeCopy("particular_file_name", destFolder);
// get the spreadsheet file you just created
const ss = SpreadsheetApp.openById(file.getId());
// get all the sheets of the spreadsheet file
const sheets = ss.getSheets();
// for every sheet copy only the contents
sheets.forEach(sh=>{
let rng = sh.getDataRange();
rng.copyTo(rng, {contentsOnly:true});
SpreadsheetApp.flush();
});
}
Please note:
If the values are coming from an importrange formula then you need to manually allow it before you overwrite the sheet with the values. Because if you don't allow it, then importrange does not return anything.
In this case:
run the version of your script (in your original question)
go to the newly created spreadsheet and manually allow the importranges
run the following script:
function copyValues(){
const ss = SpreadsheetApp.getActive(); // in case you execute the script
bound to the spreadsheet
// const ss = SpreadsheetApp.openByUrl("spreadsheet_url") // in case you
run it from standalone or other script
// get all the sheets of the spreadsheet file
const sheets = ss.getSheets();
// for every sheet copy only the contents
sheets.forEach(sh=>{
let rng = sh.getDataRange();
rng.copyTo(rng, {contentsOnly:true});
SpreadsheetApp.flush();
});
}
If you execute this code from the newly created spreadsheet file, namely you have a script bound to that, then you can use SpreadsheetApp.getActive(). If you run the code from a standalone script or a script bound to another spreadsheet, then you need to specify the url of the newly created spreadsheet, therefore you can use either openById or openByUrl as in the example above.

gscript not picking the latest mail while trying to save the csv into google sheet

So I have a google app script where I search a mail based on subject line and then take that csv and update it in an google sheet. This worked fine the first time. But going forward when I got emails with the same subject line it still pick the content of the first email and not the latest .How can I fetch data from the latest mail.
function importCSVFromGmail() {
var threads = GmailApp.search("email subject);
var message = threads[0].getMessages().slice(-1);
Log.logger(message);
var attachment = message.getAttachments()[0];
Log.logger(message.getAttachments()) ;
// Is the attachment a CSV file
if (attachment.getContentType() === "text/csv") {
var sheet = SpreadsheetApp.getActiveSheet();
var csvData = Utilities.parseCsv(attachment.getDataAsString(), ",");
// Remember to clear the content of the sheet before importing new data
sheet.clearContents().clearFormats();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
}
You should be able to get the last or most recent message like that :
var message = threads[0].getMessages().slice(-1)

How to log Google Drive File Names to Google Sheets using Google Apps Script

So I am trying to log files (and their Id) from my Drive to a spreadsheet using Google Apps Script. The problem is that I don't know how to add content to rows of a Google Sheets document.
I know how to log my files and their Id:
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
Logger.log(file.getId());
}
Now I would like to log the Name and Id of my files from one folder to a Google sheet. Does anybody know how to achieve this?
You'll need to get the spreadsheet, and add the file names to a 2D array. The following code requires you to enter the spreadsheet file ID and the sheet tab name.
function logFilesToSheet() {
var arrayForOneRow,file,id,name,outerArray,sh,ss;
id = "";//Enter your spreadsheet file id here
name = "";//Enter the sheet tab name here
ss = SpreadsheetApp.openById(id);
sh = ss.getSheetByName(name);
outerArray = [];
var files = DriveApp.getFiles();
while (files.hasNext()) {
file = files.next();
//Logger.log(file.getName());
//Logger.log(file.getId());
arrayForOneRow = [];//Reset on each loop - Each row needs a new array
arrayForOneRow.push(file.getName());
arrayForOneRow.push(file.getId());
outerArray.push(arrayForOneRow);
}
sh.getRange(sh.getLastRow() + 1,1,outerArray.length,2).setValues(outerArray);
}

send email with different PDFs to different emails attachment

I am trying to do automate send email to multiple sender(10 emails) with different PDFs(10). Is there a way to attach a pdf in the spreadsheet column next to email address? Then send email with sales quote in pdf as attachment. Is this can be done in JS in google sheet.
Appreciate if someone help me out.
If you're using Google Sheets it's possible, but you have to get creative. In fact you can send emails, with javascript, from google sheets using google scripts. I think if you get creative with a hidden sheet in the same workbook, have a formula populate that sheet with the layout of the PDF, then export that sheet as a PDF to attach to the email... it's doable.
You may find some inspiration here.
Basic send email from google sheets example here.
So, JavaScript runs in the client side. It means that your code is running the user browser. In a brief, you can't send emails just using JavaScript. You're going to need a server to do that.
For example, you may use Spring Boot with Java that already has a lot implemented method that makes your task, i.e, sending an email, super easy.
Have a look at http://spring.io/projects/spring-boot
You can do this by following the below steps,
Uploading the 10 attachments on one google drive folder
On your google sheet add the below script to get the file id
function listFilesInFolder() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileID").activate(); //The name of the google sheet is FileID in my case
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow(["File Name", "File-Id"]);
//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
var folder = DriveApp.getFolderById("*[Enter Folder ID here]*");
var contents = folder.getFiles();
var cnt = 0;
var file;
while (contents.hasNext()) {
var file = contents.next();
cnt++;
data = [
file.getName(),
file.getId(),
];
sheet.appendRow(data);
}
}
Build a simple script to send emails and have your 10 emails on one column and all the File IDs generated from the above code on the next column. Below is a sample script to send emails from spreadsheets,
function sendEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Emails").activate(); // Emails is the sheet which has the email and File ID columns
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1, 1).getValue(); // Template is the sheet which has my email body
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 1).getValue(); //Email IDs are on the first column for me
var currentAttachment = ss.getRange(i, 2).getValue(); //Assuming your File IDs are on the second column
var waiver = DriveApp.getFileById(currentAttachment);
var liabilityWaiver = waiver.getAs(MimeType.PDF);
MailApp.sendEmail(currentEmail, subjectLine, messageBody, {attachments:[liabilityWaiver],
cc:'abc#abc.com'}); // the cc is in case you want to CC someone else on the email
I hope this helps!

Categories

Resources