Excel: search for information - excel

Guys I need to find specific information in text, and write them down in column.
So, I have Column L with Long Description, and I have Column M with words that I need to find in Long Description. When word has been found write that word in Column N at same row as Long Description.
I tried coding this one but ain't work.
=INDEX(M1:M4;MAX(IF(ISERROR(FIND(M1:M4;L1));-1,1)*(ROW(M1:M4)-ROW(M1)+1)))
This is sample of what I mean.. Pleaaase really need help.

This UDF should do the trick - I won't provide a detailed description of what it does beyond the comments you can see in it, as it's not very complex piece of code, but if there is something you don't understand in it, feel free to ask.
Option Explicit
Function find_keywords(cell_to_search As Range, range_of_keywords As Range) As String
Dim c As Range
' Check for the value of each cell in the range of keywords passed to the function
For Each c In range_of_keywords
' If the string-value we search for is in the cell we check against, we add it to the return-value
If InStr(1, cell_to_search.Text, c.Text, vbTextCompare) > 0 Then
' We don't want a comma before the first keyword we add, so check for the length of the return value
If Len(find_keywords) > 0 Then
find_keywords = find_keywords & ", "
End If
find_keywords = find_keywords & c.Text
End If
Next
End Function
You need to paste the code above into a module in your workbook, and then enter the formula into the cell you want the return-value to as normal:

Related

Convert vlookup to more than 255 characters via Excel VBA

I am looking for reverse vlookup with more than 255 characters in Excel VBA.
This is the formula based one which I took from this website.
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
I have try to convert it in VBA. Here below sample code
Sub test()
'concat
Range("i1") = WorksheetFunction.TextJoin(" ", True, Range("g1:h1"))
'lookup
Sal1 = Application.WorksheetFunction.Index(Sheets("sheet1").Range("a1:a2"), Application.WorksheetFunction.Match(True, Application.WorksheetFunction.Index(Sheets("sheet1").Range("i1:i1") = Range("i1").Value, 0), 0))
'=INDEX($W$3:$W$162,MATCH(TRUE,INDEX($W$3:$W$162=U3,0),0))
End Sub
It works well but it didn't when i change the range("i1:i1") to range("i1:i2")
I'm not sure what that worksheet formula does that =INDEX(F2:F11,MATCH(A2,D2:D11,FALSE)) doesn't do.
This part Index(Sheets("sheet1").Range("i1:i2") = Range("i1").Value, 0) is comparing a 2-d array to a single value, which should result in a Type Mismatch error. Whenever you reference a multi-cell range's Value property (Value is the default property in this context), you get a 2-d array even if the range is a single column or row.
You could fix that problem with Application.WorksheetFunction.Transpose(Range("D1:D10")) to turn it into a 1-d array, but I still don't think you can compare a 1-d array to a single value and have it return something that's suitable for passing into INDEX.
You could use VBA to create the array's of Trues and Falses, but if you're going to go to that trouble, you should just use VBA to do the whole thing and ditch the WorksheetFunction approach.
I couldn't get it to work when comparing a single cell to a single cell like you said it did.
Here's one way to reproduce the formula
Public Sub test()
Dim rFound As Range
'find A2 in D
Set rFound = Sheet1.Range("D1:D10").Find(Sheet1.Range("A2").Value, , xlValues, xlWhole)
If Not rFound Is Nothing Then
MsgBox rFound.Offset(0, 2).Value 'read column f - same position as d
End If
End Sub
If that simpler formula works and you want to use WorksheetFunction, it would look like this
Public Sub test2()
Dim wf As WorksheetFunction
Set wf = Application.WorksheetFunction
MsgBox wf.Index(Sheet1.Range("F2:F11"), wf.Match(Sheet1.Range("A2").Value, Sheet1.Range("D2:D11"), False))
End Sub
Function betterSearch(searchCell, A As Range, B As Range)
For Each cell In A
If cell.Value = searchCell Then
betterSearch = B.Cells(cell.Row, 1)
Exit For
End If
betterSearch = "Not found"
Next
End Function
i found this code from above link and it is useful for my current search.Below examples i try to get value..
Kindly consider Row 1 to 5 as empty for A and B column because my table always start from Row 6
Row
A Column
B Column
6
54
a
7
55
b
8
56
c
VBA Code:
Sub look_up ()
Ref = "b"
look_up = betterSearch(Ref, Range("B6:B8"), Range("A6:A8"))
End Sub
it show Empty while use Range("B6:B8"), Range("A6:A8")
but when changing the range from B6 and A6 to B1 and A1 (Range("B1:B8"), Range("A1:A8") )it gives the value...
My question is "can get the values from desired range"
Expressing matches via VBA
I like to know if there (are) any possibilities to convert this formula.
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
So "reverse VLookUp" in title simply meant to express the (single) formula result via VBA (btw I sticked to the cell references in OP, as you mention different range addresses in comments).
This can be done by simple evaluation to give you a starting idea:
'0) define formula string
Dim BaseFormula As String
BaseFormula = "=INDEX($F$2:$F$10,MATCH(TRUE,INDEX($D$2:$D$10=$A2,0),0))"
'1) display single result in VB Editor's immediate
Dim result
result = Evaluate(BaseFormula)
Debug.Print IIf(IsError(result), "Not found!", result)
On the other hand it seems that you have the intention to extend the search string range
from A2 to more inputs (e.g. till cell A4). The base formula wouldn't return a results array with this formula,
but you could procede as follows by copying the start formula over e.g. 3 rows (note the relative address ...=$A2 to allow a row incremention in the next rows):
'0) define formula string
Dim BaseFormula As String
BaseFormula = "=INDEX($F$2:$F$10,MATCH(TRUE,INDEX($D$2:$D$10=$A1,0),0))"
'2) write result(s) to any (starting) target cell
'a)Enter formulae extending search cells over e.g. 3 rows (i.e. from $A2 to $A4)
Sheet3.Range("H2").Resize(3).Formula2 = BaseFormula
'b) optional overwriting all formulae, if you prefer values instead
'Sheet3.Range("H2").Resize(3).Value = Tabelle3.Range("G14").Resize(3).Value
Of course you can modify the formula string by any dynamic replacements (e.g. via property .Address(True,True,External:=True) applied to some predefined ranges to obtain absolute fully qualified references in this example).
Some explanations to the used formulae
The formula in the cited link
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
describes a way to avoid an inevitable #NA error when matching strings with more than 255 characters directly.
Basically it is "looking up A2 in D2:D10 and returning a result from F2:F10" similar to the (failing) direct approach in such cases:
=INDEX(F2:F11,MATCH(A2,D2:D11,FALSE))
The trick is to offer a set of True|False elements (INDEX(D2:D10=A2,0))
which can be matched eventually without problems for an occurence of True.
Full power by Excel/MS 365
If, however you dispose of Excel/MS 365 you might even use the following much simpler function instead
and profit from the dynamic display of results in a so called spill range.
That means that matches can be based not only on one search string, but on several ones (e.g. A1:A2),
what seems to solve your additional issue (c.f. last sentence in OP) to extend the the search range as well.
=XLOOKUP(A1:A2,D2:D10,F2:F10,"Not found")

