Categorization Based on Text-Code in Columns - excel

I have two columns with codes relating to various products. It is a 3-part code delimitized with a '-'. The length of each of the 3 parts are not constant and are alphanumeric.
The need is that I have to categorize them according to 4 criterias:
Compare each of the codes in B against A and vice-versa, and categorize them all as below and in the image:
1. Exactly Matched codes
2. Prefix or Suffix Changes codes
3. Totally New codes
However there seems to be a complication. The codes in two columns are not necessarily sorted and there can be a match anywhere in the other column, Is there a way to look up for the text and then do the compare function. I know this opens up a lot of complications -- my thought is to look up the value, and then pass the parameters to get the category.. Thanks again!!! – user1087661 1 hour ago
Kindly help me achieve this. Is there any formula to check through an array and Find functions? many thanks for the support.

you can use split function and select case to deal with your problem. i assume you know how to use a UDF.
Function CompareCode(Text1, Text2, Optional Delim = "-")
Dim T1, T2, CC
T1 = Split(Text1, Delim)
T2 = Split(Text2, Delim)
CC = (T1(0) <> T2(0)) * 100 + (T1(1) <> T2(1)) * 10 + (T1(2) <> T2(2)) * 1
CC = Format(-CC, "000")
Select Case CC
Case "000": CompareCode = "Same code"
Case "100": CompareCode = "Prefix changed"
Case "010": CompareCode = "Base changed"
Case "110": CompareCode = "Prefix and base changed"
Case "001": CompareCode = "Suffix changed"
Case "101": CompareCode = "Prefix and suffix changed"
Case "011": CompareCode = "Base and suffix changed"
Case "111": CompareCode = "Totally new code"
Case Else:
End Select
End Function

This is merely a partial answer:
For the first part, the exactely matching codes, you can use a simple lookup formula such as SUMIFS() where you are matching the items in Column B to the whole set in Column A.
For the other two requirements, if I wanted to do this by formula, then I would use the LEN(), LEFT() and RIGHT() formulas to extract the prefix, base, and sufix into separate columns. Do this for both Group A and B.
Finding your matching groups should become fairly straight forward from that point on.

Related

Select Case with Complex Return Value (VBA 2007)

