Get files URLs from folders ID [duplicate] - javascript

I would like to get the files URL and Name from an array of folders ID, which I'm retrieing with a script.
I would like the result to be placed on the Files tab.
The script I'm using for getting the filesID is the following:
function Folders_URL() {
var ss=SpreadsheetApp.getActive().getSheetByName("Overview");
var fldr=DriveApp.getFolderById("someID");
var files=fldr.getFolders();
var names=[],f,str; while (files.hasNext()) {
f=files.next();
names.push([f.getId(), f.getName()]);
}
ss.getRange(4,2,names.length, 2).setValues(names);
}
For getting files Names with the URL, I use this code.
It would be very helpful if someone can join both codes or just getting the URLs and File names from the array of foldersID
function getFileNames() {
var sheet = SpreadsheetApp.getActive().getSheetByName("someLink");
//Range where the links are set
var links = sheet.getRange("F3:F").getValues();
var filenames = [];
for (var i = 0; i < links.length; i++) {
var url = links[i][0];
if (url != "") {
var filename = SpreadsheetApp.openByUrl(links[i][0]).getName();
filenames.push([filename]);
}
}
//Define cell range
var startRow = 3; // print in row 2 since row 1 is the header row
var fileNameColumn = 4; // Column B = column 2
var destinationCell = sheet.getRange(startRow, fileNameColumn, filenames.length, filenames[0].length);
destinationCell.setValues(filenames);
}
Please be aware that I cannot share any sheet since I have sensitive information from my end.
Thanks!
UPDATED ANSWER
New error when running the script:

Get Urls
I tested this code on my data and it works fine. If it's not working on your data then the problem is your data.
function getUrls() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const osh = ss.getSheetByName("Sheet1");
const vs = sh.getRange(4, 1, sh.getLastRow() - 3, sh.getLastColumn()).getValues();
let obj = { pA: [] };
vs.forEach((r, i) => {
let fldr = DriveApp.getFolderById(r[1]);
let files = fldr.getFilesByName(r[2]);
while (files.hasNext()) {
let file = files.next();
let name = file.getName();;
if (!obj.hasOwnProperty(name)) {
obj[name] = [file.getUrl()];
obj.pA.push(name)
} else {
obj[name].push(file.getUrl())
}
}
});
if (obj.pA.length > 0) {
let o = obj.pA.map(p => [p, obj[p].join('\n')]);
osh.clearContents();
if(o.length > 0) {
osh.getRange(1, 1, o.length, o[0].length).setValues(o);
}
}
}

Related

Change cell Data on Spreadsheet

I am trying to take a template spreadsheet, and copy it, then change the data and export as pdf, finally email it.
So far I can do everything except change it on the sheet. It even changes in the logger. Can someone help with this?
Code as follows:
function After_Submit(e, values){
var range = e.range;
var row = range.getRow(); //get the row of newly added form data
var sheet = range.getSheet(); //get the Sheet
var headers = sheet.getRange(1, 1, 1,5).getValues().flat(); //get the header names from A-O
var data = sheet.getRange(row, 1, 1, headers.length).getValues(); //get the values of newly added form data + formulated values
var values = {}; // create an object
for( var i = 0; i < headers.length; i++ ){
values[headers[i]] = data[0][i]; //add elements to values object and use headers as key
}
const pdfFile = Create_PDF(values);
sendEmail(e.namedValues['Your Email'][0],pdfFile);
}
function sendEmail(email,pdfFile,){
GmailApp.sendEmail(email, "Subject", "Message", {
attachments: [pdfFile],
name: "From Someone"
});
}
function Create_PDF(values, ) {
const PDF_folder = DriveApp.getFolderById("1t_BYHO8CqmKxVIucap_LlE0MhslpT7BO");
const TEMP_FOLDER = DriveApp.getFolderById("1TNeI1HaSwsloOI4KnIfybbWR4u753vVd");
const PDF_Template = DriveApp.getFileById('1Ye7DyJQOjA3J_EUOQteWcuASBCfqlA-_lzyNw0REjY8');
const newTempFile = PDF_Template.makeCopy(TEMP_FOLDER);
const openDoc = SpreadsheetApp.openById(newTempFile.getId());
const newOpenDoc = openDoc.getSheetByName("Sheet1");
var body = newOpenDoc.getDataRange().getValues();
for (const key in values) {
body = body.toString().replace("{{"+key+"}}", values[key]);
}
Logger.log(body);
newOpenDoc.getDataRange().setValues(body);
SpreadsheetApp.flush();
const BLOBPDF = newTempFile.getAs(MimeType.PDF);
const pdfFile = PDF_folder.createFile(BLOBPDF);
console.log("The file has been created ");
return pdfFile;
}
When I saw your script, in the for loop of the function Create_PDF, an array retrieved from the sheet is converted to a string. I thought that this might be the reason for your issue.
When this issue was removed, how about the following modification?
From:
var body = newOpenDoc.getDataRange().getValues();
for (const key in values) {
body = body.toString().replace("{{"+key+"}}", values[key]);
}
To:
values = Object.fromEntries(Object.entries(values).map(([k, v]) => [`{{${k}}}`, v]));
var body = newOpenDoc.getDataRange().getValues().map(r => r.map(c => values[c] || c));
By this modification, the converted value by values are put into the sheet.
Reference:
map()

