Auto increment after concatenating 3 strings - excel

Problem: I need a formula to automatically increment when dragging down. Since the 3 strings are joined by concatenating, it doesn't seem to work.
=CONCATENATE("Sheet2!", SUBSTITUTE(ADDRESS(1,MATCH("String to Search For", Sheet2!$13:$13,0),4),1,""),"17")
String 1 is a separate sheet reference (Sheet2!)
String 2 is the column number converted to column letter where string to be searched is found using MATCH, ADDRESS, and SUBSTITUTE. In this case it was column 2 converted to B.
String 3 is the row number that I need information from IF string searched is found
After concatenating these, I need to drag it down 5000 rows and increment String 3 (the row number) but because the reference is concatenated, it will not increment. I've tried everything! Please help!

Try adding a ROWS function, e.g. if you put the first formula in Z2 use this version copied down
=CONCATENATE("Sheet2!", SUBSTITUTE(ADDRESS(1,MATCH("String to Search For", Sheet2!$13:$13,0),4),1,""),"17"+ROWS(Z$2:Z2)-1)
change depending on actual start cell
ROWS function, used this way, will increment by 1 each row and is more "robust" than alternatives using ROW for example

Assuming your formula is in row 2, you could do this:
=CONCATENATE("Sheet2!", SUBSTITUTE(ADDRESS(1,MATCH("String to Search For", Sheet2!$13:$13,0),4),1,""),text(row()+15,"#"))
If your formulas starts on a different row, just change the 15 as needed.

Related

Generate a unique ID (As much As possible) from a string in Excel using string functions

Let's say I have two strings in two cells
Cell A1 = Customer Country
Cell B1 = Customer City
I need to generate a unique ID using the Excel string functions (LEN, LEFT, MID, RIGHT etc.) or any other (CONCAT etc.) along with the ROW function.
Get first letter & last letter of each word, remove spaces and dashes, get the row number and return a unique string.
If I use
=IF(LEN(A$1)-LEN(SUBSTITUTE(A$1," ",""))=0,LEFT(A$1,1),IF(LEN(A$1)-LEN(SUBSTITUTE(A$1," ",""))=1,LEFT(A$1,1)&MID(A$1,FIND(" ",A$1)+1,1),LEFT(A$1,1)&MID(A$1,FIND(" ",A$1)+1,1)&MID(A$1,FIND(" ",A$1,FIND(" ",A$1)+1)+1,1))) &ROW(A$1)
I get results as CC1 in both cases. How would I get a unique ID in such as case.
The idea in the comment-section by #JosWoolley is a good one. Though, be careful how/where you'd add a column index. If you'd just add the column index number you'd create confusion between say CC111 from row 11 column 1 and the number from row 1 and possibly column 11. Just adding the actual address of the cell instead of these indices will help but can create confusion too if you don't add a delimiter first. Therefor I'd suggest something along the lines of:
Formula in D1:
=CONCAT(LEFT(TEXTSPLIT(A1," ")),"|",ADDRESS(ROW(A1),COLUMN(A1),4))
Note: If you don't yet have access to TEXTSPLIT() you can swap this with FILTERXML(). Also, you mentioned CONCAT() but if used with Excel 2019 you may need to CSE the formula.

Find Length=2 cell in a given range

I have these two rows with an image path.
In Columns D-H i have only one cell that his length is 2.
I need to find it and do formulas based on it, and I would prefer not writing 5 times "IF", any quick way to find it?
It's unclear what you're asking but it seems like you're just trying to figure out which column has a string with a length of 2 characters.
If this is the case use this formula (assuming your data starts in row 2 of the columns you mentioned):
=match(2,len(D2:H2),0) However, when you write this hit CTRL + SHIFT + ENTER
Which will give you {=match(2,len(D2:H2),0)} this is an array formula you must carry down. This will give you the relative column of the string with 2 as its length. Relative meaning, if the criteria is met in column D, it will return 1 (instead of 4).
If you want the value, just use an Index match like so, using the same CTRL + SHIFT + ENTER I mentioned earlier.
{=index(D2:H2,match(2,len(D2:H2),0))}
Here's a non-vba, non-CTE/Array formula way to do this:
=SUMPRODUCT((LEN(D1:H1)=2)*COLUMN(D1:H1))
Will spit out the number of the column that has a length of 2. If more than one column fulfills this criteria then you will get back garbage. So don't do that.
You can pop that into Index() to get the value that was hit:
=INDEX(A1:H1, 1, SUMPRODUCT((LEN(D1:H1)=2)*COLUMN(D1:H1)))

Excel Formula: Return value from array with multiple criteria

