Google Sheets save data range to PDF - google-apps-script

I am trying to save a sheet as a PDF in my drive - and I've been successful with this code:
function createPDF() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getActiveSheet()
var data = sheet.getDataRange().getValues()
var folder = DriveApp.getFolderById('my folder ID')
var tempFile = SpreadsheetApp.create("TempSheetv2")
sheet.copyTo(SpreadsheetApp.openById(tempFile.getId()))
var tempSS = SpreadsheetApp.openById(tempFile.getId())
var tempSheet = tempSS.getSheetByName('Sheet1')
tempSS.deleteSheet(tempSheet)
var blob = SpreadsheetApp.openById(tempFile.getId()).getAs('application/pdf')
var pdf = folder.createFile(blob).setName("Test PDF for 8th Grade")
DriveApp.getFileById(tempFile.getId()).setTrashed(true)
console.log(data)
}
The only problem is - the PDF has 27 pages (26 of which are blank). Is there a way to limit the PDF to only the data range?

function createPDF() {
var ss = SpreadsheetApp.getActive()
var sheet = ss.getActiveSheet();
const name = sheet.getName();//change
ss.getSheets().filter(sh => sh.getName() != name).forEach(s => s.hideSheet());//change
var data = sheet.getDataRange().getValues()
var folder = DriveApp.getFolderById('folderid')
var tempFile = SpreadsheetApp.create("TempSheetv2")
sheet.copyTo(SpreadsheetApp.openById(tempFile.getId()))
var tempSS = SpreadsheetApp.openById(tempFile.getId())
var tempSheet = tempSS.getSheetByName('Sheet1')
tempSS.deleteSheet(tempSheet)
var blob = SpreadsheetApp.openById(tempFile.getId()).getAs('application/pdf')
folder.createFile(blob).setName("Test PDF for 8th Grade")
DriveApp.getFileById(tempFile.getId()).setTrashed(true)
console.log(data)
}

Related

Copy Specific Sheet from Drive Folder and Paste Data into Active Sheet

I have 10 to 15 Files in the Drive Folder All files have more than 1 Google sheets in it with some sort of Conditional Formatting.
I want to copy the Specific Sheet Named "MasterSheet" from each File and Combine the data into the Active Sheet where from script is bieng run.
Copied data should keep conditional formatting cell color. I will appreciate the help. Thanks
function myFunction()
{
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
for(var y in spreadSheet.getSheets())
{
spreadSheet.getSheets()[y].copyTo(ActiveSpreadSheet);
}
}
}
UPDATE to check if there's a sheet called that way:
function copywithLog()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("16CxTO70ipcUt8U_beokid3vFOOLGTnPh");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var sheets = spreadSheet.getSheets()
var filtered = sheets.filter(n => ["DATA"].lastIndexOf(n.getSheetName()) == 0)
if (filtered.length==1){
var newsheet = spreadSheet.getSheetByName('DATA').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
Logger.log("Process successfully finished with the workbook named '"+spreadSheet.getName()+"'")}
else Logger.log("The worbook named '"+spreadSheet.getName()+ "' does not have a sheet called DATA")
}
}
It returns something like this:
UPDATE:
function copyinsamesheet()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var activeSpreadSheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
var newsheet = spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet)
newsheet.getDataRange().copyTo(activeSpreadSheet.getRange(activeSpreadSheet.getLastRow()+2,1))
destinsheet.deleteSheet(newsheet)
}
}
If it has always the same name, you can try with this:
function copyMasterSheets()
{
var destinsheet = SpreadsheetApp.getActiveSpreadsheet()
var myFolder = DriveApp.getFolderById("FolderID");
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var ActiveSpreadSheet = SpreadsheetApp.getActive().getSheetByName(Sheet1);
var i = 1
while(spreadSheets.hasNext())
{
var sheet = spreadSheets.next();
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
spreadSheet.getSheetByName('MasterSheet').copyTo(destinsheet).setName('MasterSheet '+i)
i++
}
}
An addendum to the answer by #Martin.
This takes the data on the various "Master Sheets" and copies it to a single sheet.
The range of data on each sheet is established dynamically, and is stacked down the page.
function copyMasters(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var target = ss.getSheetByName('Sheet1')
// idetify the starting row
var activeStartRow = 1
// get an array of all the sheets with names like "MasterSheet"
var sheetList = new Array
var sheets = ss.getSheets()
//var sourcesheet = ss.getSheets().find(sheet => sheet.getName().includes("MasterSheet"))
var mastersheets = sheets.filter(sheet => sheet.getName().includes("MasterSheet"))
//loop through the Master sheets
for (var i=0;i<mastersheets.length;i++){
var mastername = mastersheets[i].getName()
var master = ss.getSheetByName(mastername)
var masterLC = master.getLastColumn()
var masterLR = master.getLastRow()
// calculate the start row for the target sheet
if (activeStartRow==1){
var startRow =1
}else{
var startRow=startRow+masterLR
}
activeStartRow = 0
var rangeToCopy = master.getRange(1, 1, masterLR,masterLC)
//Logger.log("DEBUG: range to copy:"+rangeToCopy.getA1Notation())
var targetRange = target.getRange(startRow, 1, masterLR,masterLC)
//Logger.log("DEBUG: target range:"+targetRange.getA1Notation())
rangeToCopy.copyTo(targetRange)
// Logger.log("DEBUG: copied the data for "+mastername)
}
}
SAMPLE

