I need some help building a simple script that should do the following:
Source spreadsheet
Check if Col C on sheet source equals "Done"
If yes, copy and paste the rows from Col A and Col B that meet the criteria to the first empty row on sheet history + a timestamp of the copy paste
Plus copy and paste the same values from Col A and B on spreadsheet Destination, first empty row on tab destination + a timestamp of the copy paste
Finally delete the copied rows from the first sheet source so there are no empty rows
If not, leave the values be
Overall the goal is to CUT the values that meet the criteria and paste them on a different sheet and on a different spreadsheet at the same time.
Here you go:
function main() {
// get 'Done' rows from sheet 'source' and remove these rows
var data = get_done();
// put the rows on the sheet 'history' (same spreadsheet)
copy_to_history(data);
// pyt the rows on the sheet 'destination' (another spreadsheet)
copy_to_destination(data);
}
function get_done() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('source');
var data = sh.getDataRange().getValues();
var keep = data.filter(x => x[2] != 'Done');
sh.clearContents().getRange(1,1,keep.length,keep[0].length).setValues(keep);
var timestamp = new Date();
var done = data.filter(x => x[2] == 'Done').map(x => [timestamp, x[0], x[1]]);
return done;
}
function copy_to_history(data) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('history');
data.forEach(row => sh.appendRow(row));
}
function copy_to_destination(data) {
var ss = SpreadsheetApp.openById('1niihiUXZii1gNnifn2ZLNf4JnvLs887mJMp53OcIphA');
var sh = ss.getSheetByName('destination');
data.forEach(row => sh.appendRow(row));
}
The main shortcoming of the script: it doesn't keep formulas and formatting.
Related
first I'm not good in coding just trying figure my way and make what i need.
so my function is to copy data from sheet to sheet and delete the data after finishing.
my issue is small but can't find a solution for it, it's when I'm copying it copy just 12 rows, but for me i want it to copy as much rows will be.
my final code i want it to copy the rows that have a specific word, but for now I'm searching for a solution for this issue.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var pasteSheet = ss.getSheetByName("Sheet2");
// get source range
var range = copySheet.getRange(2,1,12,4);
var source = range.getValues();
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,12,4).setValues(source);
range.clearContent();
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,12,1);
// clear source values
Browser.msgBox('Commande Confirmer');
}```
this is my code
thanks in advance
Description
In this example, the script gets all values from Sheet1, not just 12 rows. It then uses the Array.filter() to get all rows that have the word "Hello" in Column A. Not knowing how many rows match the filter I use source.length to tell getRange() how many rows to output.
Code.gs
function test() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var pasteSheet = ss.getSheetByName("Sheet2");
// get source range
var range = copySheet.getDataRange(); // Get all values
var source = range.getValues();
source = source.filter( row => row[0] === "Hello" );
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,source.length,source[0].length).setValues(source);
// clear source values
range.clearContent();
Browser.msgBox('Commande Confirmer');
}
catch(err) {
console.log(err);
}
}
Reference
Sheet.getDataRange()
Array.filter()
I have a formula in worksheet 'Price History' cell E21 that changes to different worksheet names automatically depending on what other cells are equaling too. The script I have is returning TypeError: newSheetName.getRange is not a function. In the below script i tried to copy a blank cell above E21 and paste the cell into a blank cell on the specified worksheet but that didn't help. I am trying to only activate the worksheet of which the value is in E21. Thank you
function MyAccount() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Price History");
var newSheetName = sheet.getRange("E21").getValue();
sheet.getRange("E20").copyTo(newSheetName.getRange("C1"), { contentsOnly: true });
}
This line var newSheetName = sheet.getRange("E21").getValue(); doesn't set the variable newSheetName as a sheet but a string value.
SUGGESTION:
Since you have mentioned that the value of cell E21 basically contains worksheet name that is randomly changing, perhaps you can still try using getRangeByName(name) method as this will return the sheet with the given name & then you can get the range of that sheet. See this sample tweaked script below:
UPDATED
function MyAccount() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Price History");
var newSheetName = ss.getSheetByName(sheet.getRange("E21").getValue());
var Direction=SpreadsheetApp.Direction;
var lastRowOfC = ss.getRange("C"+(ss.getLastRow()+1)).getNextDataCell(Direction.UP).getRow() + 1; //Get the last row of column C on any worksheet
sheet.getRange("E20").copyTo(newSheetName.getRange(lastRowOfC,3), { contentsOnly: true });
}
Getting the last row script was derived from one of the answers from Determining the last row in a single column (Getting last row on a column that contains empty gaps)
Sample test on my end:
NOTE: It would also be better if you could share a sample sheet that you're using in case I have misunderstood your setup.
UPDATED
After running the script, the test cell value was copied to the destination sheet called NewTestSheet on the last row of column C, which is C4
You are trying to use a String value as a Sheet. Instead, use the sheet name to get a new sheet, then copy to the new range.
function MyAccount() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Price History");
var copyRange = sheet.getRange("E20");
var nameRange = sheet.getRange("E21");
copyRange.copyTo(ss.getSheetByName(nameRange.getValue()).getRange("C1"), { contentsOnly: true });
}
Or,
function MyAccount() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Price History");
var copyValue = sheet.getRange("E20").getValue();
var nameRange = sheet.getRange("E21");
ss.getSheetByName(nameRange.getValue()).getRange("C1").setValue(copyValue);
}
I need to pull/import data from "sheet 1" to "sheet 2" based on column 4 being a specific text string. The script should not pull lines that already exist.
I have no idea if this is possible. I can pull the data but it just recopies everything so I have duplicates.
Any help would be super appreciated.
function onEdit() {
var ss = SpreadsheetApp.openById('1Ognzsi6C0DU_ZyDLuct58f5U16sshhBpBoQ8Snk8bhc');
var sheet = ss.getSheetByName('Sheet 1');
var testrange = sheet.getRange('D:D');
var testvalue = (testrange.getValues());
var sss = SpreadsheetApp.getActive();
var csh = sss.getSheetByName('Sheet 1');
var data = [];
var j =[];
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] == 'Dan') {
data.push.apply(data,sheet.getRange(i+1,1,1,11).getValues());
j.push(i);
}
}
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
Sheet 1
Sheet 2
Solution
You should be able to replace your code with this and it will work. You would put this script in the target sheet (Sheet 2), and replace the ID in the first line of the function with the origin (Sheet 1).
I'll leave it up to you to change to an onEdit or to make it a menu item. Right now it can be run from the script editor. onEdit doesn't make sense to me as an appropriate trigger. Maybe you prefer a Time-Driven Trigger. Though a custom menu would be the best way IMO.
function pullData() {
var sourceSs = SpreadsheetApp.openById('[YOUR_SPREADSHEET_ID]');
var sourceRange = sourceSs.getSheetByName('Sheet1').getDataRange();
var sourceHeight = sourceRange.getHeight();
var sourceWidth = sourceRange.getWidth();
var sourceData = sourceSs.getSheetByName('Sheet1').getRange(2, 1, sourceHeight - 1, sourceWidth).getValues();
var targetSs = SpreadsheetApp.getActive();
var targetRange = targetSs.getSheetByName('Sheet1').getDataRange();
var targetHeight = targetRange.getHeight();
var targetWidth = targetRange.getWidth();
var sourceDataChecker = [];
var targetDataChecker = [];
sourceData.forEach((row) => {
sourceDataChecker.push(row[0] + row[1] + row[2] + row[3]);
})
if (targetHeight != 1) {
var targetData = sourceSs.getSheetByName('Sheet1').getRange(2, 1, targetHeight - 1, targetWidth).getValues();
targetData.forEach((row) => {
targetDataChecker.push(row[0] + row[1] + row[2] + row[3]);
});
};
sourceData.forEach((row, i) => {
if (!(targetDataChecker.includes(sourceDataChecker[i]))) {
targetSs.appendRow(row);
};
});
}
Explanation
This script builds an "index" of each row in both sheets by concatenating all the values in the row. I did this because I noticed that sometimes you have "joe" in two rows, and so, you can't simply use column 4 as your index. You are basically checking for any row that is different from one in the target sheet (Sheet 2).
If the target sheet is blank, then all rows are copied.
References
Append Row to end of sheet
Get Data Range (range of sheet that contains data)
Get Range Height (to deal with headers)
Get Range Width
for Each
I am using the following script to import data from another Google Sheet but it doesn´t bring in the formula I need with it.
I have tried ImportRange but that seems to just sync the two sheets and I need to delete the data in the original sheet (Sheet 1) but that also deletes it in the sheet I bought in to (Master Sheet).
Is there another way to accomplish this?
function Copy() {
var sss = SpreadsheetApp.openById('Sheet 1 ID');
var ss = sss.getSheetByName('results');
var range = ss.getRange('2:688');
var data = range.getValues();
var tss = SpreadsheetApp.openById('Master Sheet ID');
var ts = tss.getSheetByName('results');
ts.getRange(ts.getLastRow() + 1, 1, data.length, data[0].length).setValues(
data
);
var sheet = SpreadsheetApp.openById('Sheet 1 ID').getSheetByName('Roger');
ss.getRange('2:688').clearContent();
}
Issue:
Formulas are not retrieved with getValues()
Possible Solutions:
Use range#getFormulas and range#getValues and mix those two arrays to create a array of formulas and values to setValues() later.
Use Advanced Google Services to access Sheets API to directly get the mix.
Sample Script Snippets:
var data = range.getValues();
data = range.getFormulas().map(function(e, i) {//i=index of row(e)
return e.map(function(f, j) {//j = index of column(f)
return f === "" ? data[i][j] : f;
});
});
or
var req = {
ranges: 'results!2:688',
valueRenderOption: 'FORMULA', //get formulas with values
};
var r = Sheets.Spreadsheets.Values.batchGet('Sheet 1 ID', req);
data = r.valueRanges[0].values;
References:
getFormulas
EnablingAdvancedServices
batchGet
I iterate through the rows and get the value of a certain cell like so:
for (var i = 2; i < lastRow; i++) {
if (sheet.getRange(i, getColIndexByName("Department Concerned")).getValue() == "HR") {
// Do some stuff
}
}
I copy data to another sheet like so:
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
var target_range = target_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// set the values to the destination sheet
target_range.setValues(values);
What I need is to copy that data and add it to the same range of the other Spreadsheet depending on the cell value that I just took in my "for loop".
Thank you.
What you think was right, but need to find better approach.
Select values from source sheet
Check each rows, column Department Concerned for "HR" value
Select rows that fulfill above condition
Paste it in target sheet
I combined those scenarios as this,
function myFunction()
{
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// an array for selected rows
var selectedRows = [];
for(var row in values)
{
// thinking 5th column is Department Concerned
if(values[row][4] =='HR')
{
//add add entire row to selected 2d array
selectedRows.push(values[row]);
}
}
// set the values to the destination sheet
target_sheet.getRange(2, 1, selectedRows.length,10).setValues(selectedRows);
}