Looping and scanning a list of e.g., 200 strings against a column with string data (Excel, VBA, Macros)

To the best of my efforts (VBA novice) I have been trying to write using stack and other resources a macro which would allow me to scan a given list of strings in excel against another much larger list for possible partial matches (Vlookup seems not to do a trick and Instr is a lot better for this it seems). I have been able to get some code working which leverages a loop to scan through a specific range and look for a single string of interest. For example let's say I have 20 cells in Column C with various names of fruits and vegetables and I would like to highlight only specifc ones of interest for me. In the code's case below I have included a string "Cher" (for Cherry) to be searched for against the range which if found creates a hit to the right of the column searched.
My major question would be how to adjust the code so that I could not only search for a single string like "Cherry", but how to run it against a very long list e.g. of 200 items when dealing with a couple of thousands of rows of data?
Sub listchecker()
Dim cell As Range
For Each cell In Range("C2:C20")
If InStr(cell.Value, "Cher") > 0 Then
cell.Offset(0, 1).Value = cell.Value
End If
Next cell
End Sub
Thank you in advance for anyone's help!
Thank you NautMeg and SRJ for the suggestions below. I did adjust the code and it seems to be working now against an array as noted below (hooray)
Dim wordsArray() As Variant
wordsArray = Worksheets("Keywords").Range("B2:B439").Value
Dim word As Variant
Dim cell As Range
For Each cell In Worksheets("Normalized").Range("J2:J49010")
For Each word In wordsArray
If InStr(cell.Value, word) > 0 Then
cell.Offset(0, -1).Value = cell.Value
End If
Next word
Next cell
The only thing I realized now though is that it would be better for 'cell.Offset(0, -1).Value = cell.Value' actually to populate with the array match (the keyword) rather than the cell's value. This is because the keyword might be too broad or too generic and result in false positives. Returning the cells value instead of the match from the array makes life more difficult to troubleshoot/identify a bad broad/generic keyword e.g., ("is").
as SJR mentions above you could store the 200 search items in an array and then amend your code to something like the following:
Dim cell As Range
For Each cell In Range("C2:C20")
'// Add Another For Loop here to loop through your words array
For Each wrd in wordsArray
If InStr(cell.Value, wrd) > 0 Then
cell.Offset(0, 1).Value = cell.Value
End If
Next word
Next cell
End Sub
Possible issue with this kind of search is that it will pick up the first match, for example a search for "mang" could turn up "mango" or "mangetout" depending on which item comes up in the list first. This may or may not be desirable but something to look out for.

