Sorting Columns Based on Values from different sheet - google-apps-script

I've created a table with Names, Type of Sale, Location and Amount. The names is taken from a different sheet with formula ={"";Unique(rawData!A:A)} and for other columns like location Amount and type of sales, I've used Vlookup and Sumifs function based on the requirement.
This is working fine, but, when I try to sort with the googlescript with the code
function autoSort() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("Summary")
const range = ws.getRange("A2:D1000")
range.sort({column:4, ascending: false})
}
the Amount column is getting sorted but again it is changing back in a blink.
Is this due to the formula ={"";Unique(rawData!A:A)} or I'm doing something else wrong here.. Kindly help

What's going wrong?
When you are "manually" sorting your data with the script, your ={"";Unique(rawData!A:A)} formula does not change. All you are doing is rearranging the other vlookup and sumif physical formulas around the sheet. Since the names never change, neither are your resulting values.
This is a very basic and rudimentary explanation. I'm sure there is a much better explanation for what is happening, but my basic understanding is just that you can't sort formulas because ultimately nothing about the order actually changes
A solution?
Do do everything in one formula in order to group everything together.
I have come up with one to do this.
=ifna(
sort(
{
Unique(rawData!A2:A),
arrayformula(VLOOKUP(Unique(rawData!A2:A), rawData!A2:D10, 2, 0)),
arrayformula(VLOOKUP(Unique(rawData!A2:A), rawData!A2:D10, 3, 0)),
arrayformula(VLOOKUP(Unique(rawData!A2:A), rawData!A2:D10, 4, 0))
},
4, 0
)
)
This pulls all the data at once (including the names) and sorts it as a whole. The VLOOKUP references the unique array, instead of an actual cell reference. This allows the values to be sorted, without rearranging the physical formulas. Below is a link to the spreadsheet I created to test this. This may need to be changed and edited to your liking (especially given that I didn't incorporate any SUMIF formulas), but it does what you appear to be asking for.
https://docs.google.com/spreadsheets/d/1Yj0IhZsbbXvhHQfkhn3P8Ac-A8nq5D3fiOZAsVYiPVs/edit?usp=sharing
This formula creates a blank first row. This can be fixed by filtering out blank values in the unique formula, but I left it as it was right now to avoid confusion. If you would like help incorporating that, just let me know and I can edit the formula.

Related

Query to count cells changes cell's range randomly, by itself

I refer to my previous question.
The problem happens when I use the non-array solution proposed by #Martín (the one that overloaded less my system).
=QUERY(Sheet1!A2:B;"Select A,COUNT(A) where A is not null group by A pivot B")
By itself the Query() works perfectly, but only with non-dynamic ranges. The function, put in "Sheet2", draws the data to be counted from "Sheet1". The range in which the function is applied is a portion of "Sheet1", that's why I entered "Sheet1!A2:B".
In "Sheet1", new cells are constantly added and the sheet automatically organizes the answers into different categories (first_department, second_department, ...). To do this, it adds blank rows between groups of cells (different categories), removes rows in the wrong category to move them in the correct one, removes all blank rows at the end (useless part of the sheet).
At this point, the Query() in "Sheet2" has some error which leads it to consider a range outside the one originally set (it's always the number of cells on the sheet + 1), raising a "#VALUE!".
Function before:
=QUERY(Sheet1!A2:B;"Select A,COUNT(A) where A is not null group by A pivot B")
Function after (an example):
=QUERY(Sheet1!A23:B;"Select A,COUNT(A) where A is not null group by A pivot B")
In this case there were 22 cells in "Sheet1", and the Query() went to "A:23".
I've tried myself to solve the issue in the past week, trying to simulate the situation that led to the problem. I've updated the organization of "Sheet1" by adding new data or deleting some: I haven't been able to find out the source of the error. When I checked the query's behaviour, the range rightly locked at "A2:B", it didn't end up at "A23:B".
I tried deleting the entire sheet and creating a new one from scratch (maybe it was a local bug), I tried changing Google Sheet's country of use (maybe it was punctuation), but that didn't fix anything. I've looked at the Query() and it's, indeed for me, correct under all shapes.
Is there a way to lock the range, so that it doesn't change randomly?
I'd appreciate any effort!
Yes, it's a common issue, you can use INDIRECT to lock the range:
=QUERY(INDIRECT("Sheet1!A2:B");"Select A,COUNT(A) where A is not null group by A pivot B")

How do I keep values in 2 different sheets in sync?

I have a sheet that has some dates on it, like "25/02/2016", listed down a column. On the cells to the right of each date, there are some numeric values.
I need to copy these numeric values to a specific range on a different sheet. Ideally, it would work like a one-way sync, where I would write values on sheet1 and sheet2 would automatically be updated.
I've been looking through the Google Apps Script documentation, but I have no idea where to start. I do have some pseudo-code, just don't how to use it here.
function getDates() {
for (count = 0; count < sheet1.length; count++) {
if (hasDate) {
return(cell);
}
}
}
var numericValuesRows = sheet1.getDates().getRow();
var numericValuesRange = numericValuesRows.selectColumns(C-F);
Just making up method names and syntax. This bit is supposed to find out which rows have dates in them, and then select columns C to F in those rows. The next one is supposed to select the destination as all the cells from row3:columnC to row10:columnF, and copy the previously selected values to there.
var outputRange = sheet2.cellRange(C3-F10);
numericValuesRange.copyTo(outputRange);
I realise it's really crappy pseudo-code, but I'm hoping it at least helps in some way get across what I want to do. What would be the best way to do this?
Use the onEdit() trigger which will trigger when you edit a sheet. You can check the source of the edit to make sure its an edit to the cells you want in a particular sheet. Once that's done, its a matter of using getValue(), setValue() and getSheetByName(). Start here: simple triggers

Copying values from Google sheet, add time stamp, prevent duplicates

I'm using Kimono to scrape a site that lists active development permits. For a one off data scrape it's fine, the problem is that there is no way of sorting new data. Every time Kimono scrapes it updates the entire array.
This is what the sheet currently looks like
https://docs.google.com/spreadsheets/d/1BH8ESAHQJrog6x8nRBOpgBN-nTN1_aDY7wr8W_YYet0/edit#gid=1865015934
The first sheet is automatically populated and overwritten by Kimono. It seems like the most logical way of making this work would be to copy the values to another sheet, adding a time stamp when this happens and then preventing duplicate values from being posted.
Following this thread is was able to muster this code
I've got the copying part down with the following:
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('Building Permits!A1:D');
source.copyTo(ss.getRange('Sheet2!A1'), {contentsOnly: true});
source.clear();
}
What I am trying to figure out is how to prevent duplicates based on the URL value.
I know that it is right in front of me, but I'm drawing a blank on how to get this to work.
This Google documentation article on removing duplicates is very well written, so I won't duplicate it: https://developers.google.com/apps-script/articles/removing_duplicates
It has exactly what you need. Read the later part of the article where it talks about how to check duplicates not for the entire row, but specific columns in that row. Once you understand that, your problem is straightforward to solve. Just use 2 arrays, to hold the contents of the rows from the 2 sheets as in the example they've given. compare the first column value of the current row. if it matches, don't copy the row over.
note: this works only when you copy row-by-row into the target sheet, not the entire range as your'e doing right now. But that's unavoidable.

Change order of columns spreahseet

I just want to confirm if there is any inbuilt function is google apps script to reorder the columns in the spreadsheet or do I have to do something like this -
var r = currentSheet.getRange(1, 1, currentSheet.getLastRow() - 1, currentSheet.getLastColumn()).getValues();
for(var i1=0, dLen=r[0].length; i1<dLen; i1++) {
//something to reorder
}
Please help!
it depends. if you just want to present the data in a different order, just use the built-in "=query" cell function, selecting the rows in the order you want.
query has some limitations thou. for example each column must have a consistent type on all rows (date, number, string etc). there arr other built-in functions that do similar things.
if you actually want to change the source range, you need to do it by getting the entire range array values, transforming it (possibly needing to take care of functions too) and writting the entire new array in a single range write.

Why does my Apps Script reference the wrong row?

The Goal
I am trying to create a spreadsheet using some custom functions. The purpose for the sheet is to keep score in a quizzing competition. The top row has the question number, the second row the score, and the third number the number of fouls for that question.
The Problem
After noticing some problems with the score calculation, I was able to narrow the problem down to the part of the code where I add up the fouls that occurred prior to the current question. It seems that no matter what I do, the code sums over the question row, not the foul row.
Attempted Solutions
The extremely strange thing is that no matter what I change the reference cells to, it always produces the same result (i.e. it still references the question row same as it always has).
Example
I'm not sure if that makes any sense, but I've made an example sheet here so you can see what I'm talking about and try to figure out what is going on. Keep in mind that I'm well aware that I could accomplish what I'm trying to do in the example sheet with a simple built-in formula, but since there's no way to use worksheet formulas on the Apps Script side, I have to create my own version of it. I've made the example editable for anyone with the link, so you should have full access to it; but if you have problems, just let me know, and I'll see what I can do to fix it.
In your For loop, you are summing the indexes rather than the values:
Try:
for (var PrevValue in PrevValues[0]) {
Sum = Sum + Number(PrevValues[0][PrevValue]);
}
EDIT:
You'll also need to account for the case where you pass in a single cell rather than a range (=mySum($B4:B4)), because in that case the value is passed directly instead of an array.
if(PrevValues instanceof Array){
for (var PrevValue in PrevValues[0]) {
Sum = Sum + Number(PrevValues[0][PrevValue]);
}
}else
Sum = PrevValues;