Copy / paste background color from one column to another sheet in a column with matched values

In a sheet I have a column with values and background colors.
In another sheet, I have a column with the same values but in a random order.I would like a script that would paste the background color of the column from the first sheet into the column in the second sheet if their values match.
Source color:
Wished result:
My sheet
I tried to modify a script that works but removes the background color from the whole sheet. Here it is:
function copycolors() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('VALIDATION');
const cA = sh.getRange(6,3,sh.getLastRow()).getDisplayValues().flat();//values
const bA = sh.getRange(6,3,sh.getLastRow()).getBackgrounds().flat();//colors
let colors = {pA:[]};
cA.forEach((c,i) => {
colors[c]=bA[i];
colors.pA.push(c);
});
const osh = ss.getSheetByName('DATA');
const vs = osh.getDataRange().getDisplayValues();
const bs = osh.getDataRange().getBackgrounds();
let bgA = vs.map((r,i) =>{
r.forEach((c,j) =>{
let idx = colors.pA.indexOf(c);
if(~idx) {
bs[i][j] = colors[c];
}
});
return bs[i];
});
osh.getRange(1,1,bgA.length,bgA[0].length).setBackgrounds(bgA);
}
Try this modification:
function copycolors() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('VALIDATION');
const cA = sh.getRange(6,3,sh.getLastRow()).getDisplayValues().flat();//values
const bA = sh.getRange(6,3,sh.getLastRow()).getBackgrounds().flat();//colors
let colors = {pA:[]};
cA.forEach((c,i) => {
colors[c]=bA[i];
colors.pA.push(c);
});
const osh = ss.getSheetByName('DATA');
const vs = osh.getRange(4,12,osh.getLastRow()).getDisplayValues();
const bs = osh.getRange(4,12,osh.getLastRow()).getBackgrounds();
let bgA = vs.map((r,i) =>{
r.forEach((c,j) =>{
let idx = colors.pA.indexOf(c);
if(~idx) {
bs[i][j] = colors[c];
}
});
return bs[i];
});
osh.getRange(4,12,bgA.length,bgA[0].length).setBackgrounds(bgA);
}
From:
Result:
From your code I just modifed the destination row and column since you have the values fixed starting from row 4 and in column L. You don't need the Dynamic range getDataRange() used in your code as it will impact all the other cells in the Data Range.
Suggestion:
You can also add the code below to your onEdit()
if (col == 12) {
var value = range.getValue();
var validationSheet = ss.getSheetByName("VALIDATION");
var optionColor = validationSheet.createTextFinder(value).findNext().getBackground();
range.setBackground(optionColor);
}
Final Code:
function onEdit(e) {
var ss = e.source;
var sourceSheet = ss.getActiveSheet();
var shName = sourceSheet.getName();
var range = e.range;
var row = range.getRow();
var col = range.getColumn();
var destSheet = ss.getSheetByName("COMMENTAIRES");
if ((shName == "DATA" || shName == "EPHAD" || shName == "LIVRET") && (row > 4 && col >= 12 || col <= 16)) {
var dataToCopy = range.getValue();
var email = sourceSheet.getRange(row, 8).getValue();
var destRow = destSheet.createTextFinder(email).findNext().getRow();
destSheet.getRange(destRow, col).setValue(dataToCopy);
}
//ADDED SECTION
if (col == 12) {
var value = range.getValue();
var validationSheet = ss.getSheetByName("VALIDATION");
var optionColor = validationSheet.createTextFinder(value).findNext().getBackground();
range.setBackground(optionColor);
}
}
Result:

Reading excel file into array using javascript

