I'd like to search a description cell for ANY words (criteria) from a predefined list, and pull the relevant dollar amount for the item from the adjacent cell.
To illustrate, here is my setup:
A | B | C | D | E | F |
Date | Descr.| Amount| Cat1 | Cat2 | Cat3 |
D,E,F: Each one of these are item categories. If the item in that row belongs to a category, I would like its amount to populate that category cell in that same row. Each category cell has a formula to test for this and perform the operation.
My first thought was to use VLookup, but I have a list of lookup values. I haven't been able to successfully do that. Each of the category cells has a formula like this -->
=IF(SUM(COUNTIF($B10,{"*costco*","*saputo*","*t & t*"}))>0,$C10," ")
Column B refers to the description, which is searched for any of the criteria. If any of the words are contained in the description, the cell is filled with the amount from column C, otherwise its left with a space.
This works perfectly as is, however I need the criteria (costco, saputo, t&t in this case) to be flexible (add or remove strings to the list) rather than hard-coded in the formula. This is my issue: the formula stops working if I replace the criteria with a reference to another cell. I'm relatively new to excel and not familiar with restrictions/constraints of its functions, which I suspect is the issue.
Any help is much appreciated, let me know if I need to provide more info.
Ankit
Create a Name (like a named range, but refers to a value rather than a range.)
For Excel 2007 and 2010, on the Formulas tab, Defined Names group, Name Manager
For Excel 2003 Insert, Names, Define
Create a new Name (lets use the name "KeyWords") , set it "Refers To" value to
={"*costco*","*saputo*","*t & t*"}
Formula then becomes EDIT enter as an array formula
=IF(SUM(COUNTIF($B10,KeyWords))>0,$C10," ")
Editing the list then becomes editing the value of KeyWords refers to value. This can be done through the Name Manager, or if you wish, through VBA
EDIT
Sample VBA
Sub SetKeyWords()
Dim wb As Workbook
Dim nm As Name
Set wb = ActiveWorkbook
Set nm = wb.Names("KeyWords")
nm.RefersTo = "={""NewString""}"
End Sub
Load the strings you are seeking into an array (via converting a range into an array, or having the user select the strings from a small form you design)
Sub MyLookup(arrCategories() As Variant)
Dim searchrange As Range
Dim xCell As Range
Dim count As Integer
'set searchrange to the proper column
For Each xCell In searchrange
For Each catg In arrCategories
If xCell = catg Then
'Do something here
End If
Next catg
Next xCell
End Sub
You may need to adjust your string array based on whether case matters. Depending on the size of your set of data, it might be better to convert searchrange into an array.
There may be a faster way to see if certain strings are found within a given range, but this is the general idea.
Related
I am currently looking to compare multiple Ranges in a specific order using VBA. The condition is to take Column A, compare it and identify matches within Column B. The specified adjacent cell to the left/right of the identified matches in column B, will then be considered column C, then compared and matched with column D. Finally the left/right adjacent cell to the identified matches in column D will be copied and pasted to a specified range in a separate sheet.
Snip01
https://1drv.ms/u/s!Ar3kJS7jPDiLgoh6QM6ZnFl_sjuZZQ
Snip02 https://1drv.ms/u/s!Ar3kJS7jPDiLgoh5zm1b2BozaT-0iw
Snip03 https://1drv.ms/u/s!Ar3kJS7jPDiLgoh4Ane8V1jZfoxbCA
Snip04 https://1drv.ms/u/s!Ar3kJS7jPDiLgoh3enh0OIUJ3m6BDA
Currently this is all I have written in VBA, and as you can probably tell, I am absolutely lost.
Sub MatchIt()
Dim Atlas As Range
Dim Atlas2 As Range
Dim Roster As Range
Dim Roster2 As Range
Dim Push As Range
Set Atlas = Range("D2")
Set Atlas2 = Range("M2")
Set Roster = Range("T2")
Set Roster2 = Range("S2")
Set Push = Range("AB2")
For Each cell In Push
If Push.Value = Roster2.Value Then
End Sub
I am mostly getting stumped on how to specify a cell relative to a previous result (hopefully I'm wording this correctly).
I would appreciate any help with this. Thank you.
I want to create a script to make a table to summarise which customer has spend the most money in my store. I have a database with unique names in column A, values in column H and other different data.
The core of the script should work like this:
Search for unique name
Sum all the cells from "KWOTA" column (H column)
Paste name and sum of range into the other sheet.
The problem is, I don't know which way should I take. I planned to search row by row for the names through Do Until...Loop method and - if the name is repeating - add corresponding value to a range. The problem is, it will be necessary to create multiple ranges, one for each name (I don't know how many unique names I have in database) and manipulate with them. I really wish to avoid 'Add to range" method.
Is there a possibility to do it in one script, without help of another worksheet to list all the unique names first?
You could consider using the Find and FindNext methods to locate the unique names and add the value from the H column until all the unique names have been found.
Hope I interpreted your question correctly.
Example format:
Sub Find()
Dim longSum As Long
Dim SearchRange As Range
Dim CellWithUniqueName As Range
Dim FirstUniqueCell As String
Worksheets("Sheet1").Activate
Set SearchRange = Range("A1", Range("A1").End(xlDown))
Set CellWithUniqueName = SearchRange.Find(What:="uniquename")
FirstUniqueCell = CellWithUniqueName.Address
Do
Set CellWithUniqueName = SearchRange.FindNext(CellWithUniqueName)
longSum = longSum + CellWithUniqueName.Offset(0, 7).Value
Loop While CellWithUniqueName.Address <> FirstUniqueCell
'whatever else for pasting etc
End Sub
Column D contains the substring to look for, which could be anywhere in the search field of column A. Column E contains the value to replace the content of column A with. See the results in Column B. Can anyone help me out?
After implementing suggested solution
If you are fine with it, I suggest a modification to the arrangement.
Arrange the lookup values as in the image, in columns F, G and H and the replace values in the next corresponding row. You would need 3 helper columns, (since you have 3 lookup values). Column B, C and D are helper columns.
Enter the below formula in column B, B1,
=IFERROR(IF(MATCH("*"&F$1&"*",$A1,0),F$2),"")
Just drag it to the bottom throughout the range, and then drag it to right upto column E.
Column F is your actual output. Enter the formula in column F,
=B1&C1&D1
and drag it down. Hope this helps. Let me know if you need anything else.
This works, but is not very elegant and won't easily scale.
=CONCATENATE(REPT($E$1,COUNTIF(A1,"*"&$D$1&"*")),REPT($E$2,COUNTIF(A1,"*"&$D$2&"*")),REPT($E$3,COUNTIF(A1,"*"&$D$3&"*")))
It's series of REPT(Replacement,COUNTIF(Values,*Labels*)). The *'s around the search allow it to be wildcard, essentially making the COUNTIF's flags of if the element is included or not. We then repeat the replacement value the number of times the countif is present (which in the example will always be 1), and then concatenate the results.
I have created a VB script to solve this:
Sub DetermineFeatures()
Dim featureLabel As String
Dim testString As String
testString = "FEAT_EMV_L4, Team_1, Team_IBM"
Dim stringValue As Variant
Dim lookupRange As Range
Set lookupRange = Worksheets("LookupTable").Range("A1:B100")
Dim outputWorksheet As Worksheet
Set outputWorksheet = Worksheets("Output")
Dim feature As String
Dim rowIndex As Long
For Each cell In Worksheets("Original").Columns("O").Cells
rowIndex = cell.Row
cellValue = WorksheetFunction.Trim(cell.Value)
For Each stringValue In Split(cellValue, ",")
If InStr(stringValue, "LABEL_") Then
featureLabel = Trim(stringValue)
' Call the Vlookup function to look up the actual feature name
for the supplied label. This
' returns the value from the second column of the range within
the LookupTable worksheet.
feature = Application.WorksheetFunction.VLookup(featureLabel,
lookupRange, 2, False)
outputWorksheet.Cells(rowIndex, 1) = feature
If Not IsEmpty(featureLabel) Then Exit For
End If
Next
Next cell
End Sub
I want to write a formula like =SUM(tab2!A:A) but instead use the column title of A which is say "count". How can I modify this to look more like: =SUM(tab2!"count")?
The reason I want to do this is because I copy and paste a spreadsheet from another source in tab2 and the column referring to "count" may be in a different column. I want the formula to give me the correct calculation as soon as I paste the new spreadsheet by automatically finding the column to sum up by title name.
I must be missing something because this seems like a very basic question and I can't find the answer anywhere...
Thanks for your help!
I like the idea of naming ranges proposed by #Doug, but if the issue is that you are dumping your data in [and you don't know in advance which column is going to be where] and would need to rename your range every time, there are other options - I suggest using OFFSET. OFFSET allows you to dynamically create a range, starting at a particular point and moving down/up / right/left for as many rows and columns as you determine.
In your case, you will need to combine that with a method for searching the columns to see which one says "Count". I am assuming that your column headings are always in row 1. If they aren't [or if they aren't always in row 2, or any row you know in advance]... you can get around that but then I'd recommend you try to make your data more uniform instead of creating unnecessary Excel workarounds.
In total your formula would look like this:
=SUM(OFFSET(A1,,MATCH("Count",1:1,0)-1,ROWS(A:A),1))
What this does is first determine which column the word "Count" is found in, in row 1. Then it subtracts 1 from that number - this now equals the number of columns to the right that it is, from column A. It uses offset to create a reference to that column, for all rows, and sums those rows together.
Check out the name manager for naming ranges :)
You didn't say whether you would consider a macro solution. If so, this may work.
If the sheet you are pasting into is Sheet2 and the sheet you want the result in is Sheet1, then this macro, if placed in the Worksheet_Activate event of Sheet1 will give you the result as soon as you click on the Sheet1 tab afetr pasting your data into Sheet2:
Private Sub Worksheet_Activate()
Dim r As Range
Dim rCol As Range
Dim rFound As Range
Dim ws As Worksheet
Dim lTotal As Long
Set ws = Sheet2
Set r = ws.Cells
Set rFound = r.Find("count")
If Not rFound Is Nothing Then
Set rCol = rFound.EntireColumn
lTotal = Application.WorksheetFunction.Sum(rCol)
End If
Cells(1, 1) = lTotal
End Sub
It does assume there is only one cell with the word "count" in it on Sheet2.
This question stems off another post I had. (see Search through column in excel for specific strings where the string is random in each cell)
Using the above image as reference, I am trying to search through column B (actually over 1000 lines) using column E as the "lookup values." The end goal would be for "just" the names to be displayed in column C. The trick is all the randomly generated characters the encompass the names. Below is what I would want the datasheet to look like. A formula or module should work, but the vlookup and other lookup function I can't get to work.
For a worksheet function approach, you could enter in C3 and fill down this formula:
=LOOKUP(8^5,SEARCH(E$3:E$7,B3),E$3:E$7)
The constant 8^5=32768 is chosen to be larger than the maximum possible string length so that LOOKUP returns the last matching value. The formula returns #N/A if no string is found.
Another possibility, which may be easier to understand then assylias post initially, but also may be a bit more time consumptive (although with 1,000 rows, I don't think it will matter much) is below.
This requires that you name the range in column E as myNames (or whatever name you wish, just update the code - alternatively, you cuold just write Range("E1:E6")). Also, if you move the random values from column B, update that in the code as well.
Sub findString()
Dim celString As Range, rngString As Range, celSearch As Range, rngSearch As Range
Dim wks As Worksheet
Set wks = Sheets("Sheet1") 'change sheet reference to whatever your sheet name is
Set rngString = wks.Range("myNames")
Set rngSearch = Intersect(wks.UsedRange, wks.Range("B1").EntireColumn)
For Each celString In rngString
For Each celSearch In rngSearch
If InStr(1, celSearch.Text, celString.Value) > 0 Then
celSearch.Offset(, 1) = celString.Value
End If
Next
Next
End Sub
Since, I worked on your original question as well, I would suggest getting the counts through Siddharth's answer and then running this, or assylias's code above to get the names next to the columns. You could put a button the sheet, or just use the Macro dialog box to run the macro.