remove common elements from two arrays in appscript? - arrays

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;
}

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

Run function for an array of values

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()
});
}

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")
}
}
}

Loading array of display objects using shared objects in action script 3.0

I'm trying to load an array that contain some display objects, the program lets me to populate the array with circles and save them to a shared object, then, I can trace the content of my array using the load button. The problem is that i can't load the array after that I restart my program. It traces me this message:"objects loaded: ,,,"
This is the code:
var SO:SharedObject=SharedObject.getLocal("myFile", "/");
var arr:Array=new Array();
var counter:Number=-1;
addBtn.addEventListener(MouseEvent.CLICK, addObjects);
saveBtn.addEventListener(MouseEvent.CLICK, saveObjects);
loadBtn.addEventListener(MouseEvent.CLICK, loadObjects);
function addObjects(event:Event) {
counter++;
var circle:circleClip=new circleClip();
arr.push(circle);
trace("current object: "+arr[counter]);
}
function saveObjects(event:Event) {
SO.data.arrSaved=arr;
SO.flush();
trace("objects saved: "+SO.data.arrSaved);
}
function loadObjects(event:Event) {
var arrLoaded:Array=new Array();
arrLoaded=SO.data.arrSaved;
trace("objects loaded: "+arrLoaded);
}
You are to understand MVC pattern approach: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
You need to separate data from the code that visualizes things out of these data, and store data only. Something like:
// Lets say this Array contains a list of your circle objects.
var Curcus:Array;
// Storage.
var SO:SharedObject = SharedObject.getLocal("myFile", "/");
function saveCircus():void
{
var aList:Array = new Array;
aList.length = Circus.length;
for (var i:int = 0; i < Curcus.length; i++)
{
// Get an object.
var aCircle:Sprite = Curcus[i];
// Record its properties you want to store.
var anEntry:Object =
{
"x":aCircle.x,
"y":aCircle.y,
"scaleX":aCircle.scaleX,
"scaleY":aCircle.scaleY
};
// Store the entry.
aList[i] = anEntry;
}
// Store and save data.
SO.data.arrSaved = aList;
SO.flush();
}
function loadCircus():void
{
// Retrieve saved data.
var aList:Array = SO.data.arrSaved;
// Make it empty data if there are none.
if (!aList) aList = new Array;
Circus = new Array;
Curcus.length = aList.length;
for (var i:int = 0; i < aList.length; i++)
{
// Get one entry.
var anEntry:Object = aList[i];
// Create a new item. BTW, naming classes with the
// lowercase first letter is the 8th cardinal sin.
var aCircle = new CircleClip;
// Restore saved properties.
aCircle.x = anEntry['x'];
aCircle.y = anEntry['y'];
aCircle.scaleX = anEntry['scaleX'];
aCircle.scaleY = anEntry['scaleY'];
// Add to display list.
addChild(aCircle);
// Keep it for the future reference/saving.
Curcus[i] = aCircle;
}
}

ActionScript 3 Can't Add and Remove item from Array

