Check content of a "range" within a multidimensional array - javascript

I have a multidimensional array which is based on data from a spreadsheet. It is structured like this: Array[0][row][column].
Now I want to check if the values in several rows within one column are blank. Is there a way to concisely express something like if (Array[0][Row 1 to 10][Column 3] === "") ?
This is my current code:
function updateOverview() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var database = SpreadsheetApp.openById('XYZ');
var overviewContent = [ss.getDataRange().getValues()];
var campaignData = [database.getDataRange().getValues()];
for (var a = 1; a < (campaignData[0].length); a++) {
for (var d = 4; d < overviewContent[0].length; d++) {
if (campaignData[0][a][3] === overviewContent[0][0][1] && (Utilities.formatDate(campaignData[0][a][7],"GMT+01:00","yyyyMMdd")) <= (Utilities.formatDate(overviewContent[0][d][3],"GMT+01:00","yyyyMMdd")) && (Utilities.formatDate(campaignData[0][a][8],"GMT+01:00","yyyyMMdd")) >= (Utilities.formatDate(overviewContent[0][d][3],"GMT+01:00","yyyyMMdd"))) {
var campaignDuration = (Utilities.formatDate(campaignData[0][a][8],"GMT+01:00","yyyyMMdd") - Utilities.formatDate(campaignData[0][a][7],"GMT+01:00","yyyyMMdd"));
var campaignSlotAvailable = true;
for (var b = d; b < (campaignDuration +1); b++) {
if (overviewContent[0][b][5] !== "") {
campaignSlotAvailable = false;
break;
}
}
if (campaignSlotAvailable) {
overviewContent[0][d][5] === campaignData[0][a][6];
}
}
}
};
ss.getDataRange().setValues(overviewContent[0]);
};

Related

Sum cells if they are not strikethrough

