In Google Spreadsheets, if cell A > cell B, replace Cell B with Cell A - excel

I currently have a column labeled "Current Rank" in column A, and a column labeled "Highest Rank" in column B. If current rank > highest rank, I'd like to replace highest rank with current rank. Is there any way to do this while getting around the self-reference errors?

You can list all the scores and use the formula =max() to find the biggest one, but to actually replace the cell "B" with the bigger value, the only way is with a script, Google's version of Excel macros. You'd have to make something like this, and run it after you put in the new values (this is my first google script, there is most certainly cleaner way, but this code gets the job done)
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range=sheet.getRange("A1:A100")
var j=0;
for(var i in range){
if(range.getValues()[j]!=undefined){
if(sheet.getRange("B" + (j+1)).getValue()<range.getValues()[j][0]){
sheet.getRange("B" + (j+1)).setValue(range.getValues()[j][0]);
}
}
j++;
}
}
To make a script, open tools>script editor.

You need a script, but this is not a hard one.
An onEdit trigger is a little cleaner, works automatically. Open the editor via tools, paste this into an empty file. You're done. This script will evaluate column a and column b every time a change is made on the sheet.
Enter data into column A, and the max result will appear in column B (this script assumes there is a header row, data on row 1 won't get evaluated.)
function onEdit(e) {
var ss = e.source;
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var values = range.getValues();
for(var i = 1; i < values.length; i++) {
if (values[i][0] > values[i][1]) {
sheet.getRange(i + 1, 2, 1, 1).setValue(values[i][0]);
}
}
}

Related

Total Rows and Columns Count - Excel Office JS

I've been using getRangeByIndexes as it seems to be the best way to use numbers to get Ranges in Office-JS. Problem I'm having is that when I need to use entire row/columns, I've resorted to the below. I read up and looks like number of rows/cols hasn't changed in a long time, but I know in vba I used rows.count to make sure the code was dynamic, whatever version of Excel it would use the number of rows on a spreadsheet.
Is there anything similar in Office-JS?
const Excel_Worksheet_Lengths_Obj = {
"total_rows": 1048576,
"total_cols": 16384,
}
var ws = context.workbook.worksheets.getActiveWorksheet()
var Method_Headers_Rng = ws.getRangeByIndexes(0,0,1,Excel_Worksheet_Lengths_Obj.total_cols)
This will do it for you ...
const sheet = context.workbook.worksheets.getActiveWorksheet();
let rangeRows = sheet.getRange("A:A").load(["rowCount"]);
let rangeColumns = sheet.getRange("1:1").load(["columnCount"]);
await context.sync();
console.log("Row Count = " + rangeRows.rowCount);
console.log("Column Count = " + rangeColumns.columnCount);
Everything relating to the number of rows or columns looks to be done at the range level, not the worksheet level.
Passing in the first column to achieve the number of rows and the first row to achieve the number of columns does the trick. Not ideal but such is life.

Officescript how to set value in table cell (row/column) by row index

pretty simple question but I can't seem to find what I am looking for and wondering if it is possible this way, just starting using Officescript/typescript. In a part of my code, I get the index of the row with a value that matches (cRow is the index of row I am interested in).
rowValue = collectionTable.getColumnByName("SomeCol").getRangeBetweenHeaderAndTotal().getValues()[cRow]
And then I run some checks on that row and want to update some other things based on the inputs.
So what I am expecting to do is something like the following, changing getValues for setValues:
collectionTable.getColumnByName("UpdateMe").getRangeBetweenHeaderAndTotal().setValues()[cRow]
OR
let col = collectionTable.getColumnByName("SomeCol").getIndex();
let cell = collectionTable.getCell(requestRow,col);
cell.setValue(value);
But doesn't seem to work that way .. From what I can tell, setValues works on ranges but can't quite find how to get the range/row by index number and set a value in one cell. I see all examples doing it with the letter and number but don't want to do it that way if possible.
Thanks for the help!
You can use getCell with the cRow variable after getRangeBetweenHeaderAndTotal() to get a specific cell range. Once you have that range, you can read its value using getValue(). And you can write a value to that range using setValue(). You can see an example of how to do that below:
function main(workbook: ExcelScript.Workbook)
{
let cRow: number = 1;
let tbl: ExcelScript.Table = workbook.getTable("table1");
let rowCell: ExcelScript.Range = tbl.getColumnByName("SomeCol").getRangeBetweenHeaderAndTotal().getCell(cRow,0);
let rowValue: string = rowCell.getValue() as string;
rowCell.setValue("some updated value");
}
Can get the value by using the worksheet cell, but I would really like to reference the table itself to not have any issues if things are moved around and such..
let col = collectionTable.getColumnByName("SomeCol").getIndex();
// if table starts at beginning of sheet, or else have to offset col and row..
let cell = dataSheet.getCell(requestRow + 1, col);
cell.setValue(value);

Identifying spreadsheet cells where a string appears multiple times using VBA or Google Apps Script

I'd like to highlight cells in which there are repeated words. For example,
A1: Best jackets in town.
A2: Best jackets in in town.
A3: Best Best Jackets in Town.
I'd like to highlight A2 & A3 as the words "in" and "best" are occuring multiple times in them. How do I do this using VBA?
Would be fine with a Google Apps Script solution too.
No script: conditional formatting
If one takes the position that words are separated only by spaces, and that repetition anywhere in the string is acceptable (i.e., "cry baby cry" also counts as repetition), then a script isn't needed: conditional formatting in Google Sheets can do the job. Apply it with custom formula
=len(join(" ", unique(transpose(split(A1, " "))))) < len(A1)
where A1 should be replaced with the upper left corner of the range being formatted.
The idea is to split the string by spaces, pick unique words with unique, and put them together. If the result is shorter than the original, there was some repetition.
Google Apps Script solution
Google Apps Script can use any JavaScript regular expression methods, allowing for a wider range of text processing rules.
Version 1: back-to-back repetition: "best game in in town" matches but "cry baby cry" does not. This is expressed by the regex
\b(\w+)\W+\1\b
Version 2: unrestricted repetition: both "best game in in town" and "cry baby cry" match. Expressed by the regex
\b(\w+)\b.*\b\1\b
Any regex you choose goes into re variable in the following script, which processes all values in the currently active sheet. It chooses a background for each cell and sets it with setBackgrounds.
function repeated() {
var re = /\b(\w+)\W+\1\b/;
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var backgrounds = range.getBackgrounds();
var values = range.getValues();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[0].length; j++) {
backgrounds[i][j] = re.test(values[i][j]) ? "yellow" : "white";
}
}
range.setBackgrounds(backgrounds);
}

