How to copy data *to the left* of a checked box using Apps Script? - checkbox

enter image description here
So I have a sheet of names, alternating with a column of checkboxes. I want to be able to click on a box, and then have the name of the left of the checkbox be copied onto a separate sheet. I found some code that could copy data from an entire row, but my issue is that I have rows that alternate with the checkboxes, and if I check one box I only want the name to the left, not the whole row.
function onEdit(event) {
// assumes source data in sheet named main
// target sheet of move to named Completed
// getColumn with check-boxes is currently set to column 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Grid" && r.getColumn() == 3 && r.getValue() == true) {
//Parameters for checked boxes
var targetSheet = ss.getSheetByName("Absences");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange( 1, 1).offset( 0, -1).copyTo(target);
}
}

Related

Apps Script to Create TXT Files Based on Data in Rows

I am working through the following script which reads the data in certain rows and columns (from Cell A29 to Cell K150) and produces txt files based on data in Columns A and B. That is, if columns A and B have same items, only 1 file is produced with all data in those rows. The only problem is that the script also reads the blank rows/columns and creates a blank txt file. How can I modify the script to exclude blank rows (For example, data is in rows 29 - 100, I want the script to exclude remaining 50 rows and NOT create any files for blank rows)?
function CreateUploadFiles() {
// Retrieve values from Spreadsheet.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Summary"); //Set your sheet name.
var [, ...values] = sheet.getRange(28, 1, 150, 11).getValues();
// Create an array.
var csvBalanceArray = [...values.reduce((m, [h1, h2, ...r]) => {
var h = h1 + h2;
var temp = r.map(e => e instanceof Date ? Utilities.formatDate(e, Session.getScriptTimeZone(), "d/MM/yyyy") : e);
var name = `${h1} ${h2}`;
if (h2 == "Balance") {temp = temp.slice(0,3)}
return m.set(h, m.has(h) ? { rows: [...m.get(h).rows, temp], name } : { rows: [temp], name });
}, new Map()).values()];
console.log(csvBalanceArray)
//strip out new lines with space
// Create text files.
// var folder = DriveApp.getFolderById('J3'); // Set your folder ID.
var ss = SpreadsheetApp.getActive(); //Extracting Folder ID from Cell
var folder = ss.getRange("Summary!J3").getValue();
var destinationFolder = DriveApp.getFolderById(folder)
var files = destinationFolder.getFiles();
var GL = sheet.getRange("B2").getValue()
var period = sheet.getRange("B3").getValue()
var FY = sheet.getRange("B4").getValue()
//while (files.hasNext()) files.next().setTrashed(false); //For deleting files already created in your folder
csvBalanceArray.forEach(({ rows, name }) => destinationFolder.createFile(`P${period} FY${FY} ${GL} ${name}.txt`,
rows.map(r => r.join("***") //Join all columns to string value for each row
// replace remove all tab from new lines
.replaceAll("\t"," ").replaceAll("\n"," ").replaceAll("***","\t")).join("\n")));
}

Apps Script: Move SELECTED rows from one sheet to the last available rows of another sheet