I'm a little bit stuck with my Google Apps script purposed to calculate a sum of cells which are not strikethrough.
Here is its source:
function SumIfNotStrikethrough(rangeA1Notation)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var mysheet = sheet.getActiveSheet();
var dataRange = mysheet.getDataRange();
var mydatarange = mysheet.getRange(rangeA1Notation);
var numRows = mydatarange.getLastRow();
var rowindex = mydatarange.getRowIndex();
var columnindex = mydatarange.getColumnIndex();
var total =0;
for(i=rowindex;i<=numRows;i++)
{
if(dataRange.offset(i-1, columnindex-1, 1, 1).isBlank() != true && dataRange.offset(i-1, columnindex-1, 1, 1).getFontLine() != "line-through")
{
var temp = dataRange.offset(i-1, columnindex-1, 1, 1).getValue();
total = total + temp;
}
}
return total;
}
Here is its formula: =SumIfNotStrikethrough("J2").
I have two questions here:
How to add the Google Apps script to use this formula as, for example, SumIfNotStrikethrough(J2) rather than SumIfNotStrikethrough("J2")? Quotes are so annoying in terms of changing its range manually after scaling the formula on other cells :-(. What should be changed in the source code?
When I run this script I face with following error:
Range not found (line 9, file "SumIfNotStrikethrough"
Thus, how can I fix it?
UPD № 1. Here is an example with a string reference, but it only counts the number of cells:
function countStrike(range) {
var count = 0;
SpreadsheetApp.getActiveSheet()
.getRange(range)
.getFontLines()
.reduce(function (a, b) {
return a.concat(b);
})
.forEach(function (el) {
if (el === "line-through") {
count++
}
});
return count;
}
UPD № 2. Unfortunately, this question is different from my previous question "Sum cells if they are not bold". I respectively tried to change the script, but it didn't work. Yes, it sums cells but it sums all the cells with strike-through and without :-(.
Here is what I changed:
function SumIfNotStrikethrough(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
var args = formula.match(/=\w+\((.*)\)/i)[1].split("!");
try {
if (args.length == 1) {
var range = sheet.getRange(args[0]);
}
else {
sheet = ss.getSheetByName(args[0].replace(/'/g, ''));
range = sheet.getRange(args[1]);
}
}
catch(e) {
throw new Error(args.join("!") + " is not a valid range");
}
var weights = range.getFontLine();
var numbers = range.getValues();
var x = 0;
for (var i = 0; i < numbers.length; i++) {
for (var j = 0; j < numbers[0].length; j++) {
if (weights[i][j] != "line-through" && typeof numbers[i][j] == "number") {
x += numbers[i][j];
}
}
}
return x;
}
Thank you for all your attempts to help me in advance!
I've modified the suggested answer with getFontLines() rather that getFontLine():
function SumIfNotStrikethrough1(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
var args = formula.match(/=\w+\((.*)\)/i)[1].split("!");
try {
if (args.length == 1) {
var range = sheet.getRange(args[0]);
}
else {
sheet = ss.getSheetByName(args[0].replace(/'/g, ''));
range = sheet.getRange(args[1]);
}
}
catch(e) {
throw new Error(args.join("!") + " is not a valid range");
}
var lines = range.getFontLines();
var numbers = range.getValues();
var x = 0;
for (var i = 0; i < numbers.length; i++) {
for (var j = 0; j < numbers[0].length; j++) {
if (lines[i][j] != "line-through" && typeof numbers[i][j] == "number") {
x += numbers[i][j];
}
}
}
return x;
}
Here is the formula to use it: =SumIfNotStrikethrough1(A2:B3).
Now that seems to be working properly in its single use.

How can I split the below string into a 2dimensional-array:

How can I split the below string into a 2dimensional-array:
Customer::Europe|UK|Scotland|Product::Drinks|Water|
array:
[Customer][Europe]
[Customer][UK]
[Customer][Scotland]
[Product][Drinks]
[Product][Water]
Not sure how to create the array. Haven't coded in years, so be kind
hArray= [];
vArray= [];
var i = j = 0;
var count = hierarchy.search(/[:|]+/);
write(hierarchy);
while (count > 0) {
if (hierarchy.indexOf(":") < hierarchy.indexOf("|") || (hierarchy.indexOf(":") > 0 && hierarchy.indexOf("|") == -1) ) {
hArray[j] = hierarchy.substr(0,hierarchy.indexOf(":"));
hierarchy = hierarchy.slice(hierarchy.indexOf(":")+2);
count = hierarchy.search(/[:|]+/);
j++;
} else
if (hierarchy.indexOf("|") < hierarchy.indexOf(":") {
vArray[i] = hierarchy.substr(0,count);
hierarchy = hierarchy.slice(count+1);
count = hierarchy.search(/[:|]+/);
i++;
}
if (count == -1) break;
//create multiArray ?
}
var source = "Customer::Europe|UK|Scotland|Product::Drinks|Water|";
var parts = source.split(/(\w+::)/);
var result = [];
for (var i = 1; i < parts.length; i += 2) {
var key = parts[i].replace("::", "");
var values = parts[i + 1].split("|");
for (var j = 0; j < values.length - 1; ++j) {
var line = new Array(2);
line[0] = key;
line[1] = values[j];
result.push(line);
}
}
console.log(result);
You can use Array.reduce like this. First, we split on | that is behind any owrd followed by ::. Then we reduce it, by using an array as memo and push an array into the memo, which we finally return.
var arr = input.split(/\|(?=\w+::)/).reduce(function(arr, str){
var array = str.split('::');
return arr.push(str.split('::')[1].split('|').filter(String).map(function(s){
return [array[0], s]
})), arr;
}, []);

Why is this happening with javascript objects

I am working on a function to map a string that has been split into an array
function arrayDups(a) // a: array to search: as in string split into array.
{
var unique = {}
var dups = [];
var seen = false;
var bypass = {};
for(var i = 0; i < a.length; i++)
{
if(bypass[a[i]] == 'undefined')
{
unique[a[i]] = i+',';
bypass[a[i]] = false;
}
for(var k = i; k < a.length; k++)
{
// so the same char later will not produce duplicate records.
if(unique[a[k]] != 'undefined' && bypass[a[k]] != 'undefined' && !bypass[a[k]])
{
unique[a[k]] += k+',';
if(k == a.length - 1)
{
bypass[a[i]] = true
}
}
}
}
for(var x in unique)
{
dups[dups.length] = x+':'+unique[x]
}
return dups;
}
this is colled in the following context
var testCase = ('disproportionate').split('');
window.onload = function()
{
var test = document.getElementById('res')
test.childNodes[0].data = arrayDups(testCase).join("\n")
}
which produces the following output
d:undefined0,
i:undefined1,10,1,10,
s:undefined2,2,2,
p:undefined3,6,3,6,3,6,3,6,
r:undefined4,8,4,8,4,8,4,8,4,8,
o:undefined5,7,11,5,7,11,5,7,11,5,7,11,5,7,11,5,7,11,
t:undefined9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,
n:undefined12,12,12,12,12,12,12,12,12,12,12,12,12,
a:undefined13,13,13,13,13,13,13,13,13,13,13,13,13,13,
e:undefined15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
The questions:
where is undefined coming from
and why are the index positions being duplicated when for each iteration of i
k begins at the current i value and should be looking ahead to find index values of duplicate chars
I wouldn't want to answer my own question so I am adding to the original post via edits
Here is what I came up with
function arrayDups(a) // a: array to search: as in string split into array.
{
var unique = {}
var dups = [];
var seen = false;
var bypass = {};
for(var i = 0; i < a.length; i++)
{
if(!bypass.propertyIsEnumerable(a[i]))
{
unique[a[i]] = i+',';
bypass[a[i]] = 'false';
continue;
}
if(bypass.propertyIsEnumerable(a[i]) && bypass[a[i]] == 'false')
{
for(var k = i; k < a.length; k++)
{
// for every instance of a[i] == a[k] unique[a[k]] will be defined
if(a[i] == a[k] && unique.propertyIsEnumerable(a[k]))
{
unique[a[k]] += k+',';
}
if(k == a.length - 1)
{
bypass[a[i]] = 'true'
continue;
}
}
}
}
for(var x in unique)
{
dups[dups.length] = x+':'+unique[x]
}
return dups;
}
And this is the output
d:0,
i:1,10,
s:2,
p:3,6,
r:4,8,
o:5,7,11,
t:9,14,
n:12,
a:13,
e:15,
so now all I have to do is strip the railing ','

Javascript reverse sorting

i have a problem on javascript reverse method when all the data to be sorted are equal.
here is my code:
var ascAgt = false;
function sortTableAgt() {
var tbl = document.getElementById("mytable").tBodies[0];
var store = [];
for (var i = 0, len = tbl.rows.length; i < len; i++) {
var row = tbl.rows[i];
var rowdatedata = row.cells[1].innerHTML;
store.push([rowdatedata, row]);
}
if (ascAgt) {
store.sort();
ascAgt = false;
} else {
store.sort();
store.reverse();
ascAgt = true;
}
for (var i = 0, len = store.length; i < len; i++) {
var idno = i + 1;
store[i][1].cells[0].innerHTML = idno.toString();
tbl.appendChild(store[i][1]);
} store = null;
}
sample data:
ID Name Date
1 XXXXX 2012/10/05
2 XXXXX 2012/03/16
3 XXXXX 2012/05/18
4 XXXXX 2012/05/18
as i sort the name part,what i want is that nothing happens because names are equal but when it comes to the reverse method it will just reversed the given data.
am i missing something here?
thank you in advance....
So, what you want is to sort by 2nd column and, if the values are equal, sort also by 3rd column. Right?
The sort() function takes also a callback. You have to use that.
var ascAgt = false;
function sortTableAgt() {
var table = document.getElementById("mytable").tBodies[0],
rows = table.rows,
len = rows.length,
i = 0,
store = [],
order = ascAgt ? 1 : -1;
for (i = 0; i < len; i++) {
store.push(rows[i]);
}
store.sort(function(a, b) {
if (a.cells[1].innerHTML == b.cells[1].innerHTML) {
// If 2nd cell are equal, sort by 3rd cell
// Compare them as date (timestamp)
var dateA = new Date(a.cells[2].innerHTML).getTime(),
dateB = new Date(b.cells[2].innerHTML).getTime();
if (dateA == dateB) {
return 0;
} else if (dateA < dateB) {
return -1 * order;
} else {
return 1 * order;
}
} else if (a.cells[1].innerHTML < b.cells[1].innerHTML) {
return -1 * order;
} else {
return 1 * order;
}
});
for (i = 0; i < len; i++) {
store[i].cells[0].innerHTML = (i+1).toString();
table.appendChild(store[i]);
}
}
You can also check tis demo in JSBin: http://jsbin.com/welcome/39336/edit

Have 42 HTML Elements that need to be placed in 3 arrays. Javascript

Kind of a noob question, but I have a page with 42 checkboxes all placed into an array, but I need to split the array into 3 smaller arrays.
array(0) = smallOne(0);
array(1) = smallTwo(0);
array(2) = smallThree(0)
array(3) = smallOne(1);
array(4) = smallTwo(1);
array(5) = smallThree(1);
And so forth. Is there a method that does this or will I just need to list them all out?
Here's the javascript so far:
function SendForm() {
var elLength = form1.elements.length;
var chk = new Array(42);
var desc = new Array(14);
var local = new Array(14);
var other = new Array(14);
for (i = 0; i < elLength; i++) {
var count = 0;
var type = form1.elements[i].type;
if (type == "checkbox") {
if (form1.elements[i].checked) {
chk(count) = true;
}
else {
chk(count) = false;
}
count++;
}
else {
}
}
}
You could do something like this to assign them:
for (var i = 0; i < 14; i++)
{
var x = i * 3;
desc[i] = chk[x];
local[i] = chk[x + 1];
other[i] = chk[x + 2];
}

Categories

Resources