Making Google sheets for entries made today, this week, and this month

I have a Google sheet that pulls information from a form. The form inputs a timestamp and IDnumber into a spreadsheet. I need to make different sheets to show which of these entries were made Today, This week, and This month.
Example
Timestamp ID
12/1/2012 12345
12/1/2012 55555
12/4/2012 98765
12/15/2012 74823
I need to make a sheet that puts ID 12345 and 55555 into one "DAILY" Sheet, IDs 12345, 55555, and 98765 into a "WEEKLY" sheet, and one that has all of these in a "MONTHLY" sheet.
Here's what I would do...
Add today's date somewhere in the sheet (let's say cell D2) by inputting '=Today()' in D2.
In column C, next to your first two columns, add formulas to calculate the number of days between the date in column A and today's date. In row 2, the formula would look like this...
=DATEDIF(A2,D2,"D")
Then, using the script editor in the spreadsheet, I would write a script that looks at column C and writes values from column A and B depending on that value. I haven't tested the script below, but I think it's what you would need. Essentially, it loops through column C of your results sheet. Depending on the value (days from today), that row is pushed to an array for each range. Then I cleared the sheet for that range before setting the values of the array. I hope this helps!
function daysBetween(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(),
formResultsSheet = spreadsheet.getSheetByName("Form Results"),
daySheet = spreadsheet.getSheetByName("Today"),
weekSheet = spreadsheet.getSheetByName("This Week"),
monthSheet = spreadsheet.getSheetByName("This Month"),
allData = formResultsSheet.getDataRange().getValues(),
dayResults = [],
weekResults = [],
monthResults = [];
for (var i = 0; i < formResultsSheet.getLastRow(); i++) {
if (allData[i][2] === 0){
dayResults.push(allData[i])
} else if (allData[i][2] > 0 && allData[i][2] <= 7) {
weekResults.push(allData[i])
} else if (allData[i][2] > 7 && allData[i][2] <= 30) {
monthResults.push(allData[i])
}
}
daySheet.getDataRange().clear()
daySheet.getRange(1,1,dayResults.length,dayResults[0].length).setValues(dayResults)
weekSheet.getDataRange().clear()
weekSheet.getRange(1,1,weekResults.length,weekResults[0].length).setValues(weekResults)
monthSheet.getDataRange().clear()
monthSheet.getRange(1,1,monthResults.length,monthResults[0].length).setValues(monthResults)
}

Read from a specific row onwards from Excel File

I have got a Excel file having around 7000 rows approx to read. And Excel file contains Table of Contents and the actual contents data in details below.
I would like to avoid all rows for Table of Content and start from actual content data to read. This is because if I need to read data for "CPU_INFO" the loop and search string occurrence twice 1] from Table of Content and 2] from actual Content.
So I would like to know if there is any way I can point to Start Row Index to start reading data content for Excel File , thus skipping whole of Table Of Content Section?
As taken from the Apache POI documentation on iterating over rows and cells:
In some cases, when iterating, you need full control over how missing or blank rows or cells are treated, and you need to ensure you visit every cell and not just those defined in the file. (The CellIterator will only return the cells defined in the file, which is largely those with values or stylings, but it depends on Excel).
In cases such as these, you should fetch the first and last column information for a row, then call getCell(int, MissingCellPolicy) to fetch the cell. Use a MissingCellPolicy to control how blank or null cells are handled.
If we take the example code from that documentation, and tweak it for your requirement to start on row 7000, and assuming you want to not go past 15k rows, we get:
// Decide which rows to process
int rowStart = Math.min(7000, sheet.getFirstRowNum());
int rowEnd = Math.max(1500, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn = 0; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
} else {
// Do something useful with the cell's contents
}
}
}

Resources