App script: copy data from folder to single spreadsheet

I am working on a script to copy all the all data from sheets saved in a folder and concatenate them to a single spreadsheet.
The variable combinedData is not returning any data when I run it through the logger outside the while loop. Any ideas why this is happening?
// DATA CONCATINATION
function Data_concat() {
var folder = DriveApp.getFolderById("1Rky5tOyrTMJ15uhTog1ltBMwONap7Rx1");
var filesIterator = folder.getFiles();
var file;
var filetype;
var ssID;
var combinedData = [];
var data;
while(filesIterator.hasNext()){
file = filesIterator.next();
filetype = file.getMimeType();
if(filetype === "application/vnd.google-apps.spreadsheet"){
ssID = file.getId();
data = getDatafromSS(ssID);
combinedData = combinedData.concat(data);
}//end of if
}//end of while
Logger.log(combinedData)
//var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("raw_Data");
//ws.getRange("A2:J").clearContent();
//ws.getRange(2,1,combinedData.length, combinedData[0].length).setValues(combinedData)
}//end of Data_concat
//GET DATA FROM TARGET SHEET
function getDatafromSS(ssID){
var ss = SpreadsheetApp.openById(ssID);
var ws = ss.getSheets()[0];
var data = ws.getRange("A2:G" + ws.getLastRow()).getValues();
return data;
}
Save Data in all Spreadsheets in a folder
On Different Sheets:
function saveDataInAllSheetsInAFolder() {
const tss = SpreadsheetApp.getActive();
const tssnames = tss.getSheets().map(sh => sh.getName()).flat();
const fldr = DriveApp.getFolderById("Folderid");
const files = fldr.getFilesByType(MimeType.GOOGLE_SHEETS);
while(files.hasNext()) {
let file = files.next();
let ss = SpreadsheetApp.openById(file.getId());
ss.getSheets().forEach((sh,i) => {
let vs = sh.getDataRange().getValues();
let nsh = tss.insertSheet(ss.getName() + "-" + sh.getName() + "-" + Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S"));
nsh.getRange(1,1,vs.length,vs[0].length).setValues(vs)
})
}
}
google-apps-script reference
Learn More
On Same Sheet:
function saveDataInAllSheetsInAFolder() {
const tss = SpreadsheetApp.getActive();
const nsh = tss.insertSheet(Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S"));
nsh.getRange(1,1).setValue("Data Sheet " + Utilities.formatDate(new Date(),tss.getSpreadsheetTimeZone(),"yyyyMMdd HH:mm:ss.S") );
tss.setActiveSheet(nsh);
const tssnames = tss.getSheets().map(sh => sh.getName()).flat();
const fldr = DriveApp.getFolderById("Folderid");
const files = fldr.getFilesByType(MimeType.GOOGLE_SHEETS);
while(files.hasNext()) {
let file = files.next();
let ss = SpreadsheetApp.openById(file.getId());
ss.getSheets().forEach((sh,i) => {
let vs = sh.getDataRange().getValues();
nsh.getRange(nsh.getLastRow() + 1,1,vs.length,vs[0].length).setValues(vs);
})
}
}

Import data from URL into all sheets in a Google drive Folder

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]

Coping CSV file from Gmail Attachment by name

I want to only copy the CSV attachment to google sheets from an email.
The email has multiple attachments, in different file formats.
The attachment I want to copy over is consistently the same name in csv format.
I am using this code but its not pulling the attachment I want to copy to google sheet.
Can someone help me with this.
function getCSV() {
var myLabel = GmailApp.getUserLabelByName("I-Data New"); // specify label in gmail
var threads = myLabel.getThreads(0,1);
var msgs = GmailApp.getMessagesForThreads(threads);
var attachments = msgs[0][0].getAttachments();
var csv = attachments[0].getDataAsString();
var data = Utilities.parseCsv(csv);
var a = data.length ;
var b = data[0].length;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.openById('12ApSC0WVn1sZxb9VF6_CZR9L5xuGY5WHMLyyGMc').getSheetByName('IData');
sheet.getRange('A2:AM6026').clearContent();
var range = sheet.getRange(2,1, data.length,data[0].length);
range.setValues(data);
}
Loop over the attachments and get the filename. Quick edit to your existing code:
function getCSV() {
var myLabel = GmailApp.getUserLabelByName("I-Data New"); // specify label in gmail
var threads = myLabel.getThreads(0, 1);
var msgs = GmailApp.getMessagesForThreads(threads);
var attachments = msgs[0][0].getAttachments();
attachments.forEach(att => {
const name = att.getName()
if (name == "myFileName.csv") {
var data = Utilities.parseCsv(att.getDataAsString());
var sheet = SpreadsheetApp.openById('12ApSC0WVn1sZxb9VF6_CZR9L5xuGY5WHMLyyGMc').getSheetByName('IData');
sheet.getRange('A2:AM6026').clearContent();
var range = sheet.getRange(2, 1, data.length, data[0].length);
range.setValues(data);
}
})
}

Not able to fetch URLs from a column(Images URLs are saved in a column)in spreadsheet and create PDFs using urlfetchapp in Google App Script

I have a spreadsheet in which I have image urls saved in a column(column H), I am trying to create PDFs by fetching URLs from column and fetch the image stored to create my PDF
Here is my code
function createBulkPdf() {
var TEMPLATE_ID = '<<Template_id>>';
var PDF_FILE_NAME = '<<PDF folder id>>';
const copyFile = DriveApp.getFileById(TEMPLATE_ID);
const folderFile = DriveApp.getFolderById(PDF_FILE_NAME);
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var lastrow = sheet.getLastRow();
Logger.log(lastrow);
const data = sheet.getRange(2, 1, lastrow, 8).getValues();
var i = 2;
data.forEach(row => {
var url = createPdf(copyFile, folderFile, row);
sheet.getRange(i, 8).setValue(url);
Logger.log(i);
i = i + 1;
});
}
function createPdf(copyFile, folderFile, data) {
const copyfilenew = copyFile.makeCopy(folderFile);
const copyDoc = DocumentApp.openById(copyfilenew.getId());
const body = copyDoc.getBody();
var resp = UrlFetchApp.fetch(data[7]); //data[7] represents column H
Logger.log(resp.getContentText());
var next = body.findText("{al}");
var r = next.getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().appendInlineImage(resp.getBlob());
img.setWidth(100);
img.setHeight(80);
body.replaceText("{b}", data[1]); //body.toString().replaceText("{b}",b);
body.replaceText("{c}", data[2]);
body.replaceText("{d}", data[3]);
body.replaceText("{e}", data[4]);
body.replaceText("{f}", data[5]);
body.replaceText("{g}", data[6]);
copyDoc.saveAndClose();
const newpdffile = copyfilenew.getAs(MimeType.PDF);
var docid = folderFile.createFile(newpdffile).setName(data[3]).getId();
var filelink = "http://drive.google.com/uc?export=view&id=" + docid;
Logger.log(filelink);
folderFile.removeFile(copyfilenew);
return filelink;
}