I'm working on a shopping list app and i'm having issue's removing and adding an item within the array.
I have an output_txt.text and input_txt.text with three buttons add_btn, remove_btn, and clear_btn. Inside my list (output) I have items of "Bread, Dog Food, Eggs, Hamburger, Milk". I want to be able to add items to the list and sort them alphabetically.
When I add an item it sorts it alphabetically, however when I try to add another item it just replaces the last item I entered.
When I want to clear an item I want to be able to copy the item from the list and place it in the input textbox and click the remove btn to remove it, but when I do this it only removes the second item and then places it to the bottom of the list.
(The totalItems_txt.text is the total number of items I add and remove from the list.)
Here's my code:
clear_btn.addEventListener(MouseEvent.CLICK, ClearList);
function ClearList(e:MouseEvent):void {
output_txt.text = "";
totalItems_txt.text = "0";
}
addItem_btn.addEventListener(MouseEvent.CLICK, AddItem);
function AddItem(e:MouseEvent):void {
var newItems:Array = ["Bread", "Dog Food", "Eggs", "Hamburger", "Milk"];
newItems[0] = "Bread";
newItems[1] = "Dog Food";
newItems[2] = "Eggs";
newItems[3] = "Hamburger";
newItems[4] = "Milk";
newItems[5] = input_txt.text;
newItems.sort(Array.CASEINSENSITIVE);
input_txt.text = "";
output_txt.text = "";
for (var i:int = 0; i < newItems.length; i++){
output_txt.appendText(newItems[i] + "\n");
}
totalItems_txt.text = newItems.length.toString();
}
remove_btn.addEventListener(MouseEvent.CLICK, RemoveItems);
function RemoveItems(e:MouseEvent):void {
var items:Array = ["Bread", "Dog Food", "Eggs", "Hamburger", "Milk"];
items[0] = "Bread";
items[1] = "Dog Food";
items[2] = "Eggs";
items[3] = "Hamburger";
items[4] = "Milk";
items[5] = input_txt.text;
output_txt.text = "";
items.splice(1,1);
for (var i:int = 0; i < items.length; i++){
output_txt.appendText(items[i] + "\n");
}
totalItems_txt.text = items.length.toString();
}
It's easier to identify the cause of the problem if you provide a complete and verifiable example, however, at the heart of your issue is an understanding of the Array methods:
splice(startIndex:int, deleteCount:uint), for removing items.
push(... args), for adding items.
If you explicitly reference newItems[0] thru [5], then you'll only ever affect entries 0 - 5, however, push is useful since it simply adds it to the end of your array. Conversely, you could use either splice (to specifically target a certain index), or pop() (which removes the last element from an array) to delete items from your array.
The other problem is that your arrays are local. Because you're recreating them every time you call RemoveItems or AddItem, you'll never save your changes. So, move it outside of those functions, and it'll be saved between clicks.
I've reworked your code with changes, and added supplemental code for the missing UI code you didn't provide. You can run this in a new .fla file and it will work as intended.
import flash.text.TextField;
import flash.events.KeyboardEvent;
import flash.display.Sprite;
var items:Array = ["Bread", "Dog Food", "Eggs", "Hamburger", "Milk"];
function addItem(e:MouseEvent):void {
if (input_txt.text != "") { // Assuming we having something in the input_txt,
items.push(input_txt.text); // add it to the end of our items array
input_txt.text = "";
updateOutput();
}
}
function removeItems(e:MouseEvent):void {
items.splice(0,1);
updateOutput();
}
function clearList(e:MouseEvent):void {
items = []; // empty our list by replacing it with a new one.
output_txt.text = "";
totalItems_txt.text = "0";
}
function updateOutput():void {
items.sort(Array.CASEINSENSITIVE);
output_txt.text = "";
for (var i:int = 0; i < items.length; i++){
output_txt.appendText(items[i] + "\n");
}
totalItems_txt.text = "Total: " + items.length;
}
/* Supplemental UI Creation */
var addItem_btn:Sprite = new Sprite();
addItem_btn.graphics.beginFill(0xa1FFa1,1);
addItem_btn.graphics.drawRect(0,0,100,25)
addChild(addItem_btn);
addItem_btn.addEventListener(MouseEvent.CLICK, addItem);
var clear_btn:Sprite = new Sprite();
clear_btn.graphics.beginFill(0xa1a1a1,1);
clear_btn.graphics.drawRect(0,0,100,25)
addChild(clear_btn);
clear_btn.x = 101;
clear_btn.addEventListener(MouseEvent.CLICK, clearList);
var remove_btn:Sprite = new Sprite();
remove_btn.graphics.beginFill(0xFFa1a1,1);
remove_btn.graphics.drawRect(0,0,100,25)
addChild(remove_btn);
remove_btn.x = 202;
remove_btn.addEventListener(MouseEvent.CLICK, removeItems);
var input_txt:TextField = new TextField();
addChild(input_txt);
input_txt.type = "input";
input_txt.text = "input_txt";
input_txt.y = 50;
var output_txt:TextField = new TextField();
addChild(output_txt);
output_txt.text = "output_txt";
output_txt.y = 50;
output_txt.x = 101;
var totalItems_txt:TextField = new TextField();
addChild(totalItems_txt);
totalItems_txt.text = "totalItems_txt";
totalItems_txt.y = 50;
totalItems_txt.x = 202;
All you had to do is declare your array as public and then add just the values to the array by using push(). when you sort the actual index of the array still remains , but the displayed items index will be different ,

Resources