The code below is from here and was originally written by user #Cooper. All it does is that it copies the values of the columns specified in the array colA = [1,3,2,4] from SHEET 1 and add them to SHEET 2. I want to re-write the 2 last lines of the code, so that the values coming from SHEET 1 are added to the last available rows in SHEET 2. By "2 last lines", I mean these last lines of the code:
drng = des.getRange(1,1,drngA.length,drngA[0].length);//destination array controls size of destination range.drng.setValues(drngA);
Any idea how to get this done?
Thank you so much in advance for your help!
function Copy_data()
{
var src = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SHEET 1");
var des = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SHEET 2");
var srng = src.getDataRange();
var srngA = srng.getValues();
var drngA = [];
var colA = [1,3,2,4];//indirect data column selection
for (var i = 0; i < srngA.length;i++ )
{
var k = 0;
drngA[i]=[];
for(var j=0;j<srngA[i].length;j++)
{
drngA[i][k++] = srngA[i][colA[j]-1];
}
drng = des.getRange(1,1,drngA.length,drngA[0].length);//destination array controls size of destination range.
drng.setValues(drngA);
}
}
You can get the last row of the destination Sheet and after, add it to your getRange() function. The method proposed by #soMario will not work because it makes requests inside the loop while you update the Sheet, and this causes it to get different values every time you call des.getLastRow().
The simplest solution is to take the getLastRow() request outside of the loop and then include it in getRange. Note that one is added to it so that it does not overwrite the last row with the setValue() request.
Code.gs
function Copy_data() {
...
var lastRow = des.getLastRow() + 1
for (var i = 0; i < srngA.length;i++ ){
...
drng = des.getRange(lastRow,1,drngA.length,drngA[0].length)
...
}
Documentation
getRange(row, column, numRows, numColumns)
getLastRow()

get the cell containing a specific data in appscript

I'm trying to set a follow up of unpaid invoices.
For that I'd like to find a way to get to the cell of a specified invoice number.
For example, I need to go the cell containing 6126944 in the column H in the sheet follow up
This number will always be typed in the cell D16, of the sheet "first call".
Is there any way to do that, I'm quite new on appscript
If you need just to jump to the next sheet cell (column H) that contains the same number as the cell D16 -- here is the way:
function jump_to_cell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet_first_call = ss.getSheetByName('First call');
var sheet_follow_up = ss.getSheetByName('Follow up');
var num = sheet_first_call.getRange('D16').getValue();
var nums = sheet_follow_up.getRange('H:H').getValues().flat().filter(String);
for (var row in nums) {
if (nums[row] == num) {
sheet_follow_up.getRange('H'+(row+1)).activate();
break;
}
}
}

Pasting values in a different column depending on a Data Validation drop-down selection

Suppose I have the following setting on a Google Sheet:
Column A containing a list of different items (Apple/Melon/Grapes), column B containing Data Validation drop-down menus with either option 1 or 2.
What I want is that if I select option 1 for any of the items, the value of the corresponding cell in column A is going to pasted in D2. If I select option 1 for another item, the value will be pasted in D3, and so forth, thus building a secondary list without leaving any blank cells in between. If I select option 2, the item should be ignored.
Ideally, the order of the items in column D would follow my actions chronologically, i.e. if the item in A3 is the first item I select option 1 for, then it shall be on the top of the column D list at all times, even if later on I select option 1 for A1 as well (which shall then sit on the second position of the D list).
Is it possible to be achieved?
You can do this via Apps Script with a simple onEdit trigger, using its event object.
Select Tools > Script editor to open the Apps Script editor.
Copy this function and save the project (check inline comments):
function onEdit(e) {
// Get the range that was edited (column, row, sheet, value):
var range = e.range;
var sheet = range.getSheet();
var col = range.getColumn();
var row = range.getRow();
var value = range.getValue();
var sheetName = "Sheet1"; // Name of your sheet (the tab) (please change if necessary)
// Check that edited column is B, edited value is 1, and edited sheet is "Sheet1":
if (sheet.getName() === sheetName && col === 2 && value === 1) {
// Get length of non-empty cells in column D:
var columnD = sheet.getRange("D:D").getValues().map(function(item) {
return item[0];
}).filter(function(item) {
return item !== "";
});
var firstEmptyRow = columnD.length + 1; // First empty row in column D
var itemToCopy = sheet.getRange(row, 1).getValue(); // Get value from column A to copy
sheet.getRange(firstEmptyRow, 4).setValue(itemToCopy); // Write value to column D
}
}
Now, every time you edit column B and the edited value is 1, the corresponding option from column A will get copied to column D.
Reference:
onEdit
Event objects: Edit
delete range D2:D and paste in D2 cell:
=FILTER(A:A; B:B=1)

