I am trying to create an Apps Script function to update the new data at the last row of a range in Google Sheet. My sheet "import" is currently empty and I have the following error when I add my function ImportPrivacyTagCo() into A1 cell : "Exception: Range not found".
function ImportPrivacyTagCo() {
var cellVal= '=IMPORTJSON("myAPIurl")';
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('import');
var lastrow = sheet.getLastRow() + 1
sheet.getRange(lastrow).setValues([cellVal]);
}
Do you have any idea to fix this error ?
Many thanks
Look at how the .getRange() is working.
You need to add the column number. Also it looks like you want to set a formula In that case, use .setFormula() instead.
function ImportPrivacyTagCo() {
var cellVal= '=IMPORTJSON("myAPIurl")';
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('import');
var lastrow = sheet.getLastRow() + 1
sheet.getRange(lastrow, 1).setFormula(cellVal)
}
Related
Example - Screenshot
Hey,
I am trying to create a macro that will duplicate/copy a selected row to the end of a list (which is NOT the last row) within the same sheet. But so far, the only thing I got was to create a row underneath the selected row and duplicate it there.
Attached an screenshot as an example, I need to copy a selected row to the bottom of the list (row10 in this example) and not to the bottom of the sheet (row15 in this example).
Can anyone let me know where I'm going wrong and how I can fix it? This is driving me mad :(
This is what I came up with so far:
function Reschedule() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getActiveSheet().insertRowsAfter(spreadsheet.getActiveRange().getLastRow(), 1);
spreadsheet.getActiveRange().offset(spreadsheet.getActiveRange().getNumRows(), 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getCurrentCell().activate();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(spreadsheet.getCurrentCell().getRow() - 1, 1, 1, sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
};
Thank you so much in advance!
Also, any alternatives that would help me to get the same result is very welcome too!
In your situation, how about the following sample script?
Sample script:
function Reschedule() {
var activeRange = SpreadsheetApp.getActiveRange();
var sheet = activeRange.getSheet();
var row = sheet.getRange("A1").getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
var dst = sheet.getRange(row, 1);
activeRange.offset(0, 0, 1, sheet.getLastColumn()).copyTo(dst, SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
// dst.activate(); // From your showing script, if you want to activate the appended row, please use this.
}
When this script is run after a cell is selected, the row of the selected cell is copied to the next row of the last row of the sheet.
Reference:
getNextDataCell(direction)
So looking at the insertRowsAfter function, the first argument should be set to the highest empty row.
How do we find the highest empty row? Taken from Tanaike's answer, getNextDataCell.
I think your two .activate() calls are best left out--or do you need to change which cells are focused?
Finally, to copy the data, getting the source and target ranges and using getValues and setValues is probably the simplest way.
var sheet = SpreadsheetApp.getActiveSheet();
var firstColumn = 1;
var lastColumn = sheet.getRange("A1").getNextDataCell(SpreadsheetApp.Direction.NEXT).getColumn();
var numColumns = lastColumn - firstColumn + 1;
var sourceRow = sheet.getActiveRange().getRow();
var targetRow = sheet.getRange("A1").getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
sheet.insertRowsAfter(targetRow, 1);
var sourceRange = sheet.getRange(sourceRow,firstColumn,1,numColumns);
var targetRange = sheet.getRange(targetRow,firstColumn,1,numColumns);
targetRange.setValues(sourceRange.getValues());
Example: https://docs.google.com/spreadsheets/d/1GxZdTBRsI20nTphqJIsEPONfMGY3E-BE1-zhgWCgnzw/edit
I am trying to create a data entry form that submits data to a data sheets first open row. The problem is that the data sheet has formula in one of the columns so it is not truly empty. This is causing the current script to take the cells with formula into consideration and only selecting the rows after it.
Could you guys please assist me with a workaround to the issue.
Current script looks like this:
function submitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("FORM"); //Form Sheet
var datasheet = ss.getSheetByName("DATA"); //Data Sheet
//Input Values
var values = [[formSS.getRange("D4").getValue(),
formSS.getRange("D8").getValue(),
formSS.getRange("D12").getValue(),
formSS.getRange("D16").getValue(),
formSS.getRange("D20").getValue(),
formSS.getRange("D24").getValue(),
formSS.getRange("D28").getValue(),
formSS.getRange("L32").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 8).setValues(values);
}
You can find the first free row by evaluating the row contents
Sample
var freeRow;
var columnI = datasheet.getRange("I1:I" + datasheet.getLastRow()).getDisplayValues().flat();
for(var i = 0; i < columnI.length; i++){
if(columnI[i] == "") {
freeRow = i + 1;
break;
}
}
datasheet.getRange(freeRow, 1, 1, 8).setValues(values);
In addition, you are using a Form submit trigger, you use event objects
Sample
function submitData(e) {
var range = e.range;
var row = range.getRow();
// this is the row into which the latest form response has been inserted - do with it what you need
...
}
I have the following app script associated with a Google Spreadsheet that is accepting data from a Google Form:
function writePatientData() {
var spreadsheet = SpreadsheetApp.openById("<spreadsheet id>");
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//get last row in active/main sheet
var numRows = sheet.getLastRow();
//get last row of data
var last_row = sheet.getSheetValues(numRows, 1, 1, 23);
//get patientID (column V) in last row of sheet
var lastPatientID = sheet.getRange(numRows,3).getValue();
//find patient sheet based on patientID and make it active, then write to it
var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
var activePatientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
activePatientSheet.getRange(activePatientSheet.getLastRow()+1, 1,1,23).setValues(last_row);
}
What this script is doing is writing data (a row) to another sheet within this spreadsheet based on the the patientID (column V). This works as it should when I manually run the script. However, when I set a trigger to run this script (either onSubmit or edit) nothing happens. I created another function that just writes a message to the logs and set a trigger for that function and it works, so I think there is something in the script that is causing it to fail. Any ideas appreciated.
There are a few issues with your code. I tried to fix it while commenting each line I changed. Hopefully that is clear enough, please comment if you have any questions and I'll try to clarify.
function writePatientData() {
var spreadsheet = SpreadsheetApp.getActive(); //no need for id if the script is on the same spreadsheet
//var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//setActiveSheet will not work from a trigger like on-form-submit (what if no-one has the sheet open, or multiple have)
var sheet = spreadsheet.getSheets()[0]; //if you want the first sheet, just get it, no need to "activate"
var numRows = sheet.getLastRow();
var last_row = sheet.getSheetValues(numRows, 1, 1, 23)[0]; //added [0] since it is just one row
//var lastPatientID = sheet.getRange(numRows,3).getValue(); //you already have this in memory
var lastPatientID = last_row[2]; //arrays are zero based, that's why 2 instead of 3
//btw, you mention column V, but this is actually C
//var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
//you already have the spreadsheet, no need to get it again
var patientSheet = spreadsheet.getSheetByName(lastPatientID);
//var activePatientSheet = spreadsheet.getSheetByName(lastPatientID); //this is the exact same as above, why?
patientSheet.appendRow(last_row); //appendRow is just simpler than getRange(getLastRow).setValues
}
If I want my Google Apps Script app get the current selected row in a spreadsheet, I use something like this:
function getCurrentRow() {
var currentRow = SpreadsheetApp.getActiveSheet().getActiveSelection().getRowIndex();
return currentRow;
}
But what if I want to get the first cell in this row (to put a comment in it), how do I proceed?
You can use offset to get a range relative to the active range.
function getFirstCellInRow() {
var sheet = SpreadsheetApp.getActiveSheet();
var activeCell = sheet.getActiveCell();
var firstCell = activeCell.offset(0, 1-activeCell.getColumn());
return firstCell;
}
Or just use getRange(A1notation), starting with what you had:
function getFirstCellInRow2() {
var sheet = SpreadsheetApp.getActiveSheet();
var currentRow = sheet.getActiveSelection().getRowIndex();
return sheet.getRange("A"+currentRow);
}
To write into the first cell in the row:
getFirstCellInRow().setValue('Tada');
There is a getCell() method you can use ( https://developers.google.com/apps-script/reference/spreadsheet/range#getCell(Integer,Integer) )
function getFirstCell() {
var firstCell= SpreadsheetApp.getActiveSheet().getActiveSelection().getCell(1,1);
return firstCell;
}
The following script will insert "My Info" in the first row available in column A.
function FirstCellColumnA() {
// replace with destination ID
var s = SpreadsheetApp.openById('spreadsheetID');
// replace with destination Sheet tab name
var ss = s.getSheetByName('sheetname');
// In Column A first ROW Available ss.getLastRow()+1 = find the
// first row available, 1 = start in column 1, 1 = rows to start,
// 1 = column where to put the data.
ss.getRange(ss.getLastRow() + 1, 1, 1, 1).setValue('My Info');
}
I hope this help you.
In Google Spreadsheet I would like to take only the values from a complete list on one spreadsheet and append it to the bottom of a list on another spreadsheet. My trouble is that using the the copyValuesToRange() function errors the following:
Target sheet and source range must be on the same spreadsheet.
Here's my current code:
function transferList() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("0ABCD");
var target_sheet = target.getSheetByName("RFPData");
var sheet = source.getSheetByName("RFP List");
var sheet_last_row = sheet.getLastRow() + 1;
var source_range = sheet.getRange("A2:I"+sheet_last_row);
var sWidth=source_range.getWidth() + 1;
var sHeight=source_range.getHeight() + 1;
var last_row=target_sheet.getLastRow();
source_range.copyValuesToRange(target_sheet , 1, sWidth,
last_row + 1, last_row + sHeight );
}
Any idea how I can get this to work?
As you've found, copyValuesToRange() is a Range method that affects a Sheet Object that is in the same Spreadsheet Object as the Range. There isn't an atomic method that will copy a range of values to another Spreadsheet, but there are a number of ways you could do it.
Here's one way.
From the source sheet, get all the data in one operation, by selecting the complete range of data using getDataRange() and then grabbing all values into a javascript array with getValues().
To ignore the first row of headers, use the javascript array method splice().
Locate your destination, which is on the target sheet, starting after the last row of data that's currently there, using getLastRow().
Write the source data (without the headers) to the destination sheet starting at the next row, using setValues().
Script:
function transferList() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("RFP List");
var sourceData = sourceSheet.getDataRange().getValues();
sourceData.splice(0,1); // Remove header
var targetSS = SpreadsheetApp.openById("0ABCD").getSheetByName("RFPData");
var targetRangeTop = targetSS.getLastRow(); // Get # rows currently in target
targetSS.getRange(targetRangeTop+1,1,sourceData.length,sourceData[0].length).setValues(sourceData);
}
For some historic dashboard I created by importing and appending data, I use an add-on called Sheetgo. Save me programing time and help me with traceability issues.