In a Google Sheets database, I have a formula which I have built in order to allocate a reference number to a series of companies.
Each company should have its unique number in the form of RET00XX where XX will represent the unique company number. I would like these numbers to be sequential, starting on 1 and going on +1 after that.
Whenever a new company is inserted in the database, the formula should be able to attribute it a reference number. It should also be able to verify if the company already exists in the database and, if so, automatically attribute it the company's unique reference number, instead of creating a new one.
The company names are in cells of column B.
This is the formula I have built (an example of the one in row 2):
=ARRAYFORMULA(IF($B2<>"",IF((COUNTIF($B$1:$B1,$B2)>0),INDEX($A$1:$R2,MATCH($B2,$B$1:$B1,0),12),CONCATENATE("RET00",ROW($B2))),""))
The steps it takes are:
It verifies that column B in the correspondent row is not empty;
With the COUNTIF function, verifies that the company does not exist in any of the previous rows;
If the company does exist, it attributes the correspondent reference number through the INDEX function;
If the company doesn't exist, it attributes the company a new reference number with the CONCATENATE and ROW functions.
The formula is largely working, although there are some problems.
Users adding to this database have the habit of adding entries by inserting rows in the middle of the database. This makes it so, due to the way the formula is built, that company unique reference codes change each time that happens. I believe this is partially due to the fact that I use a ROW function. Also, given that new rows are inserted in the middle of the database, the formula should be able to verify is the company already exists not only by looping through all previous rows but rather through all rows (if a new row is inserted, the formula will only verify previous rows, when the company could be in the rows after the new one).
How can I attribute sequential numbers in a formula without reference to ROW? Also, how can I make sure that the spreadsheet verifies for all rows of column B instead of just the ones before the inserted row?
apply this formula in your sheets,
=ArrayFormula(if(B2:B<>"",row(A2:A)-1,""))
More information regarding this please visit this link : https://infoinspired.com/google-docs/spreadsheet/auto-serial-numbering-in-google-sheets/
Solution that is independent of starting row number
These examples will allow you to generate incrementing values in your formulas.
Incrementing integers, zero based:
The values will be: 0,1,2,3, etc.
Note: The address "$A$2" represents the cell of your top row. It should be changed to whatever cell your actual top row is. The nice thing about this method is it it will not break if you insert new rows above the start position of your formula.
=(ROW()-ROW($A$2))
Integers, one based:
The values will be: 1,2,3,4, etc.
=(ROW()-ROW($A$2) + 1)
Dates:
The values will be: 2000-01-01,2000-01-02,2000-01-03, etc.
=Date(2000,1,1) + (ROW()-ROW($A$2))
All Even Numbers:
The values will be: 0,2,4, etc.
=(ROW()-ROW($A$2) * 2
Short answer
Use Google Apps Script
Explanation
Using spreadsheet functions to set an ID on a live spreadsheet used as a database is very risky as the values will be recalculated when changes be made to the spreadsheet content.
Instead of using a formula use a script to add a "fixed value". Scripts could be called automatically on events like cell edits and row insertion, by using a custom menu or side panel, from the script editor or by time-driven triggers.
The following Q&A from Web Applications shows several ways to set a sequential number:
Can I add an autoincrement field to a Google Spreadsheet based on a Google Form?
This other from SO could be helpful too:
Auto incrementing Job Reference
Insert 1 in the first cell and paste the formula below in the following cells.
=INDIRECT(ADDRESS(ROW()-1,COLUMN())) + 1
Add number on very first row and type the formula from next cell
i used =A1+1 to get incremental number to index tasks on each line.
Related
Collections Sheet
Expenses Sheet
Hi, I would like to get the daily sum/difference of the expenses from the expenses sheet then output to collections sheet using dates as reference/identifier.
I tried this code =MINUS(C8,INDEX(Expenses!20:31,12,2)) but I want it to auto compute when I drag the box. sorry for bad english. thank you
Desired output:
Desired Output
Output at (Net) Cash On Hand Row / Reference Date Column, the output should be August 1 Collection - August 1 Expenses.
The main issue is with the structure of your expense sheet, since you need to use only every second column. For this you can use various methods, something like
=split(substitute(join(";",Expenses!A2:DJ2),"Total:;",""),";")
The join function takes the whole row and joins it into one string, the substitute function removes the Total: from it, along with the trailing ; and the split function separates it again to separate values. This will be an array, automatically spread out to 31(-ish) columns width if entered into a cell like C10 on your Collections sheet.
Then you have two options, simply do =C8-C10 in C9, which you can drag with no problem. You can also hide the row 10 by making the text color white, or even integrate it in that sheet.
My recommendation however is not to do any of that, instead enter the formula
=arrayformula(C8:AG8 - split(substitute(join(";",Expenses!A2:DJ2),"Total:;",""),";")
into C9 on the Collections sheet and it's taken care of, without the need to drag it out. You might need to tweak it, not sure if the AG8 and DJ2 are the correct columns to end them on (should be the last column if every column or every 2 columns is a day). The arrayformula makes sure that the subtractions are done automatically for each pair of values, and expanded automatically into the row. Make sure that there are no values or formulas in D9:AG9, so it can fill up the values automatically and you don't get a #REF error.
We are using Google Forms to collect data on our students. They use the same Google Form for all students, but as part of the form, they are asked the students name.
The data that ends up being collected you can see on the tab Form Responses 1 on the Google Sheet linked here.
I am attempting to use ImportRange to create a tab for each of the students. The formula that I am using for just one of the students is...
=QUERY(IMPORTRANGE("1nJANDP1fiQunxfxEf-EjwJrnIRICv6kLhYYY9XBXtD4", "Form Responses 1!A:I"),"SELECT * WHERE Col3 = 'Adam N.'")
You can take a look at the tab called Adam N. and you'll see it is kind of working.
One thing that doesn't seem to be working is when there is a text value in columns E-I, that text value doesn't end up showing on the Adam N. tab. Any ideas how I can get both the numbers and the text values to show up?
The other thing that seems to be a problem is the fact that on the Adam N. tab, the very first row has the same headers as the Form Responses 1 tab, but it also has the very first line of data. Any way to remove that?
Importrange is not needed since you are 'importing' from within the same spreadsheet. Also, I'd recommend using the (optional) header argument in query().
It is often noted that users are tempted to mix data types within a column. The query() function will give undesirable output. If a column is intended for numeric values then only numerical values must reside in that column. Date columns must only contain dates and text columns only contain text values.
This does not mean that numbers cannot appear in a text column as long as they are in a text format. So it is important to plan the columns in a table to make sure this rule is maintained regardless if the data table is created manually or via submissions from a Google Form.
Generally, the query() function will assume the greater number of cell types in a column to be that data type. For example, if there are 100 numbers and 20 text values in the same column then a numeric value will be assumed for that column. There is a good chance the text values will just be ignored. One way to avoid this, would be to convert everything to text.
See if this works
=ArrayFormula(QUERY(to_text('Form Responses 1'!A:I),"WHERE Col3 = 'Adam N.'", 1))
I'm trying to make a spreadsheet to track membership for an organization.
Basically my design is an input sheet with columns of names associated with expiration dates, then another sheet that collects all the unique names and all of their associated expiration dates, and then one last sheet that filters the names into only those with expiration dates in the future.
I am able to collect all the unique names into one column using an arrayformula, but I am stuck trying to do a lookup operation of some kind that, for each name, will look for the name in each column and if it appears then it will add the associated expiration date to it's list (and otherwise add a blank cell, and then I can filter out the blank cells).
Is there a way to use vlookup or anything else in an arrayformula to do a series of operations for all columns in a range? Also, I want to use arrayformula because I want the formula to be infinite so the spreadsheet can keep growing. I've tried using
=ARRAYFORMULA(IF(ISERROR(VLOOKUP(A1:A,Sheet1!A2:200,1,FALSE)),,Sheet1!A1:1))
But vlookup, and anything else I tried like match, interprets Sheet1!A2:200 as a single range and performs a lookup only in the first column and does not do a separate lookup in each column.
For example, I might have this input on Sheet1
And want this result on another sheet
I suspect the combination of what you would really like and what is reasonably practical is a script but the following is an array formula, though would be cumbersome to extend and does require copying down (from B1):
=split(if(ISERROR(match(A1,Sheet1!A:A,0)),"",Sheet1!A$1)&"|"&if(ISERROR(match(A1,Sheet1!B:B,0)),"",Sheet1!B$1)&"|"&if(ISERROR(match(A1,Sheet1!C:C,0)),"",Sheet1!C$1),"|")
Assumes a unique list of names in ColumnA, such as created by:
=unique(QUERY({Sheet1!A2:A6;Sheet1!B2:B6;Sheet1!C2:C6},"where Col1 is not NULL"))
in A1.
I am trying to create an athlete database, using input from the athletes, via a Google Form, which links to a spreadsheet.
Each question on the form corresponds to a matching column on the spreadsheet. Apart from the fact that I don't seem to be able to direct replies directly into the spreadsheet (they appear in a separate sheet) everything works acceptably...
However - and there's always a however - I want the athlete's Date of Birth to generate their current age, so I include another column, which - using DATEDIF - gives this figure.
The column isn't on the form, so I have to create it separately for each new entry - currently well over 700 athletes on the database and more to come.
Here's my problem... I have manually linked the DATEDIF formula for every single athlete, using their DoB cell and the A1 cell as TODAY. They all work.
Until I add another entry. Then, below that new entry, although DATEDIF seems able to keep track of the DoB cell for every athlete displaced by the new row, it also adds a row to TODAY, so A1 becomes A2, A3 if there are two new entries, and so on.
Rather than making every single cell in column A into TODAY, is there a way to apply the DATEDIF formula to stop changing A1 as my reference?
This is the formula I am using: =DATEDIF(H2,A1,"Y") my dates are all in dd/mm/yyyy format. The athlete DoBs are all in column H, TODAY is always A1...
This is so far above my head, I seem to have created a beast that I cannot tame, other than by inserting new rows and then re-pointing hundreds of DATEDIF formulae to the correct TODAY cell. And life is too short for that!
Any help greatly appreciated...
Short answer
Use
=DATEDIF(H2,$A$1,"Y") or
=DATEDIF(H2,TODAY(),"Y")
Explanation
Google Sheets references could be relative or absolute. A1 is a relative reference, $A$1 is an absolute reference.
By the other hand, you could use a function as a function parameter.
For a league I run we keep track of games played and w/l/t and calculate that into a ranking score. The player name is listed in column U and the ranking score in column AD of a fixed table. I then use an array formula to list the players in ranking order in column E (then vlookup to pull in other stats based on the value in E for that row). Specifically I use this formula in column E:
=ARRAY_CONSTRAIN(ARRAYFORMULA(INDEX($U$4:$U$153,MATCH(LARGE($AD$4:$AD$153-ROW($AD$4:$AD$153)/COUNT($AD$4:$AD$153),ROW(E72)-ROW(E$4)+1),$AD$4:$AD$153-ROW($AD$4:$AD$153)/COUNT($AD$4:$AD$153),0))), 1, 1)
I need to be able to add players to the table in U:AD without having to edit the formula every time, i.e. from $U4:$U153 and $AD$4:$AD$153 to $U4:$U154 and $AD$4:$AD$154 in all the various places in the formula then copy the new formula all the way down.
Is there a way that I could define the range as $U$4:$U(last populated row) and the same for column AD in the above formula?
I eventually be using this in both Excel and Google Sheets so I would really like to avoid scripting. First I'm looking to solve this for Google Sheets.
Here is a copy of the sheet I am working on.
You could use INDEX and COUNTA
Instead of $U4$U153,
$U4:INDEX(U4:U,COUNTA(A4:A))
The COUNTA portion will give the number of populated rows and feed it into INDEX to give $U4:$U153
The answer for the Google sheet that you shared.
skip to the end for the simple solution
I used the indirect method by entering a formula in E1 that counts the AD column for player stats and adds 3 to get the last row. (I was going create the full range AD4:AD?? but you also have U4:U73 in the formula)
=counta(AD4:AD)+3
I then changed your formula use indirect, indirect("$AD$4:AD"&E$1), to reference the last row number in cell E1 to create the required range.
=iferror(ARRAY_CONSTRAIN(ARRAYFORMULA(INDEX(indirect("$U$4:U"&E$1),MATCH(LARGE(indirect("$AD$4:AD"&E$1)-ROW(indirect("$AD$4:AD"&E$1))/COUNT(indirect("$AD$4:$AD"&E$1)),ROW(E4)-ROW(E$4)+1),indirect("$AD$4:$AD"&E$1)-ROW(indirect("$AD$4:$AD"&E$1))/COUNT(indirect("$AD$4:AD"&E$1)),0))), 1, 1),"")
I discovered by accident that if you remove the ARRAY_CONSTRAIN from your formula and change U4:U73 to U4:AC73 then the formula will populate the scores to the right of your formula where you currently have vlookups. I put an example of this in E4 but note that you will have to delete the vlookup formulas if you want to fill the formula down otherwise it will show REF
I also added iferror so that the formula can be copied to the same row as the end of the "open slots" in column A without showing errors.
Also, I got to this point and was thinking that since you're using Google Sheets, a better way to do this could be to use the QUERY function to pull the data and also sort it using ORDER BY with a single formula in cell E4.
I've not really used the QUERY function but maybe it's time to learn.
EDIT
Turns out it doesn't take much learning
=QUERY(U4:AD,"SELECT U,V,W,X,Y,Z,AA,AB,AC ORDER BY AD DESC")
Put the formula above in cell E4 and delete everything beneath and scores to the right and you're done. you'll notice that there is no indirect because Google understands that you don't want the blank rows.
https://docs.google.com/spreadsheets/d/16IclEmKwDFdInIAZhH2vt-tLJ5pbwX06jv9xrUXwhnY/edit?usp=sharing
Why are you using $ signs around U4:U153,remove $ signs for rows that will give you flexibility while keeping columns fixed.As your drag the formula,the data array will append the newly filled cells or you can create table using Ctrl+T that will automatically expand as you keeping adding data.