I would like to be able to save just the active sheet as a pdf when clicking the save pdf button. Currently my code saves all of the sheets. How should I edit this code?
function onOpen() {
var submenu = [{name:"Save PDF", functionName:"saveAsPDF"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Save as PDF', submenu);
}
function saveAsPDF() {
const folderName = `social`;
const fileNamePrefix = SpreadsheetApp.getActiveSheet().getRange('a1').getValue();
const PhasePrefix = SpreadsheetApp.getActiveSheet().getRange('a2').getValue();
var actualSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
DriveApp.getFoldersByName(folderName)
.next()
.createFile(SpreadsheetApp.getActiveSpreadsheet()
.getBlob()
.getAs(`application/pdf`)
.setName(`${fileNamePrefix} - ${PhasePrefix} - ${Utilities.formatDate(new Date(), `GMT-8`, `yyyy-MM-dd`)}`));
var ui = SpreadsheetApp.getUi()
ui.alert('New PDF file created in ' + folderName )
}
first, be careful as the save as pdf option is going away in December. I'm not sure if this will affect the script function, but you'll get a warning when trying it manually. worth checking out...
(not tested)
save as pdf goes to the folder and saves the file. if you're already in the file, you just want to save one sheet, you probably don't need to go and grab the whole file.
I was going to write this up, but I think this link will do what you want best.
https://xfanatical.com/blog/print-google-sheet-as-pdf-using-apps-script/
Scroll down to the Source Code section.
You're looking for this function 'exportCurrentSheetAsPDF'
function exportCurrentSheetAsPDF() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var currentSheet = SpreadsheetApp.getActiveSheet()
var blob = _getAsBlob(spreadsheet.getUrl(), currentSheet)
_exportBlob(blob, currentSheet.getName(), spreadsheet)
}
This has the simple excerpt. I do encourage you to go to give them clicks and there's lots of other good stuff there. I think that is probably more than you wanted, but maybe things you didn't know you wanted...
Related
Trying to make a menu item that someone can open a slide, click a button, and it will save the Slide deck as a PDF and email it (using a pre-defined template). I started by working on the scripting for saving the PDF, but I am getting errors. Request help!
function onOpen() {
var ui = SlidesApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('RightTrak Mailer')
.addItem('Save PDF', 'SavePDF')
.addSeparator()
.addToUi();
}
function SavePDF() {
folderString = "1vozH-LotRA0xzZwWNxP-sVRirVvswSTl"
var blob =
DriveApp.getFileById("1zd7BecVSJupY0GOebJCTEQKwR_SDLWOxCeoRfwCL2fQ").getBlob();
var dir = DriveApp.getFolderById("1vozH-LotRA0xzZwWNxP-sVRirVvswSTl");
dir.DriveApp.createFile(blob);
SlidesApp.getUi()
.alert('Saved to ' + folderString + " " + blob.getName())
}
When I Created a test Google Slides and Added your Script the First Error I came Across was:
Exception: No item with the given ID could be found. Possibly because
you have not edited this item or you do not have permission to access
it.
Of course your HardCoded File ID Needed to be changed to mine. I did this with getActivePresnetation(). But there is the possibility you were getting an error becasue you had the wrong id. I also found code to get the Folder ID, but then was curious why you wanted to use the long Folder ID in your Saved Name String shown to the user on the alert. I changed that to the folder Name. But your choice, you can change with the indexing on the item returned by the getFolderInfo function. Shown below is code that gets both the Slide Deck and Folder Ids programmatically instead of having to paste them in. That should fix any errors you might have had with wrong Ids.
Your Line "dir.DriveApp.createFile(blob);" Has one problem, the 'dir' is a type Folder, that has its own method createFile. It does not need the DriveApp between dir and createFile. That line changes to: "dir.createFile(blob);" That is referenced Here: https://developers.google.com/apps-script/reference/drive/folder
I was able to get the following code to work on a Google Slide Deck and have it Save a Copy of the Slide Deck as a PDF.
function onOpen() {
var ui = SlidesApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('RightTrak Mailer')
.addItem('Save PDF', 'SavePDF')
.addSeparator()
.addToUi();
}
function getFolderInfo(inputFile)
{
// found at: https://stackoverflow.com/questions/26674758/google-apps-script-get-folder-name-from-file
var fileParents = inputFile.getParents();
while ( fileParents.hasNext() )
{
var folder = fileParents.next();
folderId = folder.getId();
folderName = folder.getName();
}
return [folderId, folderName];
}
function SavePDF() {
thisSlideDeck = SlidesApp.getActivePresentation();
thisSdId = thisSlideDeck.getId();
thisFile = DriveApp.getFileById(thisSdId);
thisFolderInfo = getFolderInfo(thisFile);
var blob = thisFile.getBlob();
var dir = DriveApp.getFolderById(thisFolderInfo[0]);
dir.createFile(blob);
SlidesApp.getUi().alert('Saved to ' + thisFolderInfo[1] + " " + blob.getName());
}
I wrote a script to log who and when opens a google doc. It works fine but the doc is a template for users to fill in so want to ensure whoever needs it will make a copy of the template through apps script.
I know users need edit access for the script to work but in terms of workarounds:
Is there a way for the script to still work if I give them a copy link or a template link?
Does it make more sense to use the google sheet as the base and pull from the google doc ID?
If that doesn't work than:
2) Is there a way to prompt them with a menu window to copy the file but delay it by x seconds on open?
//setups a count for the file
function setup() {
var propertyService = PropertiesService.getDocumentProperties();
propertyService.setProperty('viewCount', '0');
}
//logs the email and date of the user accessing the file
function onOpen(e) {
var count = parseInt(PropertiesService.getDocumentProperties().getProperty('viewCount'))+1;
PropertiesService.getDocumentProperties().setProperty('viewCount', count);
Logger.log(count);
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
sheet.getSheetByName('View Count').appendRow([user,date]);
}
You can add a menu item that creates a copy of the template for the user, logs the copy to the same sheet where you track who opens the file, and prompts the user to open their copy of the file to start working.
Steps
First: add these 3 functions.
The first, copyFile, creates a copy of the active document and names it the same plus the user's email. Then it logs the activity to the same change log, adding the new file's ID to the row. Finally, thanks to this nifty function it pops up a window with a link to the new file so the user can easily open it and start working.
The second, showAnchor, is the function that generates the HTML dialog box which presents the user a link to their new file.
The third, createMenu, adds a new menu item to the Google Docs nav bar, which prompts the user to copy the document. This, of course, triggers the copyFile function.
function copyFile() {
var thisDoc = DocumentApp.getActiveDocument()
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
var newCopy = DriveApp.getFileById(thisDoc.getId()).makeCopy(thisDoc.getName() + " " + user)
sheet.getSheetByName('View Count').appendRow([user,date,newCopy.getId()]);
var url = newCopy.getUrl()
showAnchor('Open Your File',url);
}
function showAnchor(name,url) {
var html = '<html><body>'+name+'</body></html>';
var ui = HtmlService.createHtmlOutput(html)
DocumentApp.getUi().showModelessDialog(ui," ");
}
function createMenu() {
const ui = DocumentApp.getUi();
const menu = ui.createMenu("Copy This Template");
menu.addItem("Copy", "copyFile");
menu.addToUi();
}
Then: add a call to createMenu() at the end of your onOpen script:
function onOpen(e) {
var count = parseInt(PropertiesService.getDocumentProperties().getProperty('viewCount'))+1;
PropertiesService.getDocumentProperties().setProperty('viewCount', count);
Logger.log(count);
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
sheet.getSheetByName('View Count').appendRow([user,date]);
createMenu();
}
I have this and I ran the debug and it did not give me any errors. Where can I put the search function for files with certain words? Any help will be greatly appreciated.
This was one I was trying to use
var filesIterator = folder.searchFiles('title contains "Untitled"');
function MoveFiles() {
var SourceFolder = DriveApp.getFolderById('abcdefghijklmnopqrstuvwxyz');
var SourceFiles = DriveApp.getFolderById('abcdefghijklmnopqrstuvwxyz').getFiles();
var DestFolder = DriveApp.getFolderById('1hbuV93CsdOeHkZWLES8BhXYMrayoKTBr');
while (SourceFiles.hasNext()) {
var file = SourceFiles.next();
DestFolder.addFile(file);
SourceFolder.removeFile(file);
}
}
Find and Move Files
This function will show a prompt where you can enter the string to complete the query 'title contains "the string"'. You also have to provide the id of the folder to search for and the id of the destination folder.
function findAndMoveFiles() {
var SourceFolder = DriveApp.getFolderById('Id');
var DestFolder = DriveApp.getFolderById('Id');
var result = SpreadsheetApp.getUi().prompt('Enter the string to complete the search query');
var qry = Utilities.formatString('title contains "%s"', result.getResponseText());//you just need to enter the string that gets put into %s
var SourceFiles = SourceFolder.searchFiles(qry);
while (SourceFiles.hasNext()) {
var file = SourceFiles.next();
DestFolder.addFile(file);
SourceFolder.removeFile(file);
}
}
Enter the script into a gs file in the script editor. You can run the script from the script editor once it start a dialog prompt will appear on the spreadsheet so make sure to switch back to the spreadsheet at that point.
You can also run it from a menu by entering in the following code:
function onOpen(){
SpreadsheetApp.getUi().createMenu('Search Menu')
.addItem('Find and Move Files', 'findAndMoveFiles')
.addToUi()
}
You will need to save it to the Script Editor and select it and run it one time to get the menu into the spreadsheet. Also it will display in the spreadsheet upon opening the spreadsheet next time.
DriveApp Reference
UI Reference
Also checkout all of the features in the help menu of the Script Editor.
I found a script that will move my spreadsheet to a folder. How can I make it so that the functions runs when the spreadsheet is open. I will be applying this to a template so that everytime the template is opened, the "Copy of " spreadsheet file will automatically be moved to my Packing Lists folder.
Here's the code I have....
function MoveFileTo()
{
var docs=DocsList.find('Save Test');
var doc=docs[0]; /*Since we assume there is only one file with the name "Hello World", we take the index 0 */
var folders = doc.getParents();
var newFolder=DocsList.getFolder('Packing Lists');
doc.addToFolder(newFolder); // This will add the document to its new location.
var docParentFolder=folders[0];
doc.removeFromFolder(docParentFolder); // This will remove the document from its original location.
}
EDIT: I tried changing function MoveFileTo to onOpen() and onEdit() but it doesn't seem to work properly. Is there something I am missing?
Try use driveapp instead of doclist (it's deprecated). the impinball comment is really usefull, you should have a look at it.
Anyway here a working code:
function myFunction() {
var destFolder = DriveApp.getFolderById("FOLDER_ID_WHERE8YOU_WANT_TO_MOVE_YOUR_FILES");
var fileList = DriveApp.searchFiles("mimeType = 'application/vnd.google-apps.spreadsheet' and title contains 'FILE_TITLE'"); // change this search if necessary
var originalFileId="THE_ID_OF_THE_ACTUAL_SPREADSHEET_TO_BE_EXCLUDED_FROM_THE_SCRIPT_TREATMENT";
while(fileList.hasNext()){
var fileToMove = fileList.next();
if(fileToMove.getId()==originalFileId){
continue; // don't do anything if it's the original file
}
var papas = fileToMove.getParents();
destFolder.addFile(fileToMove); // do the job
while(papas.hasNext()){
papas.next().removeFile(fileToMove); // remove the actuals parents (can be more than one)
}
}
}
I am trying to extract the text from each Google document in a folder in Drive and paste the text into the first column of a Google spreadsheet so that the contents of file 1 are in A1, the contents of file 2 in A2 etc. Ultimately I am trying to recreate a database of the information stored in all these files, so if the text can be split by field so much the better, but I think this should be trivial in Excel using Text to Columns.
I have used a few snippets online to have a stab at it but I'm now stumped.
Here is my script as it stands:
//Function to extract the body from each document in a folder and copy it to a spreadsheet
function extract() {
//Define the folder we're working with ("Communication Passports") and get the file list
var folder = DocsList.getFolder("Communication Passports");
var contents = folder.getFiles();
//Define the destination spreadsheet file (CP) and set up the sheet to receive the data
var ss = SpreadsheetApp.openById("0AicdFGdf-Cx5dHFTX1R3Wm1RTEFTZ2d5ZmxuSjJSOHc");
SpreadsheetApp.setActiveSpreadsheet(ss);
Logger.log('File name: ' + ss.getName());
var sheet = SpreadsheetApp.getActiveSheet();
sheet.clear();
sheet.appendRow(["Name", "Date", "Contents", "URL", "Download", "Description"]);
//Set up other variables
var file;
var data;
//Loop through and collect the data (I don't actually need this - just borrowed the code from a snippet online - but it is SO CLOSE!)
//Sadly, getBody doesn't work on files, only on documents
for (var i = 0; i < contents.length; i++) {
file = contents[i];
data = [
file.getName(),
file.getDateCreated(),
file.getViewers(),
file.getUrl(),
"https://docs.google.com/uc?export=download&confirm=no_antivirus&id=" + file.getId(),
file.getDescription()
];
sheet.appendRow(data);
//Extract the text from the file (this doesn't work at present, but is what I actually need)
var doc = DocumentApp.openById(file.getId());
var body = doc.getBody();
//Find a way to paste the extracted body text to the spreadsheet
}
};
Any help would be very gratefully received - I'm not a programmer, I'm a teacher and the information is about children's learning needs at our school (someone deleted the database over summer and our backups only go back a month!).
Thanks,
Simon
Try to add:
var doc = DocumentApp.openById(file.getId());
body = doc.getBody().getText();
to return the actual contents of the document.
I wrote another function to parse the content into more usable chunks and then pass back to an entry in the data table and it worked fine.