Suppose the following series:
I am trying to find the latest non 1 value that precedes the latest 1.
In this case it should return 3 and not 4.
1 being the minimum value I have tried to use MATCH(MIN(range),range,0) and add 1 to get the value I needed, but the minimum function gets stuck on the first occurrence of the minimum.
Try
=INDEX(B1:P1,1,MATCH(1,(OFFSET(B1:P1,,-1)=1)*(B1:P1>1),0))
Where B1:P1 is your data range. Of course it is an array formula (SHIFT+ENTER).
Hope that helps.
I can't see a short and snappy answer to this but here is one suggestion assuming the data starts in column A
=INDEX(2:2,AGGREGATE(15,6,COLUMN(INDEX(2:2,MATCH(1,2:2,0)):INDEX(2:2,MATCH(999,2:2)))/(INDEX(2:2,MATCH(1,2:2,0)):INDEX(2:2,MATCH(999,2:2))>1),1))
If the range didn't start in column A, you would have to subtract the number of the column before the first column of the range from the column number returned by the AGGREGATE to get the correct index value relative to the start of the array e.g. for B2:Z2
=INDEX(B2:Z2,AGGREGATE(15,6,COLUMN(INDEX(B2:Z2,MATCH(1,B2:Z2,0)):INDEX(B2:Z2,MATCH(999,B2:Z2)))/(INDEX(B2:Z2,MATCH(1,B2:Z2,0)):INDEX(B2:Z2,MATCH(999,B2:Z2))>1),1)-COLUMN(A:A))
To be honest it wouldn't be worth using a MATCH to find the last number in the range unless the number of cells in the range was very large, so the formula for B2:Z2 would just be
=INDEX(B2:Z2,AGGREGATE(15,6,COLUMN(INDEX(B2:Z2,MATCH(1,B2:Z2,0)):Z2)/(INDEX(B2:Z2,MATCH(1,B2:Z2,0)):Z2>1),1)-COLUMN(A:A))
Formula starting column A
Formula starting at column B

Sort Order formula to alphabetise in Excel

I am currently drawing up a spreadsheet that will automatically remove duplicates and alphabetize a list:
I am using the COUNTIF() function in column G to create a sort order and then VLOOKUP() to find the sort in column J.
The problem I am having is that I can't seem to get my SortOrder column to function properly. At the moment it creates an index for two number 1's meaning the cell highlighted in yellow is missed out and the last entry in the sorted list is null:
If anyone can find and rectify this mistake for me I'll be very grateful as it has been driving me insane all day! Many thanks.
I'll provide my usual method for doing an automatic pulling-in of raw data into a sorted, duplicate-removed list:
Assume raw data is in column A. In column B, use this formula to increase the counter each time the row shows a non-duplicate item in column A. Hardcord B2 to be "1", and use this formula in B3 and drag down.
=if(iserror(match(A3,$A$2:A2,0)),B2+1,B2)
This takes advantage of the fact that when we refer to this row counter in our revised list, we will use the match function, which only checks for the first matching number. Then say you want your new list of data on column D (usually I do this for display purposes, so either 'group-out' [hide] columns that form the formulas, or do this on another tab). You can avoid this step, but if you are already using helper columns I usually do each step in a different column - easier to document. In column C, starting in C3 [C2 hardcoded to 1] and drag down, just have a simple counter, which error-checks to the stop at the end of your list:
=if(C2<max(B:B),C2+1," ")
Then in column D, starting at D2 and dragged down:
=iferror(index(A:A,match(C2,B:B,0)),"")
The index function is like half of the vlookup function - it pulls the result out of a given array, when you provide it with a row number. The match function is like the other half of the vlookup function - it provides you with the row number where an item appears in a given array.
Hope this helps you in the future as well.
The actual reason that this is going wrong as implied by Jeeped's comment is that you can't meaningfully compare a string to a number unless you do a conversion because they are stored differently. So COUNTIF counts numbers and text separately.
20212 will give a count of 1 because it is the only (or lowest) number.
CS10Z002 will give a count of 1 because it is the first text string in alphabetical order.
Another approach is to add the count of numbers to the count if the current cell contains text:-
=COUNTIF(INDIRECT("$D$2:$D$"&$F$3),"<="&D2)+ISTEXT(D2)*COUNT(INDIRECT("$D$2:$D$"&$F$3))
It's easier to show the result of three different conversions with some test data:-
(0) No conversion - just use COUNTIF
=COUNTIF(D$2:D$7,"<="&D2)
"999"<"abc"<"def", 999<1000
(1) Count everything as text
=SUMPRODUCT(--(D$2:D$7&""<=D2&""))
"1000"<"999"
(2) Count numbers before text
=COUNTIF(D$2:D$7,"<="&D2)+ISTEXT(D2)*COUNT(D$2:D$7)
999<1000<"999"
(3) Count everything as text but convert numbers with leading zeroes
=SUMPRODUCT(--(TEXT(D$2:D$7,"000000")<=TEXT(D2,"000000")))
"000999" = "000999", "000999"<"001000"

Copy every nth line from one sheet to another