Pulling scattered data from changing spreadsheet

I'm trying to write a script which has multiple parts. The current part (function copyOver) supposed to open a spreadsheet (by ID), extract specific data from it and insert it into a Master spreadsheet.
The part I'm stuck with is that the spreadsheet changes daily. Some days there are cells containing data of "Sea Water", other days there aren't any. Ideally, I was trying to write a script which loops through the sheet looking for the specific tab names in cells (for example: Sea water, chlorine content...) and extract the data from the row below, up until the second tab and so on. I would only need very specific data, like data from "C6", "E6", "F10", but these cells are always changing so I have to look for them by using the tab names in cells above them. There would be multiple arrays for each tab and the data coming with it.
Would that be possible to extract data this way and put them into an array containing the tab value as the header or title and the data connected to that specific tab.
var sourceID = "source sheet ID";
var main = SpreadsheetApp.openById("master sheet ID"); // MASTER
var source = SpreadsheetApp.openById(sourceID); //the workbook you're copying from
var mainsheet = main.getSheetByName("Lab Data"); // the sheet you want to copy the stuff into
var sourcesheet = source.getSheetByName("ANALYSIS REPORT"); // the sheet you're copying from
var dataRange = sourcesheet.getDataRange().getValues(); // gets sheet as data range
// finds SEA WATER tab in cell and gets the range below until the end of the document
// this is the range I need to find the rest of the tabs and the data under them.
var cont = "SEA WATER";
var i = [];
for (var y = 0; y < dataValues.length; y++){
if(dataValues[y] == cont){
i.push(y);
} // end if
} // end for
Logger.log(i);
var Row = Number(i)+Number(dataRange.getRow()); // gets the row number of SEA WATER tab
Logger.log("row number: " + Row);
var swLast = sourcesheet.getLastRow();
var swRange = sourcesheet.getRange(Row,2,swLast,11);
var swValues = swRange.getValues(); // range of needed information
Logger.log("sw: " + swValues);
var con2 = "SW outlet SW from Coarse filtration"; // looking for the secondary tab, within the
range
I got from the first loop
var res2 = [];
for(var i2 = 0; i2 < swValues.length; i2++) {
if(swValues[i2][4] === con2) res2.push(data[i2])
var row2 = Number(i2)+Number(swRange.getRow());
Logger.log("row2 " + row2);
} // for end
var look1 = "SW outlet SW from Coarse filtration ";
for(var i1 = 0; i1<dataRange.length;i1++){
if(dataRange[i1][1] == look1){
return i1+1;
}
}
Logger.log((i1+1));
} // end of function
EDIT: Here's a link to a sheet. Required data starts from row 237, until row 268 - but this can change every day. (Deleted the information for privacy reasons.)
Basically, I need all the cells with "x" in them, preferably together with the title cells above them, so I'll know what data it is.
The following code loops through your headers in column B and finds the row in which your header of interest is located
Subsequently, it copies the data starting from this row to the last data row into the sheet "Lab Data":
function myFunction() {
var sourceID = "source sheet ID";
var main = SpreadsheetApp.openById("sourceID"); // MASTER
var source = SpreadsheetApp.openById(sourceID); //the workbook you're copying from
var mainsheet = main.getSheetByName("Lab Data"); // the sheet you want to copy the stuff into
var sourcesheet = source.getSheetByName("ANALYSIS REPORT"); // the sheet you're copying from
var dataRange = sourcesheet.getDataRange()
var dataValues=dataRange.getValues(); // gets sheet as data range
for (var a = 0; a < dataValues.length; a++){
if(dataValues[a][1]=="SEA WATER"){
var Row=a+1;
break;
}
}
if(Row){
var swLast = sourcesheet.getLastRow();
var swRange = sourcesheet.getRange(Row,2,swLast,11);
swRange.copyTo(mainsheet.getRange(mainsheet.getLastRow()+1, 2));
}
} // end of function
I hope this helps to solve your issue.

Resources