Related
I'm building a monitoring system that takes a log (where people register their work in a set format) and returns a counter, which I can use for analysis. The monitor and log are two separate workbooks. The log has entries like this: INITALS;DATE;HOUR:RESULT|
Each cell can contain multiple entries.
My first attempt was to do a simple countif and look for a string (note that I use ; instead of , in formulas since I work on a Dutch excel):
=COUNTIF('LOCATION'!Table[LOG];"*NB;??/??/????;??:??:#A*|*")
This worked fine, but the formula only counted the number of cells where this string was present, not the actual number of occurences. I then tried this solution.
=SUM(LEN('LOCATION'!Tabel13[LOG])-LEN(SUBSTITUTE('LOCATION'!Tabel13[LOG];"NB";"")))
This indeed counted the number of times "NB" was present in the LOG. However, when I tried to use the original search string, this solution stopped working:
=SUM(LEN('LOCATION'!Tabel13[LOG])-LEN(SUBSTITUTE('LOCATION'!Tabel13[LOG];"*NB;??/??/????;??:??:#A*|*";"")))
It seems to me that SUM does not recognize symbols like ? or * which are necessary to define the correct search string. Where did I go wrong? Or can this be solved in another way? I can still look into VBA, but the workbooks are slow as hell already.
"?" and "*" are wildcards. Some functions support these (like COUNTIFS()) where others don't. Like you found out, SUBSTITUTE() does not.
Here is one way to count, assuming ms365:
Formula in C1:
=REDUCE(0,A1:A2,LAMBDA(a,b,a+LET(X,SEQUENCE(LEN(b)),SUM(--(IFERROR(SEARCH("NB;??/??/????;??:??:#A*|*",b,X),0)=X)))))
Note: I removed the asterisk in front of "NB" just to make searching for a position valid in comparison to what i called variable "X".
I had an excel test that I didn't do particularly well on, but this one question had me stumped. I need an equation that takes the name in this list and outputs the agent name in 'first.initial' or "COPY" or "NOT FOUND"
Sheet 1:
Agent
Adam.m
Agent
David.e
Agent
Joe.A
Agent
Ben.B
Agent
Kat.C
Agent
Training.22
Agent
Admin
Convert these names: Correct output:
David Everit David.e
Joe a. Joe.A
Ben Ben.B
Sam p. NOT FOUND
Training 22 Training.22
David E. COPY
Kat Cathy Kat.C
David D. NOT FOUND
Adam.S NOT FOUND
The equation I submitted that my teacher said was wrong was:
=IFNA(IF(COUNTIF(Sheet1!A:A, A3)>1, "COPY", INDEX(Sheet1!A:A,MATCH(A3&"*",Sheet1!A:A,0))),"Not Found")
Well here's the thing.
You are checking the original data source for the name, pre-conversion. I must admit, the COPY was a bit misleading at first but I caught on later.
You are also wrapping the whole thing in a single logical... ISNA()... Your formula can only return TRUE, FALSE or an error from this.
Putting the wrapped ISNA() aside, this means that for your formula the majority of these entries are Not Found. True, if you instead had a list of data that had already been manipulated this would almost succeed. But you are checking for the "COPY" in the wrong data...
Your first task here would be to manipulate the data to the desired format of '[Firstname].[initial]' // So assuming that the first set of characters in the cell is always going to be the forename you can use a combination of something like:
=LEFT(A2,SEARCH(" ",A2)-1) - Gets the forname by returning the left-most characters to a length of the first space position minus 1.
=RIGHT(A2,LEN(A2)-SEARCH(" ",A2)) - Gets all characters to the right of space by determining the legth from the right as the total cell length minus the position of space.
You will need to perform a logical on the second scenario though as you want a single letter is it is a word or the entire thing if it is a number:
=IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
So what i have done here is attempt to remove 0 from the string, if it is a number, this will succeed and return that number to us. If it fails it will produce an error and progress on to the second clause, giving us the single character.
You can combine these using simple string building or a concatenate clause:
=LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
or
=CONCATENATE(=LEFT(A2,SEARCH(" ",A2)-1),".",IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
So now we are almost there, except that Ben and Adam are producing errors as there isn't a space character that can be found. We'll handle that error now so that we can move on to our search:
=IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))) - if you cannot find a space character then we will have the whole cell, otherwise, we will use the space to build the search term.
Now that we have the text formatted in the way that we want it, we can move forward to do the search, the order is important as we will need to first check our results from above for duplicates and print "COPY" where found, then look for the match and return it if it's there and lastly return "NOT FOUND" if we cannot find it.
We are going to need the use of the wildcard in order to satisfy the entry Ben. So let's show the logic first then throw the whole formula together:
=IF(COUNTIF($B$1:B1,[SearchTermFormula]),"COPY", - This part of the formula uses countif to check whether the search term already exists above it, returns "COPY" if so and will continue to the next part, the absolute referencing ($$) is important so that the range updates as you copy the formula down but keeps the first cell locked.
IF(ISNUMBER(MATCH([SearchTermFormula]&"*",Sheet1!$A$1:$A$14,0)),[SearchTermFormula],"NOT FOUND") - So this works to show the basic logical, again we use IF() to determine whether a match can be made as a number would be returned if so. We can then return the search term itself or "NOT FOUND".
A more elegent version of this part though would be:
IFERROR(INDEX(Sheet1!$A$1:$A$14,MATCH([SearchTermFormula]&"*",Sheet1!$A$1:$A$14,0)),"NOT FOUND"))
As it actually returns the result from sheet1 as well as making us use the [SearchTermFormula] 1 less time, using less resources.
INDEX() essentially maps the range as a 1 based array. What that means is the first cell in the range is considered an address of 1,1. You can think of it adding X and Y axis but 0,0 is outside the top left and the Y axis is inverted.
So we get it to index column A and MATCH returns the relative position, as the row's are equally sized, the relative position will be the row number we are after so we get the result returned or an error value, so IFERROR() leads us on to produce "NOT FOUND".
Putting all that together we have:
=IF(COUNTIF($B$1:B1,IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))))>0,"COPY",IFERROR(INDEX(Sheet1!$A$1:$A$14,MATCH(IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1)))&"*",Sheet1!$A$1:$A$14,0)),"NOT FOUND"))
Sorry for the essay but I hope it helps you understand the scope
I've adapted this solution from a couple of years ago:
=LOOKUP(2^15,FIND(Keywords,A2),Categories)
I use this for searching within a description field for keywords in a named list, in order to return a corresponding category from an adjacent named list.
However I do not understand the significance of 2^15. Can someone explain?
Also it's unclear in what order the search operates. If two keyword options were "check" and "deposit," and they were assigned to different categories, but both appeared in the same description field cell, how do I know which will be found first? Is it placement in the string, or order in the list?
2^15 is simply an arbitrarily large number, which lookup attempts to find - when it can't find it, it takes the next lowest number.
Effectively your formula looks at Keywords, and attempts to find the value in A2. For each word that actually matches A2, it provides a non-error message. Then out of the whole list, it attempts to find that line number in categories, resulting in many errors, and a single correct value. Lookup picks the value by using 2^15. Though this seems to be a weird way of doing it; it is likely a holdover of pre-2007, as Lookup is generally used now only for backwards compatibility purposes. Also using 1 instead of 2^15 worked for a couple of simple cases that I tried when writing this up.
Essentially, I am looking for a way to use the "search" function like the "vlookup" function. In my case, I am have a long list, of say, 1000 descriptions of different types of fasteners and I want to classify them according to what they are, (ie. Nut, bolt, washer etc.). However, I can't sort by description or partnumber because they, alphanumerically, don't line up by class. But he descripotion field does say at some point in it, what it is(ie. Nut, bolt, washer etc.).
As said, I have a table of classes, and I am looking for a formula that would look in the "description" field for all the values in the table,and then return that value, or one associated with it (like vlookup does with cell values).
So that, if it found "nut" in the description, it would return "nut", or if it found "bolt" it would return "bolt."
I hope that this question makes sense. Let me also say that I found a way "manually" do this using the search function, along with others, but the formula was very long and each value in my table had to be specially called out. However, I will include the formula I used to make clear what I was trying to do.
See below.
=IF(ISNUMBER(SEARCH($G$2,C3)),$G$2,IF(ISNUMBER(SEARCH($G$3,C3)),$G$3,IF(ISNUMBER(SEARCH($G$4,C3)),$G$4,IF(ISNUMBER(SEARCH($G$5,C3)),$G$5,...IF(ISNUMBER(SEARCH($G$13,C3)),$G$13,"MISC"))))))))))))
You see that with each item you add to your table, you have to add another if loop. I am hoping there is a better way. (I would call it "vsearch" :-) )
Try this formula
=IFERROR(LOOKUP(2^15,SEARCH($G$3:$G$13,C3),$G$3:$G$13),"MISC")
SEARCH returns an array of numbers or errors depending on whether each term is found in C3. By searching for "bignum" (in this case 2^15) which won't be found, the match is always with the last number, i.e. the last matching term in G3:G13.
MATCH can be used to find the text, and INDEX can be used to return the text
using your example, where you are searching in G:
=MATCH("*"&C3&"*",$G:$G,0)
and then index to return the text
=INDEX($G:$G,MATCH("*"&C3&"*",$G:$G,0))
and as a finishing touch, the #VALUE! replacement
=IFERROR(INDEX($G:$G,MATCH("*"&C3&"*",$G:$G,0)),"MISC")
EXCEL - finding a match between two tables
https://drive.google.com/folderview?id=0B2WLaA0HlUBVWnlwaFRGMmdwaVU&usp=sharing - excel file
FILE : vraag.xlsm
I would like to make a dynamically solution, for searching a text pattern from one table if it is also in the text of an other table (in different columns).
(Dynamically, I mean if the are elements are added, deleted, changed)
So searching if one the elements from column 'ID_type' can be found in the text of column 'element'
!
table A [T_example] : in a column contains tekst (within maybe one
of the elements of the other table)
table B [T_rec_by_type] : contains several possible strings
edited : next seems to be a wrong approach : MATCH()
=IF(ISNA(VLOOKUP(A23;T_rec_by_type[ID_type];1;FALSE));FALSE; "File found in row " & MATCH(A23;T_rec_by_type[ID_type];0))
In the first example (exactly match, so not as search pattern), it works.
But the idea is to search in the text to find the searchpattern ... and return via VLOOKUP a value from an other column (in this stadium just ID_type).
A possible solution found in an answer online
EXCEL - Find category by searching keyword from other worksheet
https://drive.google.com/folderview?id=0B2WLaA0HlUBVWnlwaFRGMmdwaVU&usp=sharing - excel file
FILE : SearchAMatchtingStad.xlsm
In the hope to find a solution ... for my case via this answer, I tried it out but unfortunately without succes.
So what am I doing wrong?
(I tried it first with tables, columns and ...
=IFERROR(IF(INDIRECT("Sheet1!A"&MAX(IF(ISERROR(SEARCH(CONCATENATE("*";Table1[[stad 1]:[stad 3]];"*");[#shop]))+(Table1[[stad 1]:[stad 3]]="");0;ROW(Table1[[stad 1]:[stad 3]]))))=Table2[[#Headers];[antwerpen]];[#sales];"");"Not found")
to figure out my fault/problem, why it doesn't work ...
I did it just by one cell, but without luck)
= IFERROR( IF( INDIRECT("Sheet1!A" & MAX( IF( ISERROR( SEARCH("*"&Sheet1!$B$2:$D$4&"*";$B8)) + (Sheet1!$B$2:$D$4="") ; 0 ; ROW(Sheet1!$B$2:$D$4)))) = D$7;$C8; "") ; "Not found")
A small remark ENTERING AN ARRAY FORMULA: press the CTRL SHIFT and ENTER
In a way it seems that there is an issue with array formulas
So when I do a one to one 'search' it seems to work =SEARCH("*"&B2&"*";$B8)
But when I do it with an array (despite it is still an array but with "\" instead of { "genk" ; "mol" ; "leuven" ; ... }), it seems to be a problem, or not working the way I wished. =SEARCH(CONCATENATE("*";OR(Table1[[stad 1]:[stad 3]]);"*");B8)
So I give it a last try.
But with OR or without gives the same result.
And to check if it maybe a problem is with CONCATENATE, I created a simular table with the wildcard already implemented.
Maybe ONE important thing, I forget to say there is always a space in front of the ID_TYPE.
And the ID_TYPE itself followed by a number (of maximum 3 characters) and a space.
You may have to change ; to , and , to . according to your local.
#Tom Sharpe
Thanks for your answer, but when I tried it out, it doesn't work.
Maybe ONE important thing, I forget to say there is always a space in front of the ID_TYPE.
And the ID_TYPE itself followed by a number (of maximum 3 characters) and a space.
I used 0 - in case default, not found.
Correct Tom, if I use '=FORMULATEXT(B35)', I see the formula is surrouded by { and }.
So I don't understand what I'm doing wrong.
And it worked fine at your place, you did it with my spreadsheet? Strange.
I uploaded the file changed as "vraag2.xlsm"
#user3616725
Maybe ONE important thing, I forget to say there is always a space in front of the ID_TYPE.
And the ID_TYPE itself followed by a number (of maximum 3 characters) and a space.
put new file in the shared folder : vraag2.xlsm
Here's another solution without using Regex. It tests each element in the first column of the table in A1:A7 (ID_type) using FIND to see if it is a substring of the element in A25 and below. The row numbers of any matching cells in a1:a7 are stored in an array. Because you want the first match, it uses MIN to find the lowest row number. If there is no match, it stores a reference to a cell which is outside the table, i.e. A8. I'm using FIND because I don't want to match lowercase, otherwise ... "3 spots plafond" would match with A because it has an 'a' in it.
If you enter the array formula in (say) d25 and pull it down, it will give the row number of the first matching cell in the table. If you enter the second formula in (say) e25 and pull it down, it will give the corresponding cell in another column of the table, in this case column B (type).
The first formula in structured form is:-
=MIN(IF(ISERROR(FIND(T_rec_by_type[[#Data],[ID_type]],A25)),ROW(A$8),ROW(T_rec_by_type[[#Data],[ID_type]])))
and the second one in structured form is
=IFERROR(INDEX(T_rec_by_type[[#All],[type]],D25),"Not found")
The formulae in ordinary notation (which I find a bit easier) are
=MIN(IF(ISERROR(FIND(A$2:A$7,A25)),ROW(A$8),ROW(A$2:A$7)))
and
=IFERROR(INDEX(B$1:B$7,D25),"Not found")
ROW(A$8) above is just a not very subtle way of getting a row number which is greater than that of any rows in the table. You could just use an arbitrary large number, or perhaps add a Totals row to the first table and use that to get the reference.
I haven't been able to work out why your vlookup didn't work with the table (it's OK if I copy the cells somewhere else), perhaps other people can comment.
using REGEX functions from MORFUNC ADDON*
I used your vraag.xlsm shhet that you linked to.
In cell C25 put: =REGEX.MID(TABLE12[[#ThisRow],[element]],MCONCAT(T_rec_by_type[ID_type],"|"),,TRUE)
this will give you the first (left-most) of the "keywords" that appears in the corresponding "element" cell.
This is almost there. but you say that the "SSR" sensor is more important than V, so that's the one that should be displayed if they both appear.
this is not pretty, but will work (if u provide more details on possible "ID_type"s and the order of things in "element" field i might be able to come up with something more elegant...) :
paste in cell D25:
=IF(REGEX.COMP(Table12[[#This Row],[element]],A$2,TRUE),A$2,IF(REGEX.COMP(Table12[[#This Row],[element]],A$3,TRUE),A$3,IF(REGEX.COMP(Table12[[#This Row],[element]],A$4,TRUE),A$4,IF(REGEX.COMP(Table12[[#This Row],[element]],A$5,TRUE),A$5,IF(REGEX.COMP(Table12[[#This Row],[element]],A$6,TRUE),A$6,IF(REGEX.COMP(Table12[[#This Row],[element]],A$7,TRUE),A$7,""))))))
copy C25 and D25 down, for the other elements
MOREFUNC ADDON
Morefunc Addon is a free library of 66 new worksheet functions.
HERE is some information (by original author)
here is the last working download link I found
here is a good installation walk-through video