I have an Excel spreadsheet with 1 column, 700 rows. I care about every seventh line. I don't want to have to go in and delete the 6 rows between each row I care about. So my solution was to create another sheet and specify a reference to each cell I want.
=sheet1!a1
=sheet1!a8
=sheet1!a15
But I don't want to type in each of these formulas ... `100 times.I thought if I selected the three and dragged the box around, it would understand what I was trying to do, but no luck.
Any ideas on how to do this elegantly/efficiently?
In A1 of your new sheet, put this:
=OFFSET(Sheet1!$A$1,(ROW()-1)*7,0)
... and copy down. If you start somewhere other than row 1, change ROW() to ROW(A1) or some other cell on row 1, then copy down again.
If you want to copy the nth line but multiple columns, use the formula:
=OFFSET(Sheet1!A$1,(ROW()-1)*7,0)
This can be copied right too.
In my opinion the answers given to this question are too specific. Here's an attempt at a more general answer with two different approaches and a complete example.
The OFFSET approach
OFFSET takes 3 mandatory arguments. The first is a given cell that we want to offset from. The next two are the number of rows and columns we want to offset (downwards and rightwards). OFFNET returns the content of the cell this results in. For instance, OFFSET(A1, 1, 2) returns the contents of cell C2 because A1 is cell (1,1) and if we add (1,2) to that we get (2,3) which corresponds to cell C2.
To get this to return every nth row from another column, we can make use of the ROW function. When this function is given no argument, it returns the row number of the current cell. We can thus combine OFFSET and ROW to make a function that returns every nth cell by adding a multiplier to the value returned by ROW. For instance OFFSET(A$1,ROW()*3,0). Note the use of $1 in the target cell. If this is not used, the offsetting will offset from different cells, thus in effect adding 1 to the multiplier.
The ADDRESS + INDIRECT approach
ADDRESS takes two integer inputs and returns the address/name of the cell as a string. For instance, ADDRESS(1,1) return "$A$1". INDIRECT takes the address of a cell and returns the contents. For instance, INDIRECT("A1") returns the contents of cell A1 (it also accepts input with $'s in it). If we use ROW inside ADDRESS with a multiplier, we can get the address of every nth cell. For instance, ADDRESS(ROW(), 1) in row 1 will return "$A$1", in row 2 will return "$A$2" and so on. So, if we put this inside INDIRECT, we can get the content of every nth cells. For instance, INDIRECT(ADDRESS(1*ROW()*3,1)) returns the contents of every 3rd cell in the first column when dragged downwards.
Example
Consider the following screenshot of a spreadsheet. The headers (first row) contains the call used in the rows below.
Column A contains our example data. In this case, it's just the positive integers (the counting continues outside the shown area). These are the values that we want to get every 3rd of, that is, we want to get 1, 4, 7, 10, and so on.
Column B contains an incorrect attempt at using the OFFSET approach but where we forgot to use $. As can be seen, while we multiply by 3, we actually get every 4th row.
Column C contains an incorrect attempt at using the OFFSET approach where we remembered to use $, but forgot to subtract. So while we do get every 3rd value, we skipped some values (1 and 4).
Column D contains a correct function using the OFFSET approach.
Column E contains an incorrect attempt at using the ADDRESS + INDRECT approach, but where we forgot to subtract. Thus we skipped some rows initially. The same problem as with column C.
Column F contains a correct function using the ADDRESS + INDRECT approach.
If I were confronted with extracting every 7th row I would “insert” a column before Column “A” . I would then (assuming that there is a header row in row 1) type in the numbers 1,2,3,4,5,6,7 in rows 2,3,4,5,6,7,8, I would highlight the 1,2,3,4,5,6,7 and paste that block to the end of the sheet (700 rows worth). The result will be 1,23,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7……. Now do a data sort ascending on column “A”. After the sort all of the 1’s will be the first in the series, all of the 7’s will be the seventh item.
insert a new column and put a series in 1,2,3,4, etc. Then create another new column and use the command =if(int(a1/7)=(a1/7),1,0) you should get a 1 in every 7th row, filter the column on the 1
Highlight the 7th line. Paintbrush the format for the first 7 lines a few times. Then do a bigger chunk of paintbrush copying the format until you are done. Every 7th line should be highlighted. Filter by color and then copy and paste (paste the values) from the highlighted cells into a new sheet.
Create a macro and use the following code to grab the data and put it in a new sheet (Sheet2):
Dim strValue As String
Dim strCellNum As String
Dim x As String
x = 1
For i = 1 To 700 Step 7
strCellNum = "A" & i
strValue = Worksheets("Sheet1").Range(strCellNum).Value
Debug.Print strValue
Worksheets("Sheet2").Range("A" & x).Value = strValue
x = x + 1
Next
Let me know if this helps!
JFV
If your original data is in column form with multiple columns and the first entry of your original data in C42, and you want your new (down-sampled) data to be in column form as well, but only every seventh row, then you will also need to subtract out the row number of the first entry, like so:
=OFFSET(C$42,(ROW(C42)-ROW(C$42))*7,0)
Add new column and fill it with ascending numbers. Then filter by ([column] mod 7 = 0) or something like that (don't have Excel in front of me to actually try this);
If you can't filter by formula, add one more column and use the formula =MOD([column; 7]) in it then filter zeros and you'll get all seventh rows.

Resources