Can you have 2 ranges in google script? - sorting

I basically have all the classes on the same sheet and want to organise each class by first & last name.
Each class has 2 columns being used. It works when I use one sort range and sorts out the columns just need the rest of it now. Any help would be great as I am fairly new at all this.
SHEET_NAME = "ALL STUDENTS";
SORT_DATA_RANGE = "A3:B100";
SORT_ORDER = [
{column: 2, ascending: true}, // 3 = column number, sorting by descending order
{column: 1, ascending: false}, // 1 = column number, sort by ascending order
];
function onEdit(e){
multiSortColumns();
}
function multiSortColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(SHEET_NAME);
var range = sheet.getRange(SORT_DATA_RANGE);
range.sort(SORT_ORDER);
ss.toast('Sort complete.');
}
SHEET_NAME = "ALL STUDENTS";
SORT_DATA_RANGE = "D3:E100";
SORT_ORDER = [
{column: 5, ascending: true}, // 3 = column number, sorting by descending order
{column: 4, ascending: false}, // 1 = column number, sort by ascending order
];
function onEdit(e){
multiSortColumns();
}
function multiSortColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(SHEET_NAME);
var range = sheet.getRange(SORT_DATA_RANGE);
range.sort(SORT_ORDER);
ss.toast('Sort complete.');
}

All declarations outside of function are global to the entire project. So all of your range declarations will result in the last declaration. SORT_DATA_RANGE = "D3:E100";
If you want them to be unique to each function then you will have to put them in each function. However, in your case you also must give each function in your project a different name. So you cannot have two functions named onEdit(). You can create two installable onedit triggers and attach them to two different functions.
You also cannot have two multiSortColumns() functions. You can give the multiSortColumns function a parameter and use the same function over again.
Note: this is basic JavaScript. You might do well to do a little reading on your own. I get a lot info from MDN web docs

Related

Google Sheets: Sort Two Columns

In a sheet I have two rows that I'd like to sort on:
ColA: Archived - True/False checkbox
ColB: SortOrder - number, a way I have at the moment to group things
Cols C-G: various details
I have a function that does this from a macro, as I'll add a button to the sheet later to run this:
function SortServices() {
var ss = SpreadsheetApp.getActive();
ss.getRange('A1:B').activate();
ss.getActiveRange().offset(1, 0, spreadsheet.getActiveRange().getNumRows() - 1).sort([{column: 1, ascending: true}, {column: 2, ascending: true}]);
};
I'm having a problem, as there are 1000 rows but only ~300 rows currently have data. Of these, about 200 are unchecked and 100 checked (as Archived). So this sorts the entire colA, then colB, which doesn't correspond to the data cols.
Struggling to explain this, imgs might be better. Here's an example, originally:
After applying the Sort:
The issue must be the rows without data, but ColA has checkboxes, which by default are unchecked. Is there a simple way to get around this? (I don't know much about Sheets)
[Edit] Sorry, should have added what I would like... the rows with no data at the end, same as the first img. When a row is checked as Archived, using Sort would then move it down into the lower section together with other Archived items:
Solution
Divide the data in two sets and sort in the desired order those that meet the requirements (have data in column B).
Code
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var lr = ss.getLastRow()
// original values
var range = ss.getRange(1, 1, lr, 3).getValues()
// cells without data in colB
var filtered = range.filter(function (value, index, arr) {
return value[1] == "";
});
// cells with data in colB
var original = range.filter(x => !filtered.includes(x));
// write
ss.getRange(1, 1, original.length, 3).setValues(original).sort([{ column: 1, ascending: true }, { column: 2, ascending: true }]);
ss.getRange(1 + original.length, 1, filtered.length, 3).setValues(filtered)
}
Thought there would be an easier answer, but this works OK:
Inserted a new colA with formula to create a single sortable column:
=if( isblank(D2), 20000, if(B2=true, 10000+C2, C2 ) )
Then used this script:
function SortServices() {
var ss = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActive().getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 1, ascending: true});
};
Probably add this to a custom menu.

How can I write a script to auto sort a column with formulas and update every time a change is made?

