I am using Kendo Grid and using the methods suggested in this Article by Kendo. I am more interested towards the first approach as I find it faster than the 2nd approach.
The problem is if the number of records 65535, then it throws error
Invalid Row number (65536) outside allowable range (0..65535)
I am not able to find any solution to this. Done lot of research, tried the other method but that seems way too slow for my clients liking.
First you need to check if the row numbers are greater than 65535, if they are then you need to split the data in multiple sheets like so...
//create new workbook
var workbook = new HSSFWorkbook();
//create sheet
var sheet = workbook.CreateSheet();
//declare row number
int numberOfRow = 1;
//add value to sheet name inorder not to receive error that the sheet name already exists
int i = 0;
if(numberOfRow > 65535)
{
sheet = workbook.CreateSheet("(Name of sheet " + ++i + ")");
numberOfRow = 1;
//include your header row here
}
Related
I'm looking for a way to conditionally format a cohort table in Google Sheets so that the colors will change from red (low values) through yellow (medium values) to green (high values) based on the values in each row. Anyone knows if this is possible?
Also, choosing the "Color scale" option in conditional formatting menu doesn't work because it colors the table based on the values of the full table, not each row individually.
I can use that option only if I apply it to each row individually, but my dataset has thousands of entries so that doesn't work for me.
Example table: https://docs.google.com/spreadsheets/d/1gpLMdgfs10Flt-VTtsc68E3Feju2H8UQhnai-R_9b3k/copy
Thanks in advance you guys are the greatest!
I wrote a simple script in Apps Script to apply the formatting to every row. It achieves the gradient per row that you want.
Example:
function applyColorGradientConditionalFormat(min = '#FF0000', mid = '#FF9900', max = '#00FF00') {
const sheet = SpreadsheetApp.getActiveSheet();
const lastCol = sheet.getLastColumn();
const conditionalFormatRules = sheet.getConditionalFormatRules();
// Build this conditional rule for all rows in sheet
for (let i = 2; i <= sheet.getLastRow(); i++) {
let range = sheet.getRange('R' + i + 'C2:R' + i + 'C' + lastCol);
let rule = SpreadsheetApp.newConditionalFormatRule()
.setRanges([range])
.setGradientMinpoint(min)
.setGradientMidpointWithValue(mid, SpreadsheetApp.InterpolationType.PERCENT, '50')
.setGradientMaxpoint(max)
.build()
conditionalFormatRules.push(rule);
}
// Apply all conditional rules built to the sheet
sheet.setConditionalFormatRules(conditionalFormatRules);
};
// Easy improvements: Create a menu to build all conditional formats manually
// or setup triggers to do it automatically
For your sample sheet this results in the following table:
Useful documentation:
Class ConditionalFormatRuleBuilder
getConditionalFormatRules()
non scripted:
=(B2:M2=MAX($B2:$M2))*($B2:$M2<>"")
=(B2:M2=MIN($B2:$M2))*($B2:$M2<>"")
Trying to ditch Excel for Google sheets.
I have this empty table with some colored cells that I need to fill with symbols. Presently I use this VBA script to do the job:
Sub mark()
Dim r As Range
Dim rCell As Range
Set r = Selection.Cells
For Each rCell In r
If rCell.Interior.ColorIndex = 10 Then rCell.Value = "×"
If rCell.Interior.ColorIndex = 3 Then rCell.Value = "×"
If rCell.Interior.ColorIndex = 45 Then rCell.Value = "×"
If rCell.Interior.ColorIndex = 1 Then rCell.Value = "×"
If rCell.Interior.ColorIndex = 15 Then rCell.Value = "×"
Next
End Sub
Is there a way to accomplish same thing using google sheets?
Solution
In order to achieve this you will have to use Google Apps Script. You can attach an Apps Script project to your Google Spreadsheet by navigating Tools > Script Editor.
You should find a template function called myFunction, a perfect starting point for your script.
Here you can start translating your VBA script to Apps Script which is very similar to Javascript.
First you should define some constants for your script:
// An array containing the color codes you want to check
const colors = ['#00ff00']; // Watch out, it's case sensitive
// A reference to the attached Spreadsheet
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SheetName'); // Selecting the Worksheet we want to work with by name
// Here we retrieve the color codes of the backgrounds of the range we want to check
const range = ss.getDataRange().getBackgrounds(); // Here I select all the cells with data in them
Let's now loop through our range rows and columns to apply the logic:
The .getBackgrounds() method returns a multidimensional array in the form array[row][column] -> "background-color-code".
for (let i = 0; i<range.length; i++) {
let row = range[i];
// Let's loop through the row now
for (let j = 0; j< row.length; j++) {
let color = row[j];
// If the background color code is among the ones we are checking we set the cell value to "x"
if(colors.includes(color)) {
// Javascript index notation is 0 based, Spreadsheet one though, starts from 1
ss.getRange(i+1, j+1).setValue("x"); // Let's add 1 to our indexes to reference the correct cell with the .getRange(row, column) function
}
}
}
Reference
Please take a look at the documentation for further reading and method specifications
Google Apps Script Spreadsheet Service
Range Class
.getBackgrounds()
.getRange(row,column)
//Sample sheet here
Hi,
I am using formulas to calculate an array N:R. Once calculated, I want to determine the last row of the array with a non-empty cell (the empty cells are not blank).
What I can do so far:
Return the last non-empty cell of a column
=INDEX(FILTER(O:O,O:O<>""), ROWS(FILTER(O:O,O:O<>"")))
or the row of the filter selection (in my case 25 in the filter selection vs 38 in the sheet)
=ROWS(FILTER(O:O,O:O<>""))
What I haven't figured out is how to:
Do this search for the whole array and not just one row at a time
Return the row of the last non-empty cell in the array
Cheers
For a formulaic approach, you can try
=max(filter(row(N2:N), MMULT(N(N2:R<>""), transpose(column(N2:R2)^0))>0))
This custom function will do it. Sometimes scripts are way easier than some of the bizarre formulas that arise (IMHO). It just loops through the data row by row and notes the row number if it finds data ie cell.value() != ""
function findHighestNonEmptyRow(dummyRange){
var sheet = SpreadsheetApp.getActive();
var range = sheet.getRange("N:R");
var valuesRC = range.getValues();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var highestNonEmptyRow = 0;
for (var row = 0; row < numRows; row++) {
for (var col = 0; col < numCols; col++) {
if (valuesRC[row][col] != ""){
highestNonEmptyRow = row+1; // +1 to offset loop variable
}
}
}
Logger.log(highestNonEmptyRow);
return highestNonEmptyRow;
}
Log show correct value of 38. You can delete the Logger.log(highestNonEmptyRow); line when you have tested.
I put the formula in W44 in your test sheet....
EDIT: Due to feedback that all was not as expected...
There was a typo in the first script: This line var range =
sheet.getRange("N:D"); should have been var range =
sheet.getRange("N:R");
I found out that Google scripts caches the result of custom
formulas, and just returns the cached value, even if things on the
sheet have changed. This is bizarre behavior, but is intended to
reduce CPU time. The workaround is to pass in a range that is likely
to change, and this causes the function to recalculate. I updated
the formula and the called the function like this:
=findHighestNonEmptyRow(N2:R42)
and hey it all works!
Stick to the formula... however, we both learned a lot from your
question I think, so thanks for that!
I am new at this so still trying to figure how everything works.
I have a sheet that collects responses from a Google Form. Based on the answer to one of those questions I would like the row from that sheet to move to a different sheet document all together (not a sheet in the same document).
I have it set on a time based trigger every minute so as new responses come in it would kick them over to the correct document and then delete the row from the original spreadsheet.
I have been able to get part of the way there. I would like for it to take the row, columns A through E, move those to the correct document, find where the next open row is and place the data in columns A through E on the new document.
Where my issue is coming in at the moment is when the row is moved to the new document. I have formulas saved in columns G - Z on the destination page. It is finding the last row with a formula and placing the row after that (which is at the very bottom of the page). I am pretty sure this has to do with using an array? But I may be wrong. Is there a way to just have that look at the destination page column A-E, find the next blank row, and copy A-E from the original file to the new page?
arr = [],
values = sheetOrg.getDataRange().getValues(),
i = values.length;
while (--i) {
if (value1ToWatch.indexOf(values[i][1]) > -1) {
arr.unshift(values[i])
sheetOrg.deleteRow(i + 1)
sheet1in.getRange(sheet1in.getLastRow()+1, 1, arr.length, arr[0].length).setValues(arr);
};
I have multiple If statements each with some changes to the "valueToWatch" and the "Sheet1in" for different values and destination pages. If that information helps at all.
You can find the last cell in a column with data in it like this:
function findLastValueInColumn() {
var column = "A"; // change to whatever column you want to check
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var lastDataRow = sheet.getDataRange().getLastRow();
for (var currentRow = lastDataRow; currentRow > 0; currentRow--) {
var cellName = column + currentRow;
var cellval = sheet.getRange( cellName ).getValue();
if (cellval != "") {
Logger.log("Last value in Column " + column + " is in cell " + currentRow);
break;
}
}
}
You can then use this function to figure out where to start your new data.
Spreadsheet data looks like this
function myFunction()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Active Listeners');
sh.insertRowBefore(15551)
}
As i have large range of rows that could be work on. If the value of the range matches with "Apr 9" then insert row before to that. Could anyone help me to get that.
A 'for loop' to cycle through your rows from the bottom would almost do the trick. The loop inserts a row after each row specified by i. Keep in mind you'll need a different solution if your Apr 9 column is formatted as a date. This works for plain text only. You can select the column and change to plain text with "Format > Number > Plain Text" on the menu.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Active Listeners');
//var shlen = sh.getDataRange().getLastRow(); //returns integer last row
var shlen = Browser.inputBox("Enter Last Row of Preferred Range", Browser.Buttons.OK_CANCEL);
var ecell = sh.getActiveCell().getA1Notation();
You may need a different dataRange (below), I've just grabbed the parameters of data in your whole sheet (above), then grabbed a range specified in A1 notation of "A1:B[number reference of bottom row]" The modification may be that you need "B1:C" + [shlen] or whichever other range.
if (shlen >= 1) {
var dataRange = sh.getRange("A1:A" + shlen).getValues();
for (var i = shlen; i > 0; i--) {
var row = dataRange[i-1];
if (row[0] == "Apr 9") {
sh.insertRowAfter(i-1)
}
}}
}
Someone more knowledgeable than me can pitch in if they have a better answer, but my only solution (which should be ok if it's a one-of) would be to just repeat the script a few times, starting at the row of your choice each time. Select cell A1 and then press "control (or command) + down arrow". It will take you to the first gap, which should be where the previous script ended. Remember the row number you're up to and plug that in the input box when you run the script again. Might take a few iterations but you'll get there.
If this process is going to be done repeatedly then best of luck in finding a solution :)