I'm trying to read an excel file and create a multidimensional array in javascript with it.
The excel file will look like:
AA11 AA22 AN65
AB11 AB22 AN64
...
I need it to create an array that looks like:
[
[AA11, AA22, AN65],
[AB11, AB22, AN64]
]
So far, I've been able to bring up a file selection window, and I believe it's reading the file, I just think it might not be putting the data into the array correctly. This is what I have so far:
<script type="text/javascript">
$(function () {
$("#input").on("change", function () {
var excelFile,
var array = [[],[]];
fileReader = new FileReader();
$("#result").hide();
fileReader.onload = function (e) {
var buffer = new Uint8Array(fileReader.result);
$.ig.excel.Workbook.load(buffer, function (workbook) {
var column, row, newRow, cellValue, columnIndex, i,
worksheet = workbook.worksheets(0),
columnsNumber = 0,
gridColumns = [],
data = [],
worksheetRowsCount;
while (worksheet.rows(0).getCellValue(columnsNumber)) {
columnsNumber++;
}
for (columnIndex = 0; columnIndex < columnsNumber; columnIndex++) {
column = worksheet.rows(0).getCellText(columnIndex);
gridColumns.push({ headerText: column, key: column });
}
for (i = 1, worksheetRowsCount = worksheet.rows().count() ; i < worksheetRowsCount; i++) {
newRow = {};
row = worksheet.rows(i);
for (columnIndex = 0; columnIndex < columnsNumber; columnIndex++) {
cellValue = row.getCellText(columnIndex);
//newRow[gridColumns[columnIndex].key] = cellValue;
array[row,columnIndex] = cellValue;
}
window.alert(array[0][0]);
data.push(array);
}
</script>
Any help would be greatly appreciated.
Not sure what you're using to parse the Excel, is it IgniteUI ? For what it's worth, the free (community edition) of SheetJS, js-xlsx provides a few functions that produce exactly the output you needed, given the spreadsheet you provided.
The docs are a bit messy, but they are complete, the most interesting sections for this use-case are: Browser file upload form element under Parsing workbooks and XLSX.utils.sheet_to_json. You can run a test with the type of spreadsheet you provided in the code sample below:
$("#input").on("change", function (e) {
var file = e.target.files[0];
// input canceled, return
if (!file) return;
var FR = new FileReader();
FR.onload = function(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
// header: 1 instructs xlsx to create an 'array of arrays'
var result = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
// data preview
var output = document.getElementById('result');
output.innerHTML = JSON.stringify(result, null, 2);
};
FR.readAsArrayBuffer(file);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.14.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="file" id="input" accept=".xls,.xlsx,.ods">
<pre id="result"></pre>
Here the full solution aditionally I've added a group by category function
to demostrante that we can apply functions to the json array.
(async() => {
const url = "./yourfile.xlsx";
const data = await (await fetch(url)).arrayBuffer();
/* data is an ArrayBuffer */
const workbook = XLSX.read(data);
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const sheetValues = XLSX.utils.sheet_to_json(worksheet);
const groupByCategory = sheetValues.reduce((group, product) => {
const { category } = product;
group[category] = group[category] ?? [];
group[category].push(product);
return group;
}, {});
console.log(groupByCategory)
/* DO SOMETHING WITH workbook HERE */
})();

I need to list all the files in subfolders using google script

I am trying to make a summary sheet for all files in a folder. This is what I have so far, but I cannot figure out how to list the files in the subfolders of "folderid". Any ideas would be greatly appreciated.
//GLOBAL VARIABLES
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
function onOpen() {
ss.getRange(1, 1, 100, 10).clear({contentsOnly: true})
var id = "folderid";
var arr = [["CAPITAL PROJECT", "URLs", "OWNER"]];
var f = DriveApp.getFolderById(id).getFiles()
while (f.hasNext()) {
var file = f.next();
var name = file.getName()
var url = file.getUrl()
var own = file.getOwner().getName()
arr.push([name, url, own]);
ss.getRange(1,1, arr.length, arr[0].length).setValues(arr);
}
ss.getRange(2,1, arr.length, arr[0].length).sort(1)
var second = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2")
second.activate()
}
Once you get the main folder, you can get the sub-folders. If there are multiple sub-folders, you'll need an inner loop:
I've tested this code and it works:
function getAndListFilesInFolder() {
var arr,f,file,folderName,subFolders,id,mainFolder,name,own,sh,thisSubFolder,url;
sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sh.getRange(1, 1, 100, 10).clear({contentsOnly: true})
id = "Put_Your_FolderID_Here";
arr = [["CAPITAL PROJECT", "URLs", "OWNER","FOLDER"]];
mainFolder = DriveApp.getFolderById(id);
subFolders = mainFolder.getFolders();
folderName = mainFolder.getName();
f = mainFolder.getFiles();
while (f.hasNext()) {
file = f.next();
name = file.getName()
url = file.getUrl()
own = file.getOwner().getName()
arr.push([name, url, own, folderName]);
};
while (subFolders.hasNext()) {
thisSubFolder = subFolders.next();
f = thisSubFolder.getFiles();
folderName = thisSubFolder.getName();
while (f.hasNext()) {
file = f.next();
name = file.getName()
url = file.getUrl()
own = file.getOwner().getName()
arr.push([name, url, own,folderName]);
};
};
sh.getRange(1,1, arr.length, arr[0].length).setValues(arr);
sh.getRange(2,1, arr.length, arr[0].length).sort(1);
//var second = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2")
//second.activate()
}

Compare value to another spreadsheet using array loop and write new values

Hello all I'm having trouble implementing array loops in my project... Here is what I want to do.
I have a spreadsheet called "Red Book" this sheet gets updated regularly once the staff have updated it I have a column where they can select to submit the data they've just entered on that specific row (editing this column calls an onEdit function).
The data will then be written to another spreadsheet (different file) called "Raw Data"
For each submit I have a unique identifier. I need the onEdit code to do the following...
Iterate through the column A to find the unique identifier
Once found update the data in columns 1 through 5
Below is the script I have so far:
function TransferToAppData(e) {
var destFile = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
var destSheet = destFile.getSheetByName("Raw App Data");
var ss = e.source;
var s = ss.getActiveSheet();
var uniConstRng = s.getRange("A1");
var uniqueConstVal = uniConstRng.getValue();
var NextOpenRow = destSheet.getLastRow() + 1;
var ActiveRow = e.range.getRow();
Logger.log(ActiveRow);
var uniqueVal = s.getRange(ActiveRow,1).getValue();
var add = s.getRange(ActiveRow,2).getValue();
var name = s.getRange(ActiveRow,3).getValue();
var dt = s.getRange(ActiveRow,5).getValue()
if (uniqueVal == "") {
s.getRange(ActiveRow,1).setValue(uniqueVal + 1);
uniConstRng.setValue(uniqueVal + 1);
var transferVals = s.getRange(ActiveRow,1,1,5).getValues();
Logger.log(transferVals);
destSheet.getRange(NextOpenRow,1,1,5).setValues(transferVals);
destSheet.getRange(NextOpenRow, 6).setValue("Applicant");
}
else {
var destLastRow = destSheet.getLastRow();
var destDataRng = destSheet.getRange(2,1,destLastRow,5)
var destValues = destDataRng.getValues();
var sourceValues = s.getRange(ActiveRow,1,1,5).getValues();
for( var i = 0; i < destValues.length; ++i){
if (destValues([i][0])==uniqueVal) {
for(n=0;n<destValues[0].length;++n){
///I"m stuck!!!
}
}
}
}
}
As you can see I have the first array loop going, but I'm having trouble figuring out how to do a second loop that iterates only on the row where the unique value is found and write the source data to ONLY to row where the unique value was found not the whole sheet.
I figured it out...
Below is the code and here is how it works...
When values in certain columns are edited this code is fired.
1--It finds the unique identifier located in the row which was edited.
2--Compares that identifier with a column of unique identifiers in another spreadsheet.
3--When a match is found it writes the change to the new spreadsheet and exits the loop
function TransferToAppData(e) {
var destFile = SpreadsheetApp.openById('1V3R2RnpA8yXmz_JDZSkBsK9tGR2LjHZp52p5I1CuQvw');
var destSheet = destFile.getSheetByName("Raw App Data");
var ss = e.source;
var s = ss.getActiveSheet();
var uniqueConstRng = s.getRange("A1");
var uniqueConstVal = uniqueConstRng.getValue();
var NextOpenRow = destSheet.getLastRow() + 1;
var ActiveRow = e.range.getRow();
var uniqueVal = s.getRange(ActiveRow,1).getValue();
if (s.getRange(ActiveRow,2).getValue() == "" || s.getRange(ActiveRow,3).getValue()=="" || s.getRange(ActiveRow,4).getValue()=="" || s.getRange(ActiveRow,5).getValue()=="") {
s.getRange(ActiveRow,13).clearContent();
Browser.msgBox("Address, Name, Date Entered & Rent are required fields!");
} else{
if (uniqueVal == "") {
s.getRange(ActiveRow,1).setValue(uniqueConstVal + 1);
uniqueConstRng.setValue(uniqueConstVal + 1);
var transferVals = s.getSheetValues(ActiveRow,1,1,5);
destSheet.getRange(NextOpenRow,1,1,5).setValues(transferVals);
destSheet.getRange(NextOpenRow, 6).setValue("Applicant");
}
else {
var destLastRow = destSheet.getLastRow();
var destValues = destSheet.getSheetValues(2,1,destLastRow,5);
var sourceValues = s.getSheetValues(ActiveRow,1,1,5);
for(var i = 0; i < destValues.length; ++i){
if (destValues[i][0]===uniqueVal) {
destSheet.getRange(i+2,1,1,5).setValues(sourceValues);
break;
}
}
}
s.sort(1,false);
destSheet.sort(1,false);
}
}

Categories

Resources