I'm tracking the percentage of different stocks in column 3 and I want them to be automatically sorted by descending order every time the data is updated. The data in column 3 is formulaic. They are not text. How can I write this script?
Spreadsheet Here
tested on your sheet and works:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("TOP PICKS");
var range = sheet.getRange("A2:Z");
function onOpen(e) {
range.sort([{column: 3, ascending: true}]);
}

How do I send autosorted blank rows to the bottom?

I have a script that sorts Column B on edit, but there are two problems with it.
1 - It sends the rows with values to the bottom of the sheet.
2 - The numbers do not sort correctly. They should go in the order of 1,3,4,5,and 20, but when it sorts itself, it orders them as 1, 20, 3, 4, 5. It's like it only recognizes the 2 in 20 and places it after 1.
I've searched forum after forum trying to figure this out with no luck so help would be greatly appreciated.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("050")
var range = sheet.getRange("A6:L200");
// Sorts by the values in column 2 (B)
range.sort({column: 2, ascending: true});
}
I don't know if this makes a difference or not, but the sheet that's being sorted uses VLOOKUP. Each Column from B on uses VLOOKUP.
=IFERROR(VLOOKUP(A6,data2019,3,FALSE),"")
First of all, there's no need to get the blank values in the first place, instead you can use getDataRange() to only get the range you need to sort.
Once you've got your range defined, you can sort it. Your values are not being sorted correctly (this is likely due to formatting of the cell from the VLOOKUP). You can simply set the format of the data range to number format using setNumberFormat('0') then sort the data to the order you're expecting.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("050");
var range = sheet.getDataRange();
var numRows = range.getNumRows();
//sets the formatting of column B to a number in all populated rows
sheet.getRange(1, 2, numRows).setNumberFormat('0');
//sorts range by column B using newly formatted values
range.sort({column: 2, ascending: true});
}

Auto sort script for google sheets by 2 columns

I have multiple sheets that need sorting and they need to be sorted by different columns. This is the script I'm currently running:
function onEdit(){
var sheetNames = ["General Clerk Onboarding Tracker"];
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheetNames.forEach(function(name) {
var sheet = ss.getSheetByName(name);
var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
range.sort([{column: 10, ascending: true}]);
});
}
I want to add another range sort column so it'll sort by column 10 first, THEN by column 17. I can't seem to get it to auto-sort 2 columns. Any help would be appreciated!
I think you would just be looking to modify your last line as follows:
range.sort([{column: 10, ascending: true}, {column: 17, ascending: true}]);
I think this might help Additional Sorting Rules have a look and if not I will have a further look into it for you.
Good Luck :)

auto sorting multiple columns, secondary column triggers resort too

I have a sorting question. I have two columns in my table that I need to sort by (primary=column 1, secondary=column 4). I am using the script below and it works for sorting by column 1, and it works for sorting column 4 if I also make a change in Column 1 but not by itself. I would like to be able to edit a value JUST column 4 value and have it do the secondary sort.
Ex: Column 1: Date, Column 2: LastName, Column 3: DOB, Column 4: Payment
I'd like to maintain the spreadsheet in date order (ascending, allowing repeat values), but secondarily organized by payment amount (ascending). That way I can see by date the order of highest to lowest payments. If I change JUST the payment data in a cell, I'd like it to resort by column 1 (date) and then 4 (payment). This script is not accomplishing that last bit. Any advice?
/**
* Automatically sorts the 1st column (not the header row) Ascending.
*/
function onEdit(event){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var editedCell = sheet.getActiveCell();
var columnToSortBy = 1;
var tableRange = "A2:T99"; // What to sort.
if(editedCell.getColumn() == columnToSortBy){
var range = sheet.getRange(tableRange);
range.sort( [1, 4] ); // or
range.sort( [{ column: 1, ascending: true }, 4] ); // or
range.sort( [{ column: 1, ascending: true }, { column: 4, ascending: true }] );
}
}
Probably I don't understand the problem? I suggest to change your if statement from
if(editedCell.getColumn() == columnToSortBy){
...
}
to
if((editedCell.getColumn() == columnToSortBy) || (editedCell.getColumn() == 4)){
...
}

Resources