macro in VBA to get prefixes

in my job I have very often to create prefixes. Since last week I think that I can do faster my job with a Macro in excel, but I never have developed in VBA before and need your help.
We get a list with article numbers from any supplier and then I have to create the prefixes for our System. Our System is looking for the prefix and then it knows the supplier. If the first 6 chars are exactly the same with another supplier, so the prefixes from both supplier is getting longer to 7 chars. If it's the same again, the prefix is getting an eight char and so on.
Example:
article numbers from supplier_1:
04012384724993
04012384473373
04012384111453
...
article numbers from supplier_2:
12345671846219
12345629946120
12345629815294
...
article numbers from supplier_3:
12345694724109
12345694715268
12345694724773
...
Now you see that first chars from each supplier are the same.
For Supplier_1 all numbers beginning with "040123", so that's the first prefix.
Supplier_2 ans 3 have the same first 6 chars, so here we use one more to identificate him.
Supp_2 -> "1234567" and "1234562"
Supp_3 -> "1234569"
Supplier_2 have now 2 prefixes, because the 7th position is different in some article numbers, but not the same like supplier_3 is using at this position.
Now I have an excel sheet with column A and B.
In column A I paste all article numbers from supplier_1 and in column B I paste these from supplier_2.
Now I want to run a macro, that create a variable "search" with the first 6 chars from Cell A1 and check it against Column B. If one of the numbers in Column B is the same then variable "search" get additional the next char from Cell A1 and check again. If now the first 7 chars couldn't be found in Column B, it's the first prefix from supplier_1. I want to paste it into column D.
Now the variale "search" get the first 6 chars from the next Cell in column A, (A2), later A3, ... and check it against Column B.
I don't know, how to get the first 6 chars into the variable "search".
Can someone help me please?
Thank you very much.
It is always a good idea to approach big problems in as small chunks as possible. Indeed, it may be a good start to assign the first few characters of a string to a variable. A quick Google search would most likely point you to the Left function. Here's a link to the MSDN page for more information on how it works and how to use it.
I also suggest that you enable the Immediate Window, which can be done with Ctrl + G by default. Using Debug.Print will be one of your strongest tools while writing new code.
Sub Example1()
Dim searchRange As Range
Dim search As String
Set searchRange = ThisWorkbook.Worksheets("Sheet1").Range("A1")
search = Left(searchRange.Value, 6)
Debug.Print search
End Sub
Here's a snippet to give you an idea of how you might go about solving the next step of the problem.
Sub Example2()
Dim compareRange As Range
Dim cell As Range
' SpecialCells is one of many ways to find all populated cells
Set compareRange = ThisWorkbook.Worksheets("Sheet1").Columns(2) _
.SpecialCells(xlCellTypeConstants)
For Each cell In compareRange
Debug.Print cell.Value
Next
End Sub
Please remember that StackOverflow is here to help with specific coding problems that you can't get over with the resources you can find online.
I had some difficulty deciphering exactly what you needed but here is what I have come up with.
I am going to assume that you know how to insert a module into your excel spreadsheet, copy code, and run a macro. If you do not know how please let me know and I will try to assist further.
If this is not what you need please provide me with a sample data set and the answers that you would like to get from the macro so that I can compare as I develop. Best of luck with your projects!
VBA module code
'This subroutine will take the contents of column A cells and search column B for matching digits
' if they are not found it will copy the current search term into column D
Option Explicit
Sub searchPrefix()
Dim cellContents As String
Dim tempSearchVariable As String
Dim isFound As Boolean
Dim quantitySearchCharacters As Integer
Dim entryCounter As Integer
Dim i As Integer
isFound = False
quantitySearchCharacters = 6
entryCounter = 0
'counts number of entries in column A
Cells.Range("A1").Select
Do Until IsEmpty(ActiveCell)
entryCounter = entryCounter + 1
ActiveCell.Offset(1, 0).Select
Loop
' gets value of comparison cell in column A
For i = 0 To entryCounter - 1
cellContents = Cells(1 + i, 1).Value
tempSearchVariable = Left(cellContents, quantitySearchCharacters)
Cells.Range("B1").Select
Do Until IsEmpty(ActiveCell)
' detects if B1 column cell content matches the current search terms and then adds more characters if required
If Left(ActiveCell.Value, quantitySearchCharacters) = tempSearchVariable Then
quantitySearchCharacters = quantitySearchCharacters + 1
tempSearchVariable = Left(cellContents, quantitySearchCharacters)
isFound = True
End If
If isFound Then
isFound = False 'reset flag
Cells.Range("B1").Select
Else
ActiveCell.Offset(1, 0).Select
End If
Loop
Cells(1 + i, 4).Value = tempSearchVariable ' prints the discovered unique prefix to column D
Next i
End Sub

