So I'm trying to figure out a way where if the two cells match in numbers, the dropdown list item changes to "stopp".
See the example here: Example
What I want it to do is when the column G has the same number as the column H, it changes the status to "Stopp".
Could someone help?
Unfortunately, this is not possible to do directly in Google Sheets, you would need to incorporate some Apps Script to extend Google Sheets.
With Apps Script, you could simply create a function to check and update the values, or you could do it automatically with triggers. Specifically, the most useful trigger in this situation would be the onEdit() trigger (you can read more about it here), since it would run automatically every time that the document is edited.
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var column1Index = 7; //LETTER G
var column2Index = 8; //LETTER H
var outputColumnIndex = 9; //LETTER I
var numberOfRowsToCheck = 10;
var column1Values = sheet.getRange(1,column1Index,numberOfRowsToCheck,1).getValues();
var column2Values = sheet.getRange(1,column2Index,numberOfRowsToCheck,1).getValues();
for (var i=0;i<column1Values.length;i++){
if(column1Values[i][0] == column2Values[i][0]){
sheet.getRange(i+1, outputColumnIndex).setValue("Stop");
}
}
}
Related
I'm a relative newbie to using Apps Script, though I'm decent with non-Macro automation in Google sheets. I am not familiar with Javascript, though I had a class on Python back in college. What I am currently aiming to do (but am unable to figure out) is how to write a macro that deletes a cell and the cell to the immediate right if the left cell has a value of 0. (Eg. a7 is 0; both a7 and b7 should be deleted with the cells below getting shifted up). Just to throw another wrench into the mix, I have 4 separate column pairs like this (a&b, d&e, g&h, j&k), where the left value is how much is needed and the right cell is for what item needs that quantity. I've shoe-strung together some others' code (including Cooper, who was nice enough to comment on the original question) and added a couple thoughts, but I think I'm missing something and am not catching it due to my unfamiliarity with Script. Here's the code in question:
function print() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var sheet = source.getSheetByName('Temp');
sheet.copyTo(source).setName('Gathering')
activateSheetByName('Gathering') //Activates the created sheet
clearNotOrdered //deletes any item that wasn't ordered
Browser.msgBox('Ready to Print!') //just for kicks and giggles
}
function clearNotOrdered(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var limit = sheet.getLastRow(); //number of rows in the sheet
var prep = sheet.getRange(7, 1, limit-13).getValues(); //Prep list
var kitchen = sheet.getRange(7,4,limit-11).getValues(); //Kitchen's list
var breading = sheet.getRange(7,7,limit-26).getValues(); //Breader's list
var gatherer = sheet.getRange(7,10).getValues(); //Catering Person's list
for(var i = 7;i <= limit;i++){//loop for each value to be inserted in each row of the target sheet
if(prep==0){
delAdjacentShiftUp() }
if(kitchen == 0){
delAdjacentShiftUp() }
if(breading==0){
delAdjacentShiftUp() }
if(gatherer==0){
delAdjacentShiftUp() }
}
}
function activateSheetByName(sheetName) {
var sheet =
SpreadsheetApp.getActive().getSheetByName(sheetName);
sheet.activate();
}
function delAdjacentShiftUp() {SpreadsheetApp.getActiveSheet().getActiveCell().offset(0,0,1,2).deleteCells(SpreadsheetApp.Dimension.ROWS);
}
The code isn't currently giving me any error messages, but it's also not removing the data. Do I just need to run 4 separate "For" commands instead of trying to run them all together?
Try this:
function delAdjacentShiftUp() {
SpreadsheetApp.getActiveSheet().getActiveCell().offset(0,0,1,2).deleteCells(SpreadsheetApp.Dimension.ROWS);
}
Demo:
I am a wanna-be developer who is trying to figure out how to hide a set of columns based off a checkbox being clicked.
Would anyone want to help with this code?
I have 12 different sheets(one for each month) and I would like to hide columns A-H with the checkbox in I being clicked.
Ideally I can implement on each individual sheet.
Link to spreadsheet
There are few ways one can do it.
Easiest and most recommended among all is to group those column and it will have pretty much same use which you're looking for.
If you're willing to use appscript for it. Here how it should be done:-
Open Script Editor from your spreadsheet.
Declare the onEdit simple trigger which will run every time when sheet will be edited.
So whenever you'll click on tickbox on I1 this function will trigger.
When a trigger fires, Apps Script passes the function an event object as an argument, typically called e.
For this object, we're gonna have the information we need to do our task, and also to restrict our operation to only to those months sheet and range belongs to it.
Here is the code, I tried my best to explain what happening in the code:-
function onEdit(e)
{
var rangeEdited = e.range; // This will us range which is edited
var sheetEdited = rangeEdited.getSheet().getName() // from range we can get the sheetName which is edited
var mySheets = ["Jan List","Feb List"] // Put all the month sheet name in this array where you want to have this functionality
var rowEdited = rangeEdited.getRow() // From Range we can get Row which is edited
var columnEdited = rangeEdited.getColumn() // From Range we can get Column which is edited
if(mySheets.indexOf(sheetEdited) > -1) // Now we want to only restrict the operation on those sheets,so if other sheet is edited, we shouldn't run our hide function
{
if(rowEdited === 1 && columnEdited === 9) // we're further restricting the range of operation to run this function when only I1 is edited that is Row:- 1 and Col:- 9
{
hideUnhide(sheetEdited) // calling our hide function within OnEdit and passing sheetName as an argument in it
}
}
}
function hideUnhide(sheetEdited) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssname = ss.getSheetByName(sheetEdited) // accessing the sheet which is edited
var isItHidden = ssname.isColumnHiddenByUser(1) // checking if range is already hidden
if(isItHidden === false) // if No, hide that range
{
ssname.hideColumns(1, 6)
}
else // if Yes, unhide that range
{
var hideThisRange = ssname.getRange('A:H')
ssname.unhideColumn(hideThisRange)
}
}
Documentation:-
AppScript Events
I have searched high and low but I have been unable to find an answer (I am sure I am not explaining it right)
I have a Google Sheet that have multiple sheets (tabs) labeled TabA, TabB and TabC.
On this Google Sheet, I submit a slash command on Slack, which then auto-fills a row on one of the tabs using apps script.
What I am trying to do is simply insert a word called TabA into a specific cell each time a new row has been detected. And insert a word called TabB when a new row has been made on TabB sheet etc.
I am sure I just am typing my questions wrong which is why I am unable to find an answer.
I am not actually sure which part of the code posts to the sheet, I think it is this?
if(sheetName) {
sheetName = sheetName.charAt(0).toUpperCase() + sheetName.slice(1)
} else {
sheetName = "Current"
}
// Find sheet
var sheetFlag = false;
for (var r = 1; r < settings.length; r++) {
if (settings[r][1] == channelID) {
var sheetID = settings[r][2];
var targetChannelID = settings[r][4];
var title = settings[r][0];
sheetFlag = true;
break;
}
}
if (sheetFlag) {
var sheet = SpreadsheetApp.openById(sheetID).getSheetByName(sheetName);
if(!sheet) {
sheet = SpreadsheetApp.openById(sheetID).insertSheet(sheetName);
}
var lastRow = sheet.getLastRow();
var slackDetails = ["", "", text1, "","","","","",realName, new Date(),title,text2];
// paste the slack details to the sheet
sheet.getRange(lastRow + 1,1,1,slackDetails.length).setValues([slackDetails]);```
Thank you in advance
If I understood you correctly, you want to:
Keep track of new rows that are added to each sheet in your spreadsheet (TabA, TabB, TabC).
Write the name of the sheet in successive rows of column D of each sheet every time news rows are detected.
As you were told in the comments, Apps Script has no triggers to track changes made to the spreadsheet by a script. For example, onEdit trigger "runs automatically when a user changes the value of any cell in a spreadsheet".
Workaround (time-based trigger and script properties):
A possible workaround to this limitation is using a time-based trigger that will fire a function periodically. You can create this trigger manually, or programmatically, by running this function once:
function createTrigger() {
ScriptApp.newTrigger("trackRows")
.timeBased()
.everyMinutes(1)
.create();
}
This will fire the function trackRows every minute. This function's purpose is to track changes to each sheet rows since last time it was fired (in this example, 1 minute ago) and write the sheet name to a certain cell if the sheet has more rows with content than during last execution.
To accomplish this, you can use the Properties Service, which lets you store key-value pairs and use them in later executions.
The function trackRows could be something along the following lines:
function trackRows() {
var props = PropertiesService.getScriptProperties();
var ss = SpreadsheetApp.openById("your-spreadsheet-id"); // Please change accordingly
var sheets = ss.getSheets();
sheets.forEach(function(sheet) {
var sheetName = sheet.getName();
var currentRows = sheet.getLastRow();
var oldRows = props.getProperty(sheetName);
if (currentRows > oldRows) {
var firstRow = 2;
var column = 4;
var numRows = sheet.getLastRow() - firstRow + 1;
var rowIndex = sheet.getRange(firstRow, column, numRows).getValues().filter(function(value) {
return value[0] !== "";
}).length;
var cell = sheet.getRange(rowIndex + firstRow, column);
cell.setValue(sheetName);
}
props.setProperty(sheetName, currentRows);
});
}
This function does the following:
Retrieve the script properties that were stored in previous executions.
Get all the sheets in the spreadsheet.
Check the last row with content in each sheet (via Sheet.getLastRow()), and compare the value with the one previously stored in script properties.
If the current last row is higher than the one stored in properties, write the sheet name in the first empty row of column D of the corresponding (starting at D2).
Store the current last row in script properties.
Notes:
The script is adding the sheet name to the first empty row of column D once, if it detects that new rows were added. It's not taking into account how many rows were added since last execution, it only considers if rows were added. This could easily be changed though, if that's what you wanted.
If you want to start from fresh, it would be useful to delete all previously stored properties. To do that, you could run this function once:
function deleteProps() {
var props = PropertiesService.getScriptProperties();
props.deleteAllProperties();
}
Reference:
Class ClockTriggerBuilder
Class PropertiesService
Sheet.getLastRow()
What I am trying to make is a workbook that users can select from a dropdown of a group of items (Sheet1, Column A) and then Row B lookup that selected item in sheet "Dataset" and return that value with integers that go from 0 to the corresponding stock quantity total in (Sheet "Dataset" column C)
here is a Sample spreadsheet
I got some awesome code from #iamblichus that will fill the dropdowns from the corresponding stock quantity
see his code here that I have somewhat implemented Here using a query formula to lookup the group stock quantities. I'm not sure how to make this happen across two sheets though.
Answer:
Extending the code that #iamblichus provided here, you can specify the Sheets from which to get the data from and use an onEdit() trigger to automatically change the dropdown when the cell is edited.
Code:
Attach this to the Sample Spreadsheet you provided:
function onEdit(e) {
var ss = SpreadsheetApp.getActive(); // Get the spreadsheet bound to this script
var dataSetSheet = ss.getSheetByName("Dataset"); // Get the sheet called "Working with script" (change if necessary)
var fillSheet = ss.getSheetByName("Sheet 1");
// Get the different values in column C (stock quantities):
var firstRow = 3;
var firstCol = 3;
var numRows = dataSetSheet.getLastRow() - firstRow + 1;
var stockQuantities = dataSetSheet.getRange(firstRow, firstCol, numRows).getValues();
var stockNames = dataSetSheet.getRange(firstRow, firstCol - 1, numRows).getValues();
// Iterate through all values in column:
for (var i = 0; i < stockQuantities.length; i++) {
Logger.log(stockNames);
Logger.log(stockQuantities);
var stockQuantity = stockQuantities[i][0];
var values = [];
// Create the different options for the dropdown based on the value in column C:
if (stockNames[i] == e.value) {
for (var j = 0; j <= stockQuantity; j++) {
values.push(j);
}
// Create the data validation:
var rule = SpreadsheetApp.newDataValidation().requireValueInList(values).build();
// Add the data validation to the corresponding cell in column B:
fillSheet.getRange(e.range.getRow(), 2).clear();
var dropdownCell = fillSheet.getRange(e.range.getRow(), 2).setDataValidation(rule);
}
}
}
Something to note:
I have put this as an onEdit() function because SpreadsheetApp is called in Read Only mode when inside a custom function and so no set*() methods can be called. This includes setDataValidation().
As per the Documentation, the Spreadsheet service is supported, however under 'Notes' it reads:
Read only (can use most get*() methods, but not set*()).
Cannot open other spreadsheets (SpreadsheetApp.openById() or SpreadsheetApp.openByUrl()).
References:
Stack Overflow - Dropdown auto generating a range based on a total
Google Apps Script - Range.clear() method
Google Apps Script - Simple Triggers
Google Apps Script - Custom Functions in Google Sheets
Is there a way to write a Google Apps Script in Google Docs to retrieve from Google Sheets a range limited to non-blank rows and display those rows as a table?
I'm looking for a script to copy non-blank rows of data from a Google Sheets range of cells to a table in Google Documents using Google Apps Script (which I've limited experience with).
The data to be copied seem too large for linking directly to Google Documents so the Copy-Paste action from spreadsheet to document does not prompt a choice for linking the data.
Also the number of rows is dynamic so a fixed range wouldn't resolve the problem. In the spreadsheet, I've used the SORTN function and set it to display ties so the size of the non-blank rows of the range changes.
I've started with the following code outline:
function myFunction() {
// Get Google Sheet data
var app = SpreadsheetApp;
var ss = app.openById('SHEET_ID');
var activeSheet = app.getActiveSpreadsheet();
var range = activeSheet.getRange("B4:D");
// Position to paste data in Google Docs
var doc = DocumentApp.getActiveDocument();
var body = DocumentApp.getActiveDocument().getBody();
// Build a table from the array.
body.appendTable(cells);
}
This is closest question found on SE but doesn't answer this query: Copying Sheet Data to Doc table.
You want to copy the data range from Google Spreadsheet to Google Document as the table.
You want to append the table to the Google Document.
In this case, you don't want to include the empty rows of the bottom of sheet to the values.
In your situation, you are not required to link the original Spreadsheet to the table of Document.
You want to achieve this using Google Apps Script.
I could understand like above. If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Flow:
The flow of this sample script is as follows.
Retrieve the data range from Google Spreadsheet.
In this case, I used getDataRegion(dimension).
Retrieve values, backgrounds and text styles using the range.
Append new table to Google Document with the values.
Set the format of cells.
Sample script:
From your script in your question, it supposes that the script is the container-bound script of Google Document. So in order to test the script, please put the following script to the container-bound script of Google Document you shared.
function myFunction() {
// Get Google Sheet data
var ss = SpreadsheetApp.openById("###"); // Please set the Spreadsheet ID.
var sheet = ss.getSheetByName("Sheet1");
var range = sheet.getRange(4, 2, 1, 5).getDataRegion(SpreadsheetApp.Dimension.ROWS);
var values = range.getValues();
var backgroundColors = range.getBackgrounds();
var styles = range.getTextStyles();
// Position to paste data in Google Docs
var body = DocumentApp.getActiveDocument().getBody();
var table = body.appendTable(values);
table.setBorderWidth(0);
for (var i = 0; i < table.getNumRows(); i++) {
for (var j = 0; j < table.getRow(i).getNumCells(); j++) {
var obj = {};
obj[DocumentApp.Attribute.BACKGROUND_COLOR] = backgroundColors[i][j];
obj[DocumentApp.Attribute.FONT_SIZE] = styles[i][j].getFontSize();
if (styles[i][j].isBold()) {
obj[DocumentApp.Attribute.BOLD] = true;
}
table.getRow(i).getCell(j).setAttributes(obj);
}
}
}
Note:
In this sample script, the values of cells "B4:F" are retrieved from your shared Spreadsheet. So if you want to change this range, please modify above script.
References:
getDataRegion(dimension)
getValues()
getBackgrounds()
getTextStyles()
appendTable()
setAttributes(attributes)
Added:
Issue for reflecting column width from Spreadsheet to Document:
It is possible to reflect the column width. But when the column width is set to Google Document, it seems that the result is different from that of the direct copy&paste the table, even when the unit is converted from Spreadsheet to Document.
In your shared Spreadsheet, the widths of column "B" to "F" are 21, 100, 100, 100 and 100 pixels, respectively. But it was found that when the table is manually copied from Spreadsheet to Document, each column width is changed from the original size. By this, unfortunately, when the column width of table is copied by the script, the result by manual copy cannot be replicated.
Sample script:
At the following sample script, the column width of Google Spreadsheet is copied to the table of Google Document.
function myFunction() {
// Get Google Sheet data
var ss = SpreadsheetApp.openById("###"); // Please set the Spreadsheet ID.
var sheet = ss.getSheetByName("Sheet1");
var range = sheet.getRange(4, 2, 1, 5).getDataRegion(SpreadsheetApp.Dimension.ROWS);
var values = range.getValues();
var backgroundColors = range.getBackgrounds();
var styles = range.getTextStyles();
var colWidth = []; // Added
for (var col = 2; col <= 6; col++) { // Added
colWidth.push(sheet.getColumnWidth(col) * 3 / 4);
}
// Position to paste data in Google Docs
var body = DocumentApp.getActiveDocument().getBody();
var table = body.appendTable(values);
table.setBorderWidth(0);
colWidth.forEach(function(e, i) {table.setColumnWidth(i, e)}); // Added
for (var i = 0; i < table.getNumRows(); i++) {
for (var j = 0; j < table.getRow(i).getNumCells(); j++) {
var obj = {};
obj[DocumentApp.Attribute.BACKGROUND_COLOR] = backgroundColors[i][j];
obj[DocumentApp.Attribute.FONT_SIZE] = styles[i][j].getFontSize();
if (styles[i][j].isBold()) {
obj[DocumentApp.Attribute.BOLD] = true;
}
table.getRow(i).getCell(j).setAttributes(obj);
}
}
}
When you run the script, you can see the created table is different from the manually copied table. So about the width of column, in the current stage, please give the values for manually setting colWidth. Or please adjust the column width of Document side by modifying the column width of Spreadsheet side. Or please use above script. This is due to my poor skill. I deeply apologize for this.