How to use 'GetSheetByName' with a macro in Google Sheets? - google-apps-script

I'm trying to set up a macro to run once a month to collect current figures from a set of formulas, but I'm struggling to get it to select the right sheet before running the copy and paste commands.
function RecordCurrentFigures() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getSheetByName('Current Figures');
spreadsheet.getRange('9:9').activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange('B9').activate();
spreadsheet.getRange('B5:F5').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
spreadsheet.getRange('B5:F5').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
};

I think the issue is that you are calling it but you're not using it afterwards, you are using getActiveSheet and getActiveRange instead.
Try:
function RecordCurrentFigures() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('Current Figures');
var range = sheet.getRange('9:9')
sheet.insertRowsBefore(range.getRow(), 1);
// range.offset(0, 0, 1, range.getNumColumns()); // this is a NOP
var range2 = sheet.getRange('B9');
sheet.getRange('B5:F5').copyTo(range2, SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
sheet.getRange('B5:F5').copyTo(range2, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}

Related

Google script to copy and paste

I'm trying to work out if it's possible to write a script that will copy and paste special all the values in a tab with the same name across multiple workbooks in a file?
This is what I have so far but I just can't seem to get it to work properly? Any help would be most appreciated.
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Copy and Paste')
.addItem('Copy and paste sheet with new name', 'copyAndPasteSheetWithNewName')
.addToUi();
}
function copyAndPasteSheetWithNewName() {
var sheetName = Browser.inputBox('Enter the name of the sheet to copy and paste:');
var folder = DriveApp.getFileById(SpreadsheetApp.getActive().getId()).getParents().next();
var files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
var file = files.next();
var workbook = SpreadsheetApp.open(file);
var sheet = workbook.getSheetByName(sheetName);
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
}
}
From your following reply,
What I'm trying to do is just have the final part of the script hard code the worksheet. It's full of formulas and I want the results of those formulas not the formulas themselves.
In this case, how about the following modification?
From:
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
To:
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
range.copyTo(range, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false); // or range.copyTo(range, {contentsOnly: true});
By this modification, the last row of each sheet is converted to only the values without the formulas.

How do I fix this Macro to CONCATENATE and then paste values of two columns

I'm trying to write a macro in gsheets that will concatenate two columns and then copy the values back over to the first column. But everything I try the copy to column just gets blanked out.
function CopyandPasteValues() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('H2').activate();
spreadsheet.getCurrentCell().setFormula('=CONCATENATE(E2,"",G2)');
spreadsheet.getActiveRange().autoFill(spreadsheet.getRange('H2:H249'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getRange('H2:H249').activate();
spreadsheet.getRange('E2').activate();
spreadsheet.getRange('H2:H249').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
SpreadsheetApp.flush();
};
If you only need the values, try the the following:
function CopyandPasteValues() {
var spreadsheet = SpreadsheetApp.getActive();
var values = spreadsheet.getRange('E2:G249').getDisplayValues();
var output = values.map(row => row[0] + row[2]);
spreadsheet.getRange('H2:H249').setValues(output);
};

Copy in new row every time run app script in google sheets

I try to create script to copy one specific row from one sheet to another sheet in new row.
But the script allways copy replace the last one.
I use this code:
function Test() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A9:O9').activate();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Logs'), true);
spreadsheet.getRange('A24').activate();
spreadsheet.getRange('Log!A9:O9').copyTo(spreadsheet.getActiveRange(),
spreadsheetApp.CopyPasteType.PASTE_VALUES, false);
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Log'), true);
spreadsheet.getRange('D9:O9').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
Your script always copies the data to the activated range - which is always A24
Rewrite your funciton by specifying to where you want to copy your row. If you do not want to overwrite, probably you want to append your row at the bottom of the destination sheet.
You can do it as following:
function Test() {
var spreadsheet = SpreadsheetApp.getActive();
var originSheet = spreadsheet.getSheetByName("Log");
var destSheet = spreadsheet.getSheetByName("Logs");
var rowContents = originSheet.getRange('A9:O9').getValues().flat();
destSheet.appendRow(rowContents);
};
Alternatively, you can copy the data to the first empty row:
function Test() {
var spreadsheet = SpreadsheetApp.getActive();
var originSheet = spreadsheet.getSheetByName("Log");
var destSheet = spreadsheet.getSheetByName("Logs");
var firstEmtyRow = destSheet.getLastRow() + 1;
var destRange = destSheet.getRange('A' + firstEmtyRow + ':O' + firstEmtyRow);
originSheet.getRange('A9:O9').copyTo(destRange,
spreadsheetApp.CopyPasteType.PASTE_VALUES, false);
};
References:
getSheetByName()
appendRow()
flat()
getLastRow()
As pointed out by #Mike Steelson, activating sheets and ranges is not good practice. It is performed in the background if you record a macro, but it is prone to errors, so if you write a script yourself - avoid activate().

Auto Sort Data Moved by Script

