Situation:
1 company, 3 different points of sale.
I have to make 3 different stacks of invoices.
Invoice numbers are 1/1/1, 1/1/2, 1/1/3, where the first number is incremental, second number is always 1 & third number is the point of sale identifier.
First sheet is data input.
Second is the is invoice generator.
Sheet 3, 4 & 5 are point of sale invoice archive.
I managed to get next invoice number generated depending on the point of sale using the index and left functions in separate cells but i get the error message along with the result that i actually wanted.
Is there a simple way to get generated IDs from POS1, POS2, POS3 sheets into a drop-down list data validation without any error?
Sheet Racun ->Click on the invoice number, choose point of sale (eg. POS1).
Go to sheet POS1 and click save.
https://docs.google.com/spreadsheets/d/1RD_rkbtmhC-OKh2dAtc32Qo1p42RdgKaiZsnI8uRKyg/edit?usp=sharing
I am sorry if i didnt explain myself correctly. English is not my mother language.
Suggestion
You can try adding this onOpen() function below on your Apps Script to automatically get the generated IDs from POS1,POS2,POS3 sheets & build a new data validation drop-down on cell C11 of the Racun sheet.
Script
function CopyRow(){
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var data = sh.getRange('A3:F3').getDisplayValues();
var lastRow = sh.getLastRow()+1
sh.getRange('A'+lastRow+':F'+lastRow).setNumberFormat("#").setValues(data);
}
function onOpen(){
var sh = SpreadsheetApp.getActive();
var cell = SpreadsheetApp.getActive().getSheetByName("Racun").getRange('C11');
var values = [sh.getSheetByName("POS1").getRange("K2").getValue()+" (POS1)",
sh.getSheetByName("POS2").getRange("K2").getValue()+" (POS2)",
sh.getSheetByName("POS3").getRange("K2").getValue()+" (POS3)"];
var rule = SpreadsheetApp.newDataValidation().requireValueInList(values).build();
cell.setDataValidation(rule);
}
Sample Demonstration
After saving & running the script or re-opening of your sheet, you will see the new drop-down:
NOTE:
On your POS1,POS2,POS3 sheets, just change the formula on cell A3 with =LEFT(Racun!C11, LEN(Racun!C11)-6) to get the generated IDs, as seen below:
Related
I will try to be as clear as possible. Here is the example piece: link
What I want to happen is that the Filter formula will search for any Sheet containing “Form Responses” and then display the results. You can see on the Current sheet how I’ve been doing, but this is more tedious and leads to issues of the first formula begins to overwrite the next one, etc. On the Wanted tab, I’ve laid out how I imagine it and put a note in A7. Any help offered is greatly appreciated!
You can get started with this script:
function getSheetResponses(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Wanted");
var getCellValue = sheet.getRange("A7").getValue(); //Gets the name of your designated sheet on "Wanted Sheet" cell "A7"
var getName = ss.getSheetByName(getCellValue);
var getNameValue = getName.getRange(2,5,getName.getLastRow(),1).getValues(); //Gets all the values of Column E on any defined sheet names based on getCellValue
var datalength = getNameValue.length;
Logger.log(datalength);
sheet.getRange(8,6,datalength,1).setValues(getNameValue); //Puts the data on Wanted Sheet Column F
}
What this does is it gets the sheet name on cell A7, and populates the data on Column F row 8 on the "Wanted" sheet like so:
Now, the data it populates on the "Wanted" sheet came from Form Responses 1 based on the sample piece you have provided:
If ever you would want to relocate which specific row or column the data would be pasted on "Wanted" Sheet. You can refer to this documentation on how to modify the rows and columns on sheet.getRange()
Reference:
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getrangerow,-column,-numrows,-numcolumns
Hello i'm using google sheet as my second databse and in the main page called Companies i have a list of companies as shown below:
and i wrote a function that generate a new tab for every companie in the first column. here is what a tab looks like
my goal is in the companies tab under "Workers" i want to get the value of "Total workers" of each companie. the list of companies will be constantly growing so i thought about maybe a function that uses the value of the first column to search for the tab and then get the value of G2.
I am really new to google sheet and i would appreciate any help on how to solve this problem
SUGGESTION
You can try this sample script below with custom function named getTotalWorkers & then add it as a bound script to your Spreadsheet file:
UPDATED Script:
function getTotalWorkers(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var names = ss.getRange("Company!A2:A").getValues().filter(String); //get names of the sheets on column A
var res = [];
for(x=0; x<names.length; x++){
var data = ss.getRange(names[x]+"!G2").getValue(); //get the current cell G2 values on every sheet tabs
res.push([data]); //place all values to a tem[orayr array variable
}
ss.getSheetByName("Company").getRange(2,6,res.length,1).setValues(res); //add the values under the "Workers" column on Company sheet tab
}
Sample Demonstration
After saving the script from the Apps Script editor, place the updated getTotalWorkers function to a time-driven trigger:
The time driven trigger will auto populate the "Workers" F column cells every minute (based on my sample time-driven trigger configuration):
I have tons of Google Forms for a project and each one has the same sections and questions, just different choices. Every time I want to update a question, I have to change each form individually which takes a lot of time. I was wondering if there's a way to link a Form to a Sheet so I can change the question in the spreadsheet and it'll update in every single form connected.
One option I could suggest is to create a container-bound script in your Google Sheets to update the questions for multiple Google Forms using Apps Script.
Example Sheet:
We have a Google Sheet with 2 Sheets named "Questions" and "Forms" respectively.
Sheet:Questions contains the list of questions available in your Google Forms. To Update column can be used as a flag to determine which questions you want to update in the Google Forms.
Sheet:Forms contains the list of Google Forms Ids' where you want the questions to be updated.
Example Apps Script Code:
function updateFormsQuestions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formsSheet = ss.getSheetByName("Forms");
var questionsSheet = ss.getSheetByName("Questions");
//Get the list of forms to update
var formsList = formsSheet.getRange(2,1,formsSheet.getLastRow()-1).getValues();
Logger.log(formsList);
//Get the list of questions to update
var questionIndex = [];
var qCheckbox = questionsSheet.getRange(2,2,questionsSheet.getLastRow()-1,1).getValues();
Logger.log(qCheckbox);
qCheckbox.forEach(function(currentValue, index){
if(currentValue[0] == true)questionIndex.push(index);
});
Logger.log(questionIndex);
//Open Form and get all items
for( var i = 0; i < formsList.length; i++){
var forms = FormApp.openById(formsList[i][0]);
var items = forms.getItems();
//Update question
questionIndex.forEach(function(index){
Logger.log(index);
Logger.log(questionsSheet.getRange(index + 2, 1).getValue());
items[index].setTitle(questionsSheet.getRange(index + 2, 1).getValue());
});
}
}
What it Does?
Get the list of Google Forms Ids' under Sheet:Forms
Get all checkbox values under Sheet:Questions starting from Cell B2.
Check each checkbox values if set to true, then push the current index to the questionIndex array. (Note that in javascript array index starts from zero).
Open each forms listed in step 1, one-by-one using for-loop using FormApp.openById(). Then get all items of the current forms using .getItems(). It will give you an array of items available in your form (this may represent your questions in your form).
Forms items can be accessed as an array. Hence it should start from zero. (Question 1 = index 0, Question 2 = index 1 ... so on)
Update the questions in the current item using .setTitle(). The new title will be based on the cell value under Sheet:Questions column A. You can get the value of the cell using .getValue() assuming you already selected the correct cell range using .getRange().
Notice that we increment the row index by 2 when getting the cell value questionsSheet.getRange(index + 2, 1).getValue(). Cell rows and columns starts from 1 in sheets, if we want to access Cell A3, row = 3; col = 1. The index that we saved earlier in Step 3 starts from zero (since we used an array). If you are curious why we increment 2 instead of 1. The reason is because we also adjusted the indexing when we start getting the checkbox values from row 2 instead of row 1 in Step 2.
Sheet:Questions Column C will show you the indexing of the qCheckbox array, while Column D will show you the indexing of sheets when accessing rows.
Output:
BEFORE:
AFTER:
Additional References:
Forms Service - allows scripts to create, access and modify Google Forms
Spreadsheet Service - allows scripts to create, access, modify Google Sheets
I need the code to autosave copies in google sheets when closing an invoice template i have made - to save it based on the invoice number and to reopen to a new invoice with the invoice number increased by 1
i am including a link to the sheet
https://docs.google.com/spreadsheets/d/1b4saYo1ruVfpUbUsGVd0Vf3NmjwQo78riuMyWi0OFcg/edit?usp=sharing
there are formulae sitting in the sheet which should not be changed.
i just need to be able to have the code for a button that i can click and it closes the current sheet at the same time saving it as a pdf in an online location and when i reopen the invoice number has increased by 1
What you have:
Each sheet is an invoice with a number
What you want:
Trigger a new blank invoice to appear
This new invoice needs to have a unique number = previous number + 1
To accomplish this you will have to:
Get the current sheet (the current invoice)
Copy the sheet
I would suggest renaming it to the invoice number for easier finding
Update the current invoice number.
Delete the old invoice contents on the original sheet (previously referred to as current sheet)
Step-by-step
Preliminary Setup
I've made a copy based on the sheet you provided. I did some modifications like removing the extra columns and rows to make life easier.
Based on this copy, let's store some information about our sheet into a variable.
On out Apps Script code for that sheet, let's write:
const fieldsA1 = {
invoiceNumber : "F5",
salesperson : "A14" //As an example of a field we want to clear later
};
function generateNewInvoice() {
}
Get the current sheet
var spreadsheet = SpreadsheetApp.getActive(); //Gets the current spreadsheet file
var currentInvoice = SpreadsheetApp.getActiveSheet(); //Get the open Sheet (the current invoice)
Copy the sheet
var copyInvoice = spreadsheet.duplicateActiveSheet(); //Creates a copy of currentInvoice and assign it to copyInvoice
Rename and style the new sheet
In this case I chose to style the new sheet in the following format:
copyInvoice.setName("Invoice " + currentInvoice.getRange(fieldsA1.invoiceNumber).getValue());
copyInvoice.setTabColor("red"); //For example, to highlight the tab
Update the current invoice number
var newInvoiceNumber = Number(currentInvoice.getRange(fieldsA1.invoiceNumber).getValue())+1; //Gets a new invoice number by adding 1 to the current Invoice Number
currentInvoice.getRange(fieldsA1.invoiceNumber).setValue(newInvoiceNumber);
Delete the old contents from the original sheet
//Other operations that might be interesting for your invoice
currentInvoice.getRange(fieldsA1.salesperson).clear(); //Reset salesperson
Final result
const fieldsA1 = {
invoiceNumber : "F5",
salesperson : "A14" //As an example of a field we want to clear later
};
function generateNewInvoice() {
var spreadsheet = SpreadsheetApp.getActive(); //Gets the current spreadsheet file
var currentInvoice = SpreadsheetApp.getActiveSheet(); //Get the open Sheet (the current invoice)
var copyInvoice = spreadsheet.duplicateActiveSheet(); //Creates a copy of currentInvoice and assign it to copyInvoice
copyInvoice.setName("Invoice " + currentInvoice.getRange(fieldsA1.invoiceNumber).getValue());
copyInvoice.setTabColor("red"); //For example, to highlight the tab
var newInvoiceNumber = Number(currentInvoice.getRange(fieldsA1.invoiceNumber).getValue())+1; //Gets a new invoice number by adding 1 to the current Invoice Number
currentInvoice.getRange(fieldsA1.invoiceNumber).setValue(newInvoiceNumber);
//Other operations that might be interesting for your invoice
currentInvoice.getRange(fieldsA1.salesperson).clear(); //Reset salesperson
}
Now it's just a matter of triggering the generatedNewInvoice function from the sheet. You could do this with a toolbar action, for example.
I have two sheets used to track a construction project.
On the first sheet, a list of tasks is incorporated into a timeline with cost projections, etc. The tasks are something like the following:
Cut Concrete
Pour new pad
Frame
Roof
The second sheet is for tracking individual purchases, each of which is associated with a task from the first sheet (e.g., Cut Concrete). It looks something like the following:
DATE PAYEE ITEM CATEGORY COST
----- ---------- ---------- -------- ------
10/25 Home Depot (10) 2x4's Frame ▽ $54.00
Using Data Validation, the Category dropdown in the second sheet references the list of items from the first sheet. This is working perfectly. Here's the problem...
If I change the item on the first sheet (for instance, "Frame" to "Framing"), although the dropdown is updated, any previously entered rows (such as the one shown above), just show a validation error (i.e., a red indicator in the right corner of the cell).
Since a construction project can easily have hundreds of items purchased, rather manually looking for data validation errors, is there a way to have the second sheet's values updated? For instance...
Add a script that watches for content changes in the first sheet. When the user starts editing a "task" cell, its original value is noted; and upon exiting the cell, if the value has changed, the script looks through the second spreadsheet for the original value and replaces it with the new one. (Seems like a lot of hassle.)
Find some way for the dropdown to insert a cell reference to the first sheet instead of the actual value. That way, the dropdown cell is always referencing the source item (i.e., the "task" cell's current content).
A more obvious feature I don't know about.
As per my favored possibility noted in my question, I figured out how to write a script that would run after a value was selected from the dropdown, thus overwriting the literal value with a cell reference.
The following script runs after the user makes a selection in the dropdown menu:
function onEdit(event){
var activeSheet = event.source.getActiveSheet();
var activeSheetName = activeSheet.getName();
var activeCell = activeSheet.getActiveCell();
var activeColumn = activeCell.getColumn();
if (activeSheetName == "Envelope (Spent)" && activeColumn === 4) {
var destinationCell = activeCell;
var destinationContent = destinationCell.getValue();
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var sourceSheetName = sourceSheet.getName();
var sourceRange = sourceSheet.getRange("D:D");
var sourceValues = sourceRange.getValues();
for (var i = 0; i < sourceValues.length; i++) {
if (sourceValues[i] == destinationContent) {
var sourceRow = sourceSheet.getRange("D" + i + ":D" + i).getRow() + 1;
destinationCell
.setValue("='" + sourceSheetName + "'!D" + sourceRow)
.setNote(destinationContent)
;
}
}
}
}
To allow for an easy recovery in case the two sheets somehow get out of sync, the originally selected value, derived from the dropdown's data validation, is inserted as a note. I figured it was easier to clear all the notes in the future than to find myself with a bunch of entries that don't correspond with the source list of tasks.
The data validation in Google sheets is always inserting the Literals you type or pick so you can't link it to the original cell. You have to solve the whole thing through scripts
Get a list of all data validation items through onOpen()
Create an onEdit() function that runs if the data validation range is edited, checks which field is changed and then goes through the purchases, checks which purchases have the old value and replaces them with the new one.