I'm using the following code to get all the value of all my sheets that have a numeric name. Once it find a numeric sheet name, it must sum row 8 to 108 of column 6. All the sheets must be sum in the right array. Right now, my script add the data in the array after then it crash instead of doing a sum.
example (cell = value : variable = value)
sheet 1 (8,6)=1 : colonne[1] = 1
sheet 2 (8,6)=2 : colonne[1] = 3
sheet 3 (8,6)=3 : colonne[1] = 6
sheet 1 (8,7)=2 : colonne[2] = 2
sheet 2 (8,7)=2 : colonne[2] = 4
sheet 3 (8,7)=2 : colonne[2] = 6
function CalculTotal() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var substring1;
var colonne=[];
for (var i=0 ; i<sheets.length ; i++)
{
substring1=sheets[i].getName();
if(!isNaN(parseFloat(substring1)) && isFinite(substring1)){
colonne=colonne+(ss.getSheetByName(substring1).getRange(8,6,100).getValues());
}
}
s.getRange(8,4,100).setValues(colonne);
}
Try this:
function CalcTotal() {
var ss=SpreadsheetApp.getActive();
var sheets=ss.getSheets();
var regex=new RegExp('^[\\d\\.,]+$')
var total=0;
var n=1;
var html='<style>th,td{border:1px solid #000;}</style><table>';
html+=Utilities.formatString('<tr><th>%s</th><th>%s</th><th>%s</th></tr>','Item','Sheet','Sum')
for(var i=0;i<sheets.length;i++){
var name=sheets[i].getName();
var sum=0;
var nameisnum=false;
var result=regex.exec(name);
if(result){
nameisnum=true;
var shi=ss.getSheetByName(name);
var rgi=shi.getRange(8,6,101,1);
var vAi=rgi.getValues();
for(var j=0;j<vAi.length;j++){
sum+=vAi[j][0];
}
if(nameisnum){
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',n++,name,sum);
total+=sum;
}
}
}
html+=Utilities.formatString('<tr><td colspan="2">Total:</td><td>%s</td></tr>',total);
html+='</table>';
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Sheet Sums');
}
Here is an example of how to add 2 arrays, but notice this is done in the form of a 2D array. getValues() returns an array of array[i] i = number of rows, array[i][j] j is the column both indexes start with 0. setValues() works the same way but places a 2D array.
function CalculTotal() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var substring1;
var colonne=[];
// Initialize result array
for( var i=0; i<100; i++ ) colonne[i] = [0];
for (var i=0 ; i<sheets.length ; i++)
{
substring1=sheets[i].getName();
if(!isNaN(parseFloat(substring1)) && isFinite(substring1)){
var values = ss.getSheetByName(substring1).getRange(8,6,100,1).getValues();
for( var j=0; j<values.length; j++ ) {
colonne[j][0] = colonne[j][0]+values[j][0];
}
}
}
s.getRange(8,4,100,1).setValues(colonne);
}
Related
Right now, If i run for loop
{“FirstName” : “Kim”}
{“LastName” : “hana”}
{“Phone” : “010-1234-5648”}
{“Email” : “abc#gmail.com”}
It comes out like this.
But the result I want is
{“FirstName” : “Kim”, “LastName” : “hana”, “Phone” : “010-1234-5648”, “Email” : “abc#gmail.com”}
I want to make it come out like this.
What should I do?
This is my code that I just wrote.
function testRun(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var LastRow = ss.getLastRow();
var LastCol = ss.getLastColumn();
var arr = [];
for(var i = 1; i<=LastCol; i ++){
var fieldName = ss.getRange(1,i).getValue();
arr.push(fieldName);
}
//arr = [FirstName, LastName, Phone, Email]
for(var i =2;i<=LastRow;i++){
for(var j=1;j<=LastCol;j++){
var payload = Utilities.jsonStringify({
[arr[j-1]] : ss.getRange(i,j).getValue()}
);
}
}
}
Modification points:
In your showing script, it seems that payload is not used.
When getValue() is used in a loop, the process cost becomes high. Ref
When these points are reflected in a sample script for achieving your goal, it becomes as follows.
Sample script:
When your showing script is modified, how about the following modification?
function testRun() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var LastRow = ss.getLastRow();
var LastCol = ss.getLastColumn();
var [header, ...values] = ss.getRange(1, 1, LastRow, LastCol).getValues();
var arr = [];
for (var i = 0; i < LastRow - 1; i++) {
var temp = {};
for (var j = 0; j < LastCol; j++) {
temp[header[j]] = values[i][j];
}
arr.push(temp);
}
console.log(JSON.stringify(arr))
}
When this script is run, arr is [{"FirstName":"Kim","LastName":"hana","Phone":"010-1234-5648","Email":"abc#gmail.com"}].
As another apporach, I thought that you might be able to also use the following sample script.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var [header, ...values] = ss.getRange(1, 1, ss.getLastRow(), ss.getLastColumn()).getValues();
var arr = values.map(r => header.reduce((o, h, j) => (o[h] = r[j], o), {}));
console.log(JSON.stringify(arr))
Your code creates separate objects in each iteration. Create an empty object for every Person, then add the properties you need.
This should look something like this:
for(var i=2; i<=LastRow; i++){
var payload = {}
for(var j=1; j<=LastCol; j++){
payload[arr[j-1]] = ss.getRange(i,j).getValue()};
}
}
Here is the code I have worked on- I have tried many different combinations and none of them are giving me the desired results- Can you please explain why my code is incorrect?
the code is iterating the the rows looking for rows larger than 0- if so, copy the row to the target sheet- However I am getting the wrong rows copied over?
function try2() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var lastrow = sheet2.getLastRow()+1;
var target = sheet2.getRange(lastrow,1,1,5);
var data = sheet1.getRange('E1:E500').getValues();
for(var i=1; i< data.length; i++) {
Logger.log(i)
if (data[i] > 0) {
Logger.log(data[i])
sheet1.getRange(i, 1, 1, 5).copyTo(target);
}
}
}
I updated the code to have the lastrow & target variables in the for loop with still undesired results.
function try2() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var data = sheet1.getRange('E1:E500').getValues();
for(var i=1; i< data.length; i++) {
var lastrow = sheet2.getLastRow()+1;
var target = sheet2.getRange(lastrow,1,1,5);
//Logger.log(i)
if (data[i] !== "") {
Logger.log(data[i])
sheet1.getRange(i, 1, 1, 5).copyTo(target);
}
}
}
Requirement:
Copy data from one sheet to the next free row of another sheet.
Solution:
function try2() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var targetLastRow = sheet2.getLastRow() + 1;
var dataLastRow = sheet1.getLastRow();
var dataRange = sheet1.getRange(1,5,dataLastRow);
var data = dataRange.getValues();
for(var i = 0; i < data.length; i++) {
if (data[i]) {
sheet1.getRange(i+1, 1, 1, 5).copyTo(sheet2.getRange(targetLastRow+i,1));
}
}
}
Explanation:
This script will loop through all of the rows in column E on your first sheet, and copy any that aren't blank across to your sheet "Final". By using dataLastRow to get the data. You save time over defining a set range E1:E500, the script will now only get the necessary amount of rows to run the copy whereas before it was running the for loop 500 times no matter what.
The data is copied to targetLastRow+i, which is the next available row of sheet "Final", incremented by 1 every time the loop completes.
Code that worked altering #ross code- Thanks
function try3() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Final');
var targetLastRow = sheet2.getLastRow() + 1;
var dataLastRow = sheet1.getLastRow();
var dataRange = sheet1.getRange(1,5,dataLastRow);
var data = dataRange.getValues();
for(var i = 0; i < data.length; i++) {
Logger.log(data[i])
if (data[i] > 0) {
Logger.log(data[i])
sheet1.getRange(i+1, 1, 1, 5).copyTo(sheet2.getRange(targetLastRow+i,1));
}
}
}
I am trying to convert a VBA macro that rearranges columns on a sheet from an array of column indices to a Google script
I want to return all columns but with the columns listed in the array as the first 3 columns and all the other columns in their same order
The original vba is using header names but I am using column indices
I get error Incorrect range height, was 1 but should be 24
I have no idea if there are other issues as well
Thanks in advance
Here is what I have
function myFunction() {
var sheet =SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var data = sheet.getDataRange().getValues();
var LC = sheet.getLastColumn();
var LR = sheet.getLastRow();
var headers = [4,2,3]; //array of colunm indices
var temp = [];
var Dex = 0
for (var i = 0; i < LC; i++) {
for(var j = 0; j < LC; j++) {
for (var F = 0; F < headers.length - 1; F++) {
if (headers[F] = data[j]) {
Dex = F
break;
};
}
if (F < i) {
temp = data.indexOf(i);
data[i] = data.indexOf(j)
data[j] = temp
}
};
};
sheet.getRange(1, 1, LC,LR).setValues([data])
}
Here is the vba
Sub vba()
Dim rng As Range
Dim i As Integer
Dim J As Integer
Dim Temp
Dim nams As Variant
Dim F
Dim Dex As Integer
nams = Array("ItemID", "FirstName", "LastName", "Year")
Set rng = Range("A1").CurrentRegion
For i = 1 To rng.Columns.Count
For J = i To rng.Columns.Count
For F = 0 To UBound(nams)
If nams(F) = rng(J) Then Dex = F: Exit For
Next F
If F < i Then
Temp = rng.Columns(i).Value
rng(i).Resize(rng.Rows.Count) = rng.Columns(J).Value
rng(J).Resize(rng.Rows.Count) = Temp
End If
Next J
Next i
End Sub
Try this:
function moveColumns() {
var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var rg= sh.getDataRange()
var vA=rg.getValues();
var vB=[];
var first3 = [8,7,6,5];
var first3desc=first3.slice();
first3desc.sort(function(a, b){return b-a;});
for(var i=0;i<vA.length;i++){
var row=vA[i];
for(var j=0;j<first3.length;j++){
row.splice(j,0,vA[i][first3[j]-1+j]);
}
for(var j=0;j<first3desc.length;j++){
var c=first3desc[j]-1+first3.length;//for debugging
row.splice(first3desc[j]-1+first3.length,1);
}
vB.push(row);
}
sh.getRange(1,1,vB.length,vB[0].length).setValues(vB);
}
Here's the function as I run it this time.
function moveColumns() {
var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var rg= sh.getDataRange()
var vA=rg.getValues();
var vB=[];
var first3 = [8,7,6,5,4,3,2,1];
var first3desc=first3.slice();
first3desc.sort(function(a, b){return b-a;});
for(var i=0;i<vA.length;i++){
var row=vA[i];
for(var j=0;j<first3.length;j++){
row.splice(j,0,vA[i][first3[j]-1+j]);
}
for(var j=0;j<first3desc.length;j++){
var c=first3desc[j]-1+first3.length;
row.splice(first3desc[j]-1+first3.length,1);
}
vB.push(row);
}
sh.getRange(1,1,vB.length,vB[0].length).setValues(vB);
}
My "Elements" sheet before:
My "Elements" sheet after:
On this line
var data = sheet.getDataRange().getValues();
data gets a 2D array, but later the script handled it as 1D array. In other words, to reference a cell value, instead of data[index] use something like data[row][column].
A single equal sign = is use to assign an object/literal to a variable so this headers[F] = data[j] instead of doing a comparison replaces the value of headers[F] by the object of data[j] which initially is an array.
I am looping through a range of data in a Google spreadsheet in JavaScript.
The problem I'm having is I have some merged cells that have the same value, for example C:6 to E:6 all have the same value as those 3 cells are merged.
So in my loop it will show C:6 = 'Focus and targeting' D:6 = '' and E:6 = '' What I'm trying to do is in my loop assign the 2nd and 3rd values to the first cell value.
Here is what I have:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Audit');
var range = sheet.getDataRange();
var numRows = range.getNumRows();
var numCols = sheet.getMaxColumns();
var values = range.getValues();
var count = 0;
for (var i = 2; i <= numCols - 2; i++) {
var questionCategory = values[5][i];
if(questionCategory == undefined) {
continue;
}
if(questionCategory == "") {
// need to assign 2nd and 3rd cells of merged list to have the value of 1st cell in merged list
}
count++;
}
Here is what the data looks like:
Any ideas how I can achieve this?
Here is custom function to get merged cell value:
function getMergedCellValue(cellRange)
{
if (!cellRange.isPartOfMerge())
{
return cellRange.getDisplayValue();
}
return cellRange.getMergedRanges()[0].getDisplayValue();
}
And updated code using this function:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Audit');
var range = sheet.getDataRange();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var values = range.getValues();
var count = 0;
var questionRowNum = 6;
for (var i = 0; i < numCols; i++)
{
// assign 2nd and 3rd cells of merged list to have the value of 1st cell in merged list
var questionCategory = values[questionRowNum-1][i] || getMergedCellValue(sheet.getRange(questionRowNum, i+1));
count++;
}
I'm trying to transpose (copy column content into a row) a range from one sheet to another. Yet the catch is that each row has a different number of columns populated, and I don't want to have blank columns copied over into the output sheet.
So I was trying to do the following:
Go to 'import manipulation' tab
row by row (in a loop), check what the last POPULATED column is
Then col by col (second loop), copy each cell's value then paste it onto "Transpose" sheet in the first available row
Keep doing this until the last Populated column was copied over, and then move onto the next row
Repeat
I've ran the debugger and nothing comes up, however when I run the function it doesn't paste anything into the "Test" sheet. Any suggestions?
function transpose(sh) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Import Manipulation");
var lastrow = sh.getLastRow();
var numrows = lastrow;
for(var i= 1; i<= numrows; i++) {
Logger.log(i);
var rowrange = sh.getRange(i, 50);
Logger.log(rowrange);
var lastcol = rowrange.getValues().length;
for(var j=5; j<= lastcol; j++) {
var colrange = sh.getRange(i,j);
var copycell = colrange.getValue();
var pastesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test");
var pasterow = pastesheet.getLastRow();
Logger.log(pasterow);
var pastecell = pastesheet.getRange(pasterow + 1, 1);
Logger.log(pastecell);
var doit = pastecell.setValue(copycell);
doit(pastecell);
}
}
}
I was able to do it so that it transposes, and it's working (albeit probably not the most efficient).... appreciate suggestions for how to make it more efficient!
function transpose(sh) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Import Manipulation");
var lastrow = sh.getLastRow();
var numrows = lastrow;
var lastcol = sh.getLastColumn();
for(var i= 1; i<= numrows; i++) {
Logger.log(i);
var rowrange = sh.getRange(i,1,1,lastcol);
Logger.log(rowrange);
for(var j=5; j<= lastcol; j++) {
var colrange = sh.getRange(i,j);
var copycell = colrange.getValue();
var pastesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Transpose");
var pasterow = pastesheet.getLastRow();
Logger.log(pasterow);
var pastecell = pastesheet.getRange(pasterow + 1, 1);
Logger.log(pastecell);
pastecell.setValue(copycell);
}
}
}
This line of code:
var rowrange = sh.getRange(i, 50);
Is only getting one cell. On the first loop, it gets the cell in row 1 column 50.
The variable lastcol in this line:
var lastcol = rowrange.getValues().length;
will always be 1. getValues() gets a 2D array and in this case it will be [[cellValue]]
I created some new code:
function transpose(sh) {
var arrayThisRow,cellValue,i,j,lastCol,lastrow,numrows,pastesheet,
rowrange,rowValues,sh;
sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Import Manipulation");
pastesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test");
lastrow = sh.getLastRow();
lastCol = sh.getLastColumn();
Logger.log('lastCol: ' + lastCol);
numrows = lastrow;
arrayThisRow = [];
for(i=1; i<= numrows; i++) {
//Logger.log(i);
rowrange = sh.getRange(i,1,1,lastCol);
//Logger.log(rowrange);
rowValues = rowrange.getValues();//
rowValues = rowValues[0];//There is only 1 inner array
for(j=0; j <= lastCol; j++) {
cellValue = rowValues[j];
if (cellValue) {
arrayThisRow.push(cellValue);
} else {
break;//Stop pushing values into the array as soon as a blank cell is found
}
}
}
Logger.log('arrayThisRow: ' + arrayThisRow)
if (arrayThisRow.length > 0) {
pastesheet.appendRow(arrayThisRow)
}
}