My issue is, I have data being moved from one Sheet to another via script when marked "Complete". In the "Completed" sheet is where I want to sort the data. I already have an Autosort script that works only when debugging, not even on edit (tried editing everywhere), Let alone when data is moved to the sheet.
I want to be able to Auto sort whenever data is moved to the new sheet (I don't think its an onEdit function?)
I am not a programmer and I'm fairly new to Google Apps Script. I just dabble into code once in a while because I find it interesting, so I don't even know where to start to get the results I'm looking for.
This is the Auto Sort,
function AutoSortOnEdit() {
var sheetNames = ["Complete"];
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheetNames.forEach(function(name) {
var sheet = ss.getSheetByName(name);
var range = sheet.getRange(4, 1, sheet.getLastRow() - 1,
sheet.getLastColumn());
range.sort({column: 2, ascending: true});
});
}
EDIT: I realized I was using a script for multiple sheets. I changed it for one sheet, same issues though.
function AutoSortOnEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Completed Returns");
var range = sheet.getRange(4, 1, sheet.getLastRow() - 1,
sheet.getLastColumn());
range.sort({column: 2, ascending: true});
}
Any help would be greatly appreciated!
I managed to get it working by throwing the 2 scripts together under 1 function like so. I could not figure out how to get the event function to run while calling multiple functions, so I just combined them. Above the 2 "}" brackets is the move Script and below them is the Auto sort.
function onEdit(e) {
var ss = e.source;
var s = ss.getActiveSheet();
var r = e.range;
var actionCol = 24;
var nameCol = 24;
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
var colNumber = s.getLastColumn();
if (e.value == "TRUE" && colIndex == actionCol) {
var targetSheet = ss.getSheetByName("Completed Returns");
if (ss.getSheetByName("Completed Returns")) {
var targetSheet = ss.getSheetByName("Completed Returns");
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
s.deleteRow(rowIndex);
}
}
var sheet = ss.getSheetByName("Completed Returns");
var range = sheet.getRange(4, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
range.sort({column: 2, ascending: true});
}
Thanks Everyone for the response!
You can add your function to one another
function AutoSortOnEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Completed Returns');
var range = sheet.getRange(
4,
1,
sheet.getLastRow() - 1,
sheet.getLastColumn()
);
range.sort({ column: 2, ascending: true });
}
function copyData() {}
function userActionRun() {
copyData();
AutoSortOnEdit();
}
At now you can bind it ti EDIT event
function onEdit(){
userActionRun();
}
You can use the Sort function to sort a data-set.
If you have a function that moves data form one sheet to another when the row is marked as complete, then you can add a line at the end of that to sort it.
You could also create a FilterView that sorts the whole sheet based on your parameters. Unlike Filters, FilterViews are saved between sessions.

Google Apps Script Find bottom of column

I need some assistance with Google Apps Script. I am working in google sheets and currently have the following script:
function transpose() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('C3:N3').activate();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet21'), true);
spreadsheet.getRange("'A/P'!C3:N3").copyTo(spreadsheet.getActiveRange(),
SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true);
};
Rather than just paste in A1 of Sheet 21, I would like it to find the bottom of column F. I am also wondering how to copy data from whichever sheet I am in, not just the sheet named A/P.
Thank you in advance!
You want to add the values of C3:N3 in the active sheet to the next row of last row on column F in Sheet21. If my understanding is correct, how about this modification?
Modification points :
In your script, if the active sheet is not Sheet21, the active range becomes "A1", because spreadsheet.getRange('C3:N3').activate() at other sheet is changed by spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet21'), true). By this, the values of "'A/P'!C3:N3" are copied for "A1" of Sheet21.
Flow of modified script:
Retrieve the range of source (Active sheet)
Retrieve the destination (Sheet21) sheet.
Retrieve the destination range.
Copy
Modified script : Pattern 1
If the address of last row of column "F" in "Sheet21" is smaller than that of other columns, please use this.
function transpose() {
var spreadsheet = SpreadsheetApp.getActive();
var srcRange = spreadsheet.getActiveSheet().getRange('C3:N3');
var dstSheet = spreadsheet.getSheetByName('Sheet21');
var range = dstSheet.getRange('F1:F');
var values = range.getValues();
var formulas = range.getFormulas();
var i;
for (i = values.length - 1; i >= 0; i--) {
if (values[i][0] != "" || formulas[i][0] != "") break;
}
var dstRange = dstSheet.getRange("F" + (i + 2));
srcRange.copyTo(dstRange, SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true);
};
Modified script : Pattern 2
If the address of last row of column "F" in "Sheet21" is larger or the same with that of other columns, please use this.
function transpose() {
var spreadsheet = SpreadsheetApp.getActive();
var srcRange = spreadsheet.getActiveSheet().getRange('C3:N3');
var dstSheet = spreadsheet.getSheetByName('Sheet21');
var dstRange = dstSheet.getRange("F" + (dstSheet.getLastRow() + 1));
srcRange.copyTo(dstRange, SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true);
};
If I misunderstand your question, please tell me. I would like to modify it.