Search and Replace random cell text by first :

I have a slew of rows (100K+) to search and modify the contents.
For example the cells contain similiar text as DGC9610411:DB:10:82
All of this text can change per row except that fact that the : means something to me.
In this and every other row, i need to remove the first : and all the text after so that the cell would look like this DGC9610411
Next I will be adding the contents of another cell to the end. I think that will be an easy step and I could most likely figure that out without much effort.
I have this code in a while loop for each row. so the code is looking at one row at a time.
I have searched but everyone seems to have a different set of needs.
Just use Find and Replace, no need for vba or formulas.
Select the column containing the data that you need to modify
Press Ctrlh to open the Find and Replace dialog.
In the "Find what:" field, type :*
In the "Replace with:" field, leave it blank
Click Replace All
EDIT: If it has to be VBA, this simple macro will accomplish the same thing. Be sure to change the A to your actual column letter.
Sub tgr()
Columns("A").Replace ":*", ""
End Sub
EDIT: Upon request I am adding a formula solution. In cell B1 and copied down:
=LEFT(A1,FIND(":",A1&":")-1)
Try this small macro:
Sub colonoscopy()
Dim c As String
Dim r As Range, I As Long
For Each r In ActiveSheet.UsedRange
v = r.Value
I = InStr(1, v, ":")
If I > 0 Then
r.Value = Mid(v, 1, I - 1)
End If
Next r
End Sub

Get in column B the words of column A that are `not in dictionary`

How could I create a macro that would check each cell of column A, find the words that are not in the defined dictionary, and write them (separated by space) in the next cell. In the picture below you can see an example of the worksheet after that macro was completed.
The complete idea was to get a (varchar) column from a database and use excel to spell check it. The next step would be to send an e-mail to the user in charge, containing the rows that contain at least one word in column B (along with the column id, of course). I think that I could do the rest of the work, except this step of getting the erroneous words. If you can think of another idea to spell check a db column, I would be grateful if you shared it with me. Thanks.
You can use VBA to call the built-in Office dictionary using Application.CheckSpelling
This is the syntax:
Function CheckSpelling(Word As String, [CustomDictionary], [IgnoreUppercase]) As Boolean
... and here is an example that meets your requirements:
Option Explicit
Public Sub Checker()
Dim s As Variant
Dim sArray As Variant
Dim lCurrRow As Long
Dim lStartRow As Long
Dim lEndRow As Long
lStartRow = 1
lEndRow = 5
Application.ScreenUpdating = False
With ThisWorkbook.Worksheets(1)
'Clear existing data in Column B
Call .Columns(2).ClearContents
For lCurrRow = lStartRow To lEndRow
'Populate an Array, splitting the song title at the spaces
sArray = Split(.Cells(lCurrRow, 1).Text, " ")
'Loop through each word in the Array
For Each s In sArray
'Spell Check against the main MS Office dictionary
If Not Application.CheckSpelling(s) Then
'this word is missing, output to Column B:
.Cells(lCurrRow, 2).Value = Trim(.Cells(lCurrRow, 2).Value & " " & s)
End If
Next s
Next lCurrRow
End With
Application.ScreenUpdating = True
End Sub
Don't do this
This is a crazy idea. Excel is not the right tool for this.
Having said that, it might be doable.
First you will have to split the 'sentences' into words. This can be done using VBA into a separate sheet.
Then you can check whether each word exists using COUNTIF or VLOOKUP. For instance if you have a sheet called dictionary containing all valid words in alphabetical order (in the first column), the most efficient way would be =IF(VLOOKUP(B2;dictionary!A:A;1)<>B2;B2;"") for a word in B2.
Then you can concatenate the resulting cells for each sentence, or just find the first one (using VLOOKUP again, now with an extra argument FALSE).
But... Just forget it!

Resources