Run function for an array of values - loops

I'm trying to run a couple of functions for an array of values and it's not working. Essentially what I want to do is paste and export a PDF of the range A1:C15 for every cell in Z. I have tried a couple of things and nothing seems to work, the latest code I tried is the following:
function GuardarPDF(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var refesSheet = ss.getSheetByName("etiqueta");
var lista_refes = refesSheet.getRange("Z4:Z" + refesSheet.getLastRow()).getValues();
var lista_refes_ok = lista_refes.filter(([a]) => a);
for (var i = 0; i < lista_refes_ok.length; i++) {
console.log(lista_refes_ok[i][0]) // Here, you can see the folder ID in the log.
var refes = lista_refes_ok[i][0];
try {
for (var i = 0; i < lista_refes_ok.length; i++) {
console.log(lista_refes_ok[i][0]) // Here, you can see the folder ID in the log.
var refes = lista_refes_ok[i][0];
try {
var referencia2 = refesSheet.getRange("B5").setvalue(refes);
CreaPDF();
}}
(CreaPDF works fine, I'm having trouble generating the iteration so that a PDF for every row in Z is generated)
Does anybody know where the problem is or how to solve it? Thank you so much in advance!

Your code had a variety of errors, but I think this is what you are looking for:
Try:
function GuardarPDF() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const refesSheet = ss.getSheetByName(`etiqueta`)
const lista_refes = refesSheet.getRange(`Z4:Z${refesSheet.getLastRow()}`)
.getValues()
.flat()
.filter(cell => cell != ``)
lista_refes.forEach(ref => {
refesSheet.getRange(`B5`).setValue(ref)
CreaPDF()
Utilities.sleep(5000)
})
}
This will get all values listed in Z4:Z(lastRow), then remove any blank cells. For each of the values, it will write the ref to cell B5 (potential error), and run CreaPDF.
If you need any further explanation, have any questions, or need modification, please let me know!
Learn More:
Array.forEach()
Utilities.sleep()

Try this:
function myfunk() {
const ss = SpreadsheetApp.getActive()
const rsh = ss.getSheetByName(`Your Sheet Name`)
const vs = rsh.getRange(4,26,rsh.getLastRow() - 3).getValues().flat().filter(e => e);
vs.forEach(e => {
rsh.getRange(`B5`).setValue(e);
SpreadsheetApp.flush();
CreaPDF()
});
}

Related

How do I get unique values after getRespondentEmail in google apps script?

I've been trying without success to get unique values from an array, after creating the array from getRespondentEmail in google apps script. I've tried to use the set method, the forEach etc for this and each time it returns an empty array or empty curly brackets. This is a sample of my code:
function test(){
var form = FormApp.openById('...');
form.setCollectEmail(true);
var formResponses = form.getResponses();
var getEmails = [];
var uniqueResponses = [...new Set(getEmails)];
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var oneEmail = formResponse.getRespondentEmail();
getEmails.push(oneEmail);
}
Logger.log(uniqueResponses);
}
Does anyone know what the problem might be? I'm stuck. Thank you so much.
In your script, how about the following modification?
Modified script:
function test(){
var form = FormApp.openById('...');
form.setCollectEmail(true);
var formResponses = form.getResponses();
var getEmails = [];
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var oneEmail = formResponse.getRespondentEmail();
getEmails.push(oneEmail);
}
var uniqueResponses = [...new Set(getEmails)];
Logger.log(uniqueResponses);
}
In your script, when var uniqueResponses = [...new Set(getEmails)] is run, getEmails has no value. By this, your issue occurs. In this modification, var uniqueResponses = [...new Set(getEmails)] is used after getEmails has the values. By this, the duplicated values are removed.
Reference:
Set

Is it possible to show gradients with react-svgmt?

I would like to use react-svgmt to manipulate SVG's. These SVG's can be uploaded from the users. My problem is, that if the SVG has a gradient these parts of the SVG are not shown.
Has anybody a solution for my problem to reactivate these links after the import of the SVG via react-svgmt?
With the developertools of my browser I was be able the see that the elements are in the code, but the grandients will be linked to the elements and these links are broken.
I have seen that other people has the same problem with gradients and created an issue on github, but the developer did not respond.
I found a solution for my problem.
react-svgmt add to elements like linearGradients "-{nr}" to its id-names. Then this fill:url(#linear-gradient-2); does not work anymore in the style-tags, because it must be fill:url(#linear-gradient-2-{nr});.
So the first SVGProxy after loading is <SvgProxy selector="linearGradient" onElementSelected={handleGradients} ></ SvgProxy>
an the function handleGradients looks like following and saves the {nr}
const handleGradients = (gradients) => { if (typeof gradients.length !== 'undefined') { const output = gradients.map((g, i) => { nr = g.id.substring(g.id.lastIndexOf("-")+1); setNr(g.id.substring(g.id.lastIndexOf("-")+1)); if(g.href.baseVal.length > 0) { var base = g.href.baseVal; g.href.baseVal = base + '-' + nr; } return g; }); } else { nr = gradients.id.substring(gradients.id.lastIndexOf("-")+1); setNr(gradients.id.substring(gradients.id.lastIndexOf("-")+1)); if(gradients.href.baseVal.length > 0) { var base = gradients.href.baseVal; gradients.href.baseVal = base + '-' + nr; } } };
Then I had another SVGProxy
<SvgProxy selector="defs > style" onElementSelected={handleStyleElem} ></ SvgProxy>
with the following handlefunction which replaces all urls with the schema from above
const handleStyleElem = (svgStyle) => { var styleStr = svgStyle.outerHTML; styleStr = styleStr.replaceAll(/url\(#((\w|-)*)\);/g, 'url(#$1-'+ nr +');'); svgStyle.outerHTML = styleStr; };

remove common elements from two arrays in appscript?

I have a google sheet. I am try to get all tab names in to array. I used this code.
function allTabNames() {
try{
var out = new Array();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i =0; i<sheets.length; i++) out.push([sheets[i].getName()]);
Logger.log(out);
Logger.log(out.length);
return out
}
catch (er){
Logger.log(er);
}
}
It's working correctly. Now I want to remove some tab names. I created a new array using the tab names I want to remove.
var duparray = ["Sheet1", "newRoad147", "Sheet2", "Sheet3", "Sheet4","Sheet5", "Sheet6"];
When I run the first mentioned code I will get this. The array "out".
[[Sheet1], [newRoad147], [Sheet2], [Sheet3], [Sheet4], [Sheet5], [Sheet6], [Sheet7], [AddData], [WCO069], [WCO065], [WCO149], [WCO141], [WCO158], [BarChart], [Sheet11]]
I am trying to remove the common element in these two arrays. For that I used the following code. But it did not go well.
function allTabNames() {
try{
var out = new Array();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i =0; i<sheets.length; i++) out.push([sheets[i].getName()]);
Logger.log(out);
Logger.log(out.length);
//return out
var duparray = ["Sheet1", "newRoad147", "Sheet2", "Sheet3", "Sheet4","Sheet5", "Sheet6"];
var outx = out.filter( function( el ) {
return duparry.indexOf( el ) < 0;
} );
}
catch (er){
Logger.log(er);
}
Logger.log(outx);
}
The order of these tabs can be changed. That is why I try to remove the element using the specific names of the elements in the array. Then we hope to create a dropdown list of elements in this new array using data validation.
Get Sheet names and omit not included
function getTabName() {
const ss = SpreadsheetApp.getActive();
const nincl = ['Sheet1','Sheet2'];//not included
const shts = ss.getSheets().filter(sh => !~nincl.indexOf(sh.getName())).map(sh => sh.getName());
ss.getSheetByName('Sheet5').getRange("C5").setDataValidation(SpreadsheetApp.newDataValidation().requireValueInList(shts,true).build());
return shts;
}

Is there a way to exclude cells that contain formulas from my Google Script?

Apologies is this has been asked already but if someone could point me in the right direction that would be great. I've looked for several versions/solutions to this but can't seem to find one (I may be looking in the wrong place).
Basically, I'm looking for a way to exclude any cells that contain a formula from the following script. So I only want it to run this on cells that exactmatch "1". Any help would be greatly appreciated.
function runReplaceInSheet(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("2020");
// get the current data range values as an array
var values = sheet.getDataRange().getValues();
// Replace 1 with HOL
replaceInSheet(values, "1", "HOL");
// Write all updated values to the sheet, at once
sheet.getDataRange().setValues(values);
}
function replaceInSheet(values, to_replace, replace_with) {
//loop over the rows in the array
for(var row in values){
//use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = values[row].map(function(original_value) {
return original_value.toString().replace(to_replace,replace_with);
});
//replace the original row values with the replaced values
values[row] = replaced_values;
}
}
Flow:
getFormulas and replace only if the array of formulas is empty
Sample script:
function replace(sheetName = '2020', searchValue = '1', replaceValue = 'HOL') {
const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
const range = sheet.getDataRange();
const formulas = range.getFormulas();
const values = range.getValues();
range.setValues(
formulas.map((row, i) =>
row.map(
(formula, j) =>
formula || values[i][j].toString().replace(searchValue, replaceValue)
)
)
);
}
You may use the getFormulas() method to get all the formulas in the current shet and iterate through them like a 2d array.
var values = sheet.getDataRange().getDisplayValues();
var formulas = sheet.getDataRange().getFormulas();
for (var r=0; r<values.length; r++) {
for (var c=0; c<values[r].length; c++) {
var cellValue = values[r][c];
var formula = formulas[r][c];
if (!formula && cellValue === "1") {
sheet.getRange(r+1, c+1).setValue("HOL")
}
}
}

Impossible to find the function setBackground on a object

I'm trying to do something like: If the column E has the word ok, column D gets formated as red. Seens preety easy, but something is wrong as I'm not entenring the if. Do u guys know what is wrong? I have read some other topics, but seens preety much the same
function onEdit() {
var ss =SpreadsheetApp.getActiveSheet();
var myRangeValues = ss.getRange('D7:E').getValues();
Browser.msgBox(myRangeValues);
for (var i = 0; i < myRangeValues.length; i++){
if(myRangeValues[i][0] == 'ok'){
myRangeValues[i][0].setBackground('red');
}
}
}
Thanks for the attention.
EDIT:
new code not working. I tried to put the logger.log in other lines as well. even without the logger, the error I get is that the function setBackground is impossible to find in the object.
function onEdit() {
var ss =SpreadsheetApp.getActiveSheet();
var myRangeValues = ss.getRange('D7:E').getValues();
for (var i = 0; i < myRangeValues.length; i++)
{
if(myRangeValues[i][1] == 'ok')
{
myRangeValues[i][0].setBackground('red');
//Logger.log("myRangeValues[i][1]: " + myRangeValues[i][1]);
}
}
}
You are mixing up methods.
value arrays don't have setBackground() method, this is a spreadsheet range method
use the code below to do what you want :
function onEdit() {
var ss =SpreadsheetApp.getActiveSheet();
var myRangeValues = ss.getRange('D7:E').getValues();
var myRangeColors = ss.getRange('D7:E').getBackgrounds();// get the colors
for (var i = 0; i < myRangeValues.length; i++)
{
if(myRangeValues[i][1] == 'ok')
{
myRangeColors[i][0]='#F00';
}
}
ss.getRange('D7:E').setBackgrounds(myRangeColors); //set the modified colors
}

Resources