Using Excel 2007 and inexperienced with VBA.
I am trying to create a text generator where, given a particular type of entry, it returns a string of text AND a number of corresponding cells.
I have a lot of data to combine and somewhat complex text statements. The data I have here is sample data. The final file will combine multiple text strings ("one" and "two", etc) with multiple cells that need to be referenced based on the specific data input there (some instances require 8 different cells).
I was able to figure out how to do Select Case where it can look up the type of entry I need, and it returns a specific text string. Great! I also know I can combine things like "One" & "Two". But how do I combine the corresponding text for the line?
Where if the entry was "ID" I could return something that looked like "One 1" but combines "One " & K2 as the .Value to return?
Image shows the sample data
Image shows data for Columns I, J, and K.
Column I stores the entry type, J is where the data is returned, and K is the column with data to be referenced. Again, what's here is the simplified reference data.
I know this line is wrong. But I'm not sure what to put in place for K2 so it will correctly reference the cell, and then loop correctly for 300 times.
Case Is = "ID": .Value = "One" & (K2)
Am I close to something workable? What would you suggest? Is Select Case the wrong way to handle this problem?
I've tried a number of options, but I am inexperienced with VBA. I think whatever I implemented to fix the issue was likely done incorrectly.
Full code of what I have shown below.
Private Sub CommandButton1_Click()
Dim logtype As Range
For Each logtype In Range("I2:I302")
With logtype.Offset(0, 1)
Select Case logtype.Value
Case Is = "ID": .Value = "One" & K2
Case Is = "Phase": .Value = "Two"
Case Is = "Install New": .Value = "Three"
Case Is = "Install OH": .Value = "Four"
Case Is = "Install AR": .Value = "Five"
Case Is = "Insp": .Value = "Six"
Case Is = "LUI": .Value = "Seven"
Case Is = "": .Value = ""
Case Else: .Value = "Not Recognized"
End Select
End With
Next logtype
End Sub
EDIT:
What I put in a comment below, just formatted more clearly.
I want to create a macro that spits out the correct language of an entry based on the kind of work completed in a work order.
For example, ID or Install New and then return the correct language and reference data for the entry:
I2: ID
K2: Number (I'd type in the actual No.)
Returns:
"Complied with ID No. [K2]. No defects noted."
I4: Install New
L4: Actual part number
M4: etc...
N4: ...
O4: ...
Returns:
"Removed P/N [L4], S/N [M4]. Installed P/N [N4], S/N [O4]. Ops checked good."
Does that make sense? Thanks!
EDIT 2:
Hey everyone, I've tried tracking down alternative methods of solving this problem but I still haven't produced anything better than what I have here.
Any thoughts or help would be greatly appreciated. Thank you!
For each cell in Range("I2:I302")
cell.offset(0,1).value=cell.offset(0,1).text & cell.offset(0,2).text
next

Way to extract Count from description

I constantly am tasked with pulling information from another source and receive the information without Size denomination. The size or count is in the description and want to be able to write an excel formula with the following logic:
if cell contains Capsules, Tablets, Liquid, etc, then make this cell equal too Capsules, Tablets, Liquid, etc + the number that comes before it
A few example items:
Nature's Bounty Magnesium 500 mg, 200 Tablets
Aerobic Life Mag 07 Oxygen Digestive System Cleanser Capsules, 180 Count
Natural Vitality Natural Calm Anti Stress Drink 30 count Raspberry Lemon
Want the following column to have Tablets or Count if it is said in the description.
I've tried using if and then statements but don't know how to combine them to create 'or' and 'and'
Expect to have the columns from the examples above to look as follows:
200 Tablets
180 Count
30 Count
If the values are in column A, the formula would be like that:
=+IF(ISERROR(VALUE(RIGHT(LEFT(A3,SEARCH(IF(ISERROR(SEARCH("Tablets",A3)),IF(ISERROR(SEARCH("Capsules",A3)),IF(ISERROR(SEARCH("Count",A3)),"","Count"),"Capsules"),"Tablets"),$A3)-1),4))),0,VALUE(RIGHT(LEFT(A3,SEARCH(IF(ISERROR(SEARCH("Tablets",A3)),IF(ISERROR(SEARCH("Capsules",A3)),IF(ISERROR(SEARCH("Count",A3)),"","Count"),"Capsules"),"Tablets"),$A3)-1),4)))&" "&IF(ISERROR(SEARCH("Tablets",A3)),IF(ISERROR(SEARCH("Capsules",A3)),IF(ISERROR(SEARCH("Count",A3)),"","Count"),"Capsules"),"Tablets")
As the formula is long see below separated in two different cells, the first one search which is the item we are looking (Tablets, Capsules or Count) and returns it, the second one search the previous number:
+IF(ISERROR(SEARCH("Tablets",A4)),IF(ISERROR(SEARCH("Capsules",A4)),IF(ISERROR(SEARCH("Count",A4)),"","Count"),"Capsules"),"Tablets")
+IF(ISERROR(VALUE(RIGHT(LEFT(A4,SEARCH(B4,$A4)-1),4))),0,VALUE(RIGHT(LEFT(A4,SEARCH(B4,$A4)-1),4)))
The formula has a limitation regarding the numbers is getting, and it's limited to 9999, more than that the formula trunks the result. Also for number 1 to 9 the formula may return error #value. This can be addressed changing the second formula if needed.
I would do something like this:
Start with an IF statement IF(-test-, -true-, -false-)
Populate the -test- portion. Say I first wanted to find 'Tablet'. I could use ...FIND("Tablet",A2)... However, the issue here is if "Tablet" is not found it will throw an error so I would error-proof it like this ...IFERROR(Find("Tablet",A2), FALSE)... which will return FALSE if "Tablet" is not found in cell A2.
But I also want to look for 'Count' so I could use an OR along with that I already built up ...OR( IFERROR(Find("Tablet",A2), FALSE), IFERROR(Find("Count",A2), FALSE) ) so this will OR together the outcomes - if either "Tablet" or "Count" is found, this function returns a number (and since it's a number, it's read as TRUE!)
Now I throw that OR() equation into my IF for the -true-, then of course my I could make as "Tablet" or "Count" or put a new equation there to specifically say what it found. And my -false- I can make ""
At this point, I would have a complete equation which will check for "Count" or "Tablet" and spit out whatever is in my -true- equation. Otherwise, the cell would remain blank:
IF(OR( IFERROR(Find("Tablet",A2), FALSE), IFERROR(Find("Count",A2), FALSE) ), "Count/Tablet", "")
Here's a lightly-tested UDF using RegExp:
Function Amounts(txt)
Dim re As Object, allMatches, m, rv, sep
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "(\d+\s?(tablets|tablet|count|liquid))"
re.ignorecase = True
re.MultiLine = True
re.Global = True
Set allMatches = re.Execute(txt)
For Each m In allMatches
rv = rv & sep & m
sep = ","
Next m
Amounts = IIf(rv <> "", rv, "(none)")
End Function
Usage:
=Amounts(A2)

Returning multiple values using Vlookup in excel

I have an excel sheet set up to automatically calculate meetings per day by day of the week. I would like to write a formula to return all dates I have a meeting scheduled (comma separated preferably), but I am having some difficulty. Using Vlookup, I can only get it to return the first date.
For example, here is what my data looks like:
A B C
Initial Meetings Follow-up Meetings Date
1 1 7/29/2015
0 1 7/30/2015
1 1 7/31/2015
0 0 8/1/2015
0 0 8/2/2015
I would like to write a formula to return "7/29/2015, 7/31/2015" in one cell, and "7/29/2015, 7/30/2015, 7/31/2015" in another, but I seem to be stuck.
You can't do this with vLookup.
This can be done relatively easily in a VB script, but it would affect portability as many if not most users disable macros by default and in many cases users are prevented from using Macros because their company disables them and makes it policy that users should not use them.
If you are OK with Macros, you can put the following into a new module and then use =MultiVlookup(lookup_value,table_array, col_index_num) in the same way as you'd use vlookup and it should give you a comma separated list of multiple matches:
Public Function MultiVlookup(find_value, search_range, return_row)
Dim myval ' String to represent return value (comma-separated list)
Dim comma ' Bool to represent whether we need to prefix the next result with ", "
comma = False
'Debug.Print find_value.value, return_row
For Each rw In search_range.Rows ' Iterate through each row in the range
If rw.Cells(1, 1).value = find_value Then ' If we have found the lookup value...
If comma Then ' Add a comma if it's not the first value we're adding to the list
myval = myval + ", "
Else
comma = True
End If
myval = myval + Str(rw.Cells(1, return_row).value)
End If
Next
MultiVlookup = myval
End Function
This may not be the cleanest way of doing it, and it isn't a direct copy of vlookup (for instance it does not have a fourth "range lookup" argument as vlookup does), but it works for my test:
Finally my original suggestion (in case it helps others - it's not the exact solution to the question) was:
I've not tried it myself, but this link shows what I think you might be looking for.
Great code, but don't forget to add the following is you use Option Explicit:
Dim rw As Range
WHEELS

Prevent Partial Duplicates in Excel

I have a worksheet with products where the people in my office can add new positions. The problem we're running into is that the products have specifications but not everybody puts them in (or inputs them wrong).
Example:
"cool product 14C"
Is there a way to convert Data Valuation option so that it warns me now in case I put "very cool product 14B" or anything that contains an already existing string of characters (say, longer than 4), like "cool produKt 14C" but also "good product 15" and so on?
I know that I can prevent 100% matches using COUNTIF and spot words that start/end in the same way using LEFT/RIGHT but I need to spot partial matches within the entries as well.
Thanks a lot!
If you want to cover typo's, word wraps, figure permutations etc. maybe a SOUNDEX algorithm would suit to your problem. Here's an implementation for Excel ...
So if you insert this as a user defined function, and create a column =SOUNDEX(A1) for each product row, upon entry of a new product name you can filter for all product rows with same SOUNDEX value. You can further automate this by letting user enter the new name into a dialog form first, do the validation, present them a Combo Box dropdown with possible duplicates, etc. etc. etc.
edit:
small function to find parts of strings terminated by blanks in a range (in answer to your comment)
Function FindSplit(Arg As Range, LookRange As Range) As String
Dim LookFor() As String, LookCell As Range
Dim Idx As Long
LookFor = Split(Arg)
FindSplit = ""
For Idx = 0 To UBound(LookFor)
For Each LookCell In LookRange.Cells
If InStr(1, LookCell, LookFor(Idx)) <> 0 Then
If FindSplit <> "" Then FindSplit = FindSplit & ", "
FindSplit = FindSplit & LookFor(Idx) & ":" & LookCell.Row
End If
Next LookCell
Next Idx
If FindSplit = "" Then FindSplit = "Cool entry!"
End Function
This is a bit crude ... but what it does is the following
split a single cell argument in pieces and put it into an array --> split()
process each piece --> For Idx = ...
search another range for strings that contain the piece --> For Each ...
add piece and row number of cell where it was found into a result string
You can enter/copy this as a formula next to each cell input and know immediately if you've done a cool input or not.
Value of cell D8 is [asd:3, wer:4]
Note the use of absolute addressing in the start of lookup range; this way you can copy the formula well down.
edit 17-Mar-2015
further to comment Joanna 17-Mar-2015, if the search argument is part of the range you're scanning, e.g. =FINDSPLIT(C5; C1:C12) you want to make sure that the If Instr(...) doesn't hit if LookCell and LookFor(Idx) are really the same cell as this would create a false positive. So you would rewrite the statement to
...
...
If InStr(1, LookCell, LookFor(Idx)) <> 0 And _
Not (LookCell.Row = Arg.Row And LookCell.Column = Arg.Column) _
Then
hint
Do not use a complete column (e.g. $C:$C) as the second argument as the function tends to become very slow without further precautions

Sort out dimensions listed incorrectly/only keep data in a certain format

I have a list of around 1500 items with dimensions, but the dimensions do not all have the same format. The dimensions I want to keep are listed as L x W x H. How can I sort the dimensions listed like this from the stuff I don't want (some are listed as only L x H, Diameter, or just gibberish, etc.) Thank you.
If by gibberish you mean text values that could include <space>x<space> then you have some real problems. However, it it can be reasonable assumed that the L x W x H format is what you want and the only values that contain 2 occurrences of <space>x<space> are valid ones then a helper column would identify the valid entries.
In an unused column to the right put this formula into the second row.
=ISNUMBER(FIND(" x ", $A2, FIND(" x ", $A2) + 3))
Fill down as necessary. The results should resemble the image below.
        
Use Data ► Sort & Filter ► Filter to filter your Helper column for FALSE. These entries can be deleted and when you turn the filter off you will be ;left with valid entries.
Elaborating on #jeeped's answer, if you are dealing with data from an external source, you might want to relax your rules to allow other valid input formats:
There must be exactly three numbers, all non-negative integers.
A decimal point is allowed, but no digits after the decimal point.
They can be separated by "x" or "X" or "*".
They can have extra spaces before, after or between the numbers, but not between the digits.
That would mean these values would all be OK:
17x12x13
100 * 50 * 2
100. X 200. X 300
Problems of this sort are ideally suited to regular expressions. The RegExp feature can be added in Code editor with Tools > References, then check "Microsoft VBScript Regular Expressions". Then try this VBA function:
Public Function IsNxNxN(s As String) As Boolean
With New RegExp
.Pattern = "^\s*(\d+)\.?\s*[xX*]\s*(\d+)\.?\s*[xX*]\s*(\d+)\.?\s*$"
With .Execute(s)
IsNxNxN = (.Count = 1)
End With
End With
End Function
In jeeped's sample worksheet, you would replace the B2 formula with:
=IsNxNxN(A2)
If you are trying to clean up the data as well as filter it, you could use this:
Public Function CleanupNxNxN(s As String) As String
With New RegExp
.Pattern = "^\s*(\d+)\.?\s*[xX*]\s*(\d+)\.?\s*[xX*]\s*(\d+)\.?\s*$"
With .Execute(s)
If .Count = 1 Then
With .Item(0)
CleanupNxNxN = .SubMatches(0) & " x " & _
.SubMatches(1) & " x " & _
.SubMatches(2)
End With
End If
End With
End With
End Function
and set the formula for C2 to:
=CleanupNxNxN(A2)
Any dimension values that are invalid will report False in column B and blank in Column C. Valid dimensions such as " 10. x 20X30 " would be reformatted as "10 x 20 x 30".
If you would like to allow extra "gibberish" before or after the dimensions, you could remove the "^" and "&" anchor characters from .Pattern, and get:
"approx. Size: 10*20*30 feet" would yield: True, "10 x 20 x 30"

Resources