So far I've had the best luck with members from here for my questions. Right now I'm trying to correct a whole column with javascript. I have an array at the top full of values, if the array in the document doesn't agree, it gets corrected. However, my array is 4 longer than the document's rows. I need to append 4 more rows to get the document corrected.
I've tried messing with Range.e.r, no luck. I've tried countless experimenting and looking at other posted solutions, but none seem to work for my situation. If you have time, I appreciate your help. Thanks so much for your kindness and generosity.
I can work with 4 rows appended to the end. It'll be sloppy, but I can have variables carry the data to their proper locations. A better solution would be appending rows where it's wrong and inserting the names there. I also don't know how to do that.
Here's my code:
var worksheet5 = wb.Sheets[272];
var range = XLSX.utils.decode_range(worksheet5['!ref']);
range.s.r = 2; // <-- zero-indexed, so setting to 1 will skip row 0
worksheet5['!ref'] =XLSX.utils.encode_range(range);
header = getHeaderRow(worksheet5,range);
var data5 = XLSX.utils.sheet_to_json(worksheet5);
var n = 0;
var newData5 = data5.map(function(record){
if(record.Count === GAC[n]){
n++;
}
else{
if(record.Count != GAC[n]){
var Holdon = record.County;
record.Count = GAC[n];
if(Holdon === GAC[n]){
record.Count = Holdon;
n++;
}
n++;
}
}
return record;
}); ```
Related
I have a row of tick boxes and I need to count the most recent successive TRUE values. So it should start counting when the first TRUE appears and stop when it changes to FALSE, ignoring anything that comes after that.
Right now I have a script doing that, but since I have a lot of entries, it takes a long time to run and stops after 6min without finishing everything.
for(var j=3;j<lastRow;j++){
count = 0;
for (var k=stupac-1;k>2;k--){
if (range.getCell(j,k).getValue() == true){
count++;
}
else if ((range.getCell(j,k).isChecked() == false)&&(count>0)){
break;
}
}
range.getCell(j,stupac).setValue(count);
}
I thought the best way would be to stop the COUNTIF when the value changes, but have had no luck trying to get that working.
I came up with this solution which seems pretty fast. Your approach iterates over each cell which is not efficient especially when the search space is large. The following approach iterates over the rows in the specified data range.
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1');
const data = sh.getRange('A3:G'+sh.getLastRow()).getValues();
const counts = [];
data.forEach(row=>{
let t_index = row.indexOf(true);
let cutRow = t_index > -1 ? row.slice(t_index, row.length+1) : [];
let f_index = cutRow.indexOf(false);
let ct = f_index > -1 ? f_index : cutRow.length;
counts.push([ct]);
});
sh.getRange(3,8,counts.length,counts[0].length).setValues(counts);
}
Please adjust the data ranges according to your needs.
The solution here matches the following file:
Please make sure that you have enabled V8 Runtime.
I have two problems.
1) My function noDateAlert(); is SLOW. Any suggestions to make it take less than 5 seconds? Currently takes 17-30 depending on how many lines it has to check.
2) The error message will not pop up when I run noDateAlert(); in another function from my custom menu. It works fine when I run it by itself from the script page. It also works fine when run within the other program from the script page.
I'm using this program to warn me if the 3 cells are empty.
When it is enclosed in the other function it is the first thing listed.
Here's the function:
function noDateAlert() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh0 = ss.getSheetByName("Loads");
// get data from Loads sheet
var data = sh0.getRange(8,29,53,31).getValues();
var data2 = sh0.getRange(8,3,53,3).getValues();
for(var i=0; i < 45; i++) { //Controls how many rows it goes through for posting // len = data.length; i < len
//Only work on loads currently wanting to post
if(data2[i][0] == "P-Post"){
//Warn me if all 3 cells in one row are empty/blank
if(data[i][0] == "" && data[i][1] == "" && data[i][2] == ""){
Browser.msgBox("Some of the loads you want to post are missing dates. Please check dates and run 'Post Loads' again.");
return false;
break;
};
};
};
};
Try this for your msgbox. And I'll keep on looking at the other problem.
SpreadsheetApp.getUi().alert('Some of the loads you want to post are missing dates. Please check dates and run \'Post Loads\' again.');
I'm not privy to your data but I doubt that I do things this way. But since you have access to and knowledge of your data I'll assume that breaking this up in two ranges makes sense. However, I hope you realize that data2[i][0] is actually column 3 and data[i][0] is actually column 29. I left the limit for i at 53 since you specified 53 rows in both ranges. But again. I don't know the detail nor do I have access to the data. So if this doesn't help, you can change it back.
function noDateAlert()
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh0=ss.getSheetByName("Loads");
var data = sh0.getRange(8,29,53,31).getValues();
var data2 = sh0.getRange(8,3,53,3).getValues();
for(var i=0;i<53;i++)
{
if(data2[i][0]=="P-Post")
{
if(!data[i][0] && !data[i][1] && !data[i][2])
{
SpreadsheetApp.getUi().alert('Some of the loads you want to post are missing dates. Please check dates and run \'Post Loads\' again.');
return false;
}
}
}
}
I recognize that this question is similar to this one. I'm sad to say, I just don't know enough to follow that one.
I also recognize that it is very similar to the Google tutorial, but they are creating a new array, and I need to combine arrays.
The problem
I'm trying to create a permanent list from a volatile list. The permanent list will be updated daily. I need the script to look for duplicates on one sheet, and copy everything new to another sheet. I'm pretty sure that my problem lies mostly in my logic.
I've been bashing together all the similar answers I could find to help (commented out) and I just can't figure it out. More explanation below.
Spreadsheet here
Script here
Code.gs
function updateRoster() {
var ss = SpreadsheetApp
.openById("15DRZRQ2Hcd7MNnAsu_lnZ6n4kiHeXW_OMPP3squbTLE");
var data = ss
.getSheetByName("Volatile Data")
.getDataRange()
.getValues();
var saveData = ss
.getSheetByName("All Data")
.getDataRange()
.getValues();
for (i in data) {
var value = data[i][3];
for (j in saveData) {
var search = saveData[j][3]
if(value == search) {
Logger.log(data[i][3]);
}
}
}
}
I get this in the Log:
[16-03-24 06:35:44:914 PDT] 1.00000006E8
[16-03-24 06:35:44:916 PDT] 1.00000012E8
[16-03-24 06:35:44:918 PDT] 1.00000022E8
Which is correct, those are the duplicates, but I need to select every other row. The ones that are not duplicates.
I've tried a bunch of changes, but I just keep getting the second sheet's list repeated. Please help.
Simply replacing value == search with value != search will not work since then it would add the row to the second sheet if even one of the rows in saveData is different. But it needs to check if all rows are different.
If you are sure that your volatile data sheet doesn't have any duplicates in it, you can do it this way:
var saveSheet = ss.getSheetByName("All Data");
loopThroughData:
for (i in data) {
var value = data[i][3];
for (j in saveData) {
var search = saveData[j][3]
if(value === search) continue loopThroughData;
//here we leave the inner loop and jump back to the top if
//even one row is equal
}
saveSheet.appendRow(data[i]);
}
edit: However it's usually better to use functions instead of a combination of continue and labels.
Therefore I would prefer this solution:
function updateRoster() {
...
function areThereDuplicates(i) {
var value = data[i][3];
for(var j in saveData) {
if(saveData[j][3] === value) return true;
}
return false;
}
for (i in data) {
if(!areThereDuplicates(i)) saveSheet.appendRow(data[i]);
}
}
Well to get every OTHER value you could check for every row that is Different or "new"
if(value != search) {
Logger.log(data[i][3]);
}
and simply add the new rows to the file as
if(value != search) {
Logger.log(data[i][3]);
ss.getSheetByName("All Data").appendRow(data[i]);
}
Good luck =)
I am learning jQuery and am having issues trying to figure out how to select elements in a multidimensional array. I have a select list with database IDs and I want to set a var with the cost field in the database according to the id that selected. I have all the pieces except for translating the selected ID to a cost. Can someone please help me with getting this right please?
var rangeListData = [{"idrange_list":"1","range_cost":"0","target_range_name":"Self Only"},{"idrange_list":"2","range_cost":"1","target_range_name":"1 Space"},{"idrange_list":"3","range_cost":"2","target_range_name":"2 Spaces"},{"idrange_list":"4","range_cost":"3","target_range_name":"3 Spaces"},{"idrange_list":"5","range_cost":"4","target_range_name":"4 Spaces"},{"idrange_list":"6","range_cost":"5","target_range_name":"5 Spaces"}];
$('#slctPowerTarget').change(function () {
var targetID = $('#slctPowerTarget').val();
var cost $.grep(rangeListData, function(e) { return e.idrange_list == targetID }); // this is the line that is wrong
$('#spanTotalEffectsCost').text(cost);
});
If I put targetID in where cost is it lists fine. But when I try to look this up nothing happens. It is not right somehow and I am not sure what else to try. I think I get how idrange_list == targetID is supposed to match them but not sure how to call the related range_cost.
Thanks for any help you can offer! I read through the docs at jquery.com but can't seem to wrap my head around them.
You can do this :-
// Get the Multidimensional Array first
var data = $.grep(rangeListData, function (e) {
return e.idrange_list === targetID
});
// Get the range cost from the array
var cost = data[0].range_cost;
// Check the value in console for debugging purpose
console.log(cost);
Here is the final code. I also added an IF clause in there in case they select the default setting. This way it will reset instead of tossing an error and keeping page calculations working no matter if they change the drop downs or go back to "Select..."
$('#slctPowerRange').change(function () {
var rangeID = $('#slctPowerRange').val();
if (rangeID > 0) {
var rdata = $.grep(rangeListData, function (e) {
return e.idrange_list === rangeID
});
var rcost = rdata[0].range_cost;
}
else {
var rcost = 0 ;
}
$('#hdnRangeCost').val(rcost);
});
I'm struggling a little. I'm attempting to utilize the cool feature of assigning a custom attribute to an element. However it isn't working.
Basically, I'm trying to assign multiple elements to the TR element identifying information in that row. Here is what it looks like:
for (x=0; x< theData.length; x++)
{
// create table row
var selector = "wc_" + wID + "_row_" + x;
oRow = document.createElement("TR");
oRow.setAttribute("id", selector);
tBodyO.appendChild(oRow);
var rowCount = 0;
var identCnt = 0;
for (var index in theData[x])
{
identCnt = 0;
if (hasIdentify)
{
for (y=0; y < theIdent.length; y++)
{
console.log("ROW: "+x+" , checking: "+index+" === "+theIdent[y]["data_name"]);
if (index === theIdent[y]["data_name"])
{
myrow = $("#" + selector);
//myrow.attr("test","works");
console.log("ident Dataname: "+theIdent[y]["data_name"]+ " identify:"+theIdent[y]["identify"]+" value: "+theData[x][index]);
jQuery.data( myrow, "test", { first: 16, last: "pizza!" });
alert(myrow.data("test"));
}
}
}
}
}
I've left out some code that's not really relevant, but I hope you get the picture. What I'm trying to do is this:
I have an array that contains "identity" information about a particular row of data. It can have 0, 1 or more such identity pieces. I want to store these as a custom data attribute on the <TR> element.
Each data will have a distinct key (example: i_0_1 where 0 is the data row number and 1 is the identity counter)
However, I can't get this to work. I've tried lots of alternatives even trying to resort to .attr() with no luck. What am I doing wrong??
I'm getting an alert that says undefined. When I try the myrow.attr("test","works"); route I can see the attribute in the DOM. Why won't the data() way work for me?
I just figured out what the problem is. I guess after reading the docs on jQuery.data() I didn't see anyone really clearly come out and say:
You will not see the data info in the DOM - element when you look at the source.
To the credit of everyone here, they did tell me, I just didn't know what I was reading (now that I know what is expected)
Matt wrote:
"ill not actually set an attribute or property on the element; jQuery stores this data in an internal cache, and merely maps it to the element you selected"
Although after playing around with the .attr() and setAttribute() functions I just became more confused.
Thanks everyone!