VBA HasNextCell function - excel

I have tried searching for a solution but cant find it.
I have a list of products, and each product has many parts. Is there a HasNext function in VBA to see if there are more parts for a product? For instance, for chicken burger, I want to pick out all the parts, put them in an array and display it in another sheet.
I cant hard-code the array, because the client would add in more products in the future. There might be 15, 20, 23 parts etc. Is there a HasNext function to get the value in the next column and add it into the array?
Product | Part 1 | Part 2 | Part 3
Chicken Burger | Veggie | Bun | Patty

You can use Range.End property to detect how "long" the title row is:
Dim col
col=Range("A1").End(xlToRight).Column
For i = 1 to col
If Cells(1, col).Value <> "" Then
'...
End
P.S. I wonder why MSDN refers to it as "property" instead of "method"...

Related

Excel Formula - Match substrings of List to List

I have two Lists in an excel spreadsheet.
The first list has strings such as
1234 blue 6 abc
xyz blue/white 1234
abc yellow 123
The other list contains substrings of the first list
yellow
blue/white
blue
Result
1234 blue 6 abc blue
xyz blue/white 1234 blue/white
abc yellow 123 yellow
Now I need some kind of match formula to assign the correct value from the second list to the first. The problem, there is no specific pattern to determine where the color substring is positioned. The other problem, the values are not totally unique. As my example above shows, the lookup needs to be in an order (checking for "blue/white" before checking for "blue").
I played around the formulas like match, find also using wildcards * but couldn't come to any result.
A similar question asked here on SO covers the opposite case How to find if substring exists in a list of strings (and return full value in list if so)
Any help is appriciated. A formula would be cool, but using vba is also okay.
=INDEX(D$7:D$9, AGGREGATE(15, 7, ROW($1:$3)/ISNUMBER(SEARCH(D$7:D$9, A2)), 1))
Here is a solution with VBA
List 1 (strings) is in column A
List 2 (substrings) is in column C
The code basically contains to nested while loops checking whether the substring is inside the string.
row_1 = 1
While .Cells(row_1, "A") <> ""
row_2 = 1
While .Cells(row_2, "C") <> ""
color = .Cells(row_2, "C").Value
If InStr(1, .Cells(row_1, "A"), color, vbBinaryCompare) > 0 Then
.Cells(row_1, "B") = color
End If
row_2 = row_2 + 1
Wend
row_1 = row_1 + 1
Wend

Count or Sum (?) items in a single cell that match criteria from a list in Excel

I have a single cell that is the output of a survey, that contains items selected from a list of 20 possible items.
ie.
Original possible selections:
Ape, Blue, Cat, Red, Dog, Yellow, Pig, Purple, Zebra
User is asked to "select all of the animals," from the list of possible selections. The output places all of the items they've identified into a single cell, separated by commas.
A new row is created for each survey entry.
ie.
| User 1 | "Ape, Cat, Pig, Purple" |
| User 2 | "Cat, Red, Dog, Pig, Zebra" |
| User 3 | "Ape, Cat, Dog, Pig, Zebra" |
etc...
I have a table with all of the animals and colors, with defined ranges.
ie. animals = A1:A5, and colours = B1:B4
I need to "score" the cell for each user, in a new cell. Where the score value is the count of the number of correctly identified items each counts as 1 point.
ie.
| User 1 | "Ape, Cat, Pig, Purple" | 3 |
| User 2 | "Cat, Red, Dog, Pig, Zebra" | 4 |
| User 3 | "Ape, Cat, Dog, Pig, Zebra" | 5 |
What would the formula need to be for that score cell for each row?
I found a previous thread, that seems to point in the right direction,
Excel: Searching for multiple terms in a cell
But this only checks for the existence of any of the items in a cell from a list and returns a true or false
Thanks for anyone's help!
COUNTIF with SUMPRODUCT:
=SUMPRODUCT(COUNTIF(D2,"*" & $A$1:$A$5 & "*"))
Which also has the limitation of the amimals not being a sub-string, like Ant and Ant-Eater
If sub-strings are a problem then use this:
=SUMPRODUCT(--(ISNUMBER(SEARCH(", " & $A$1:$A$5 & ", ",", " & D2 & ", "))))
This will make a complete match between the commas.
The formula shown is entered in D3 (an array formula, so use Ctrl+Shift+Enter) and filled down to D5
A3:A6 is a named range "animals"
Note this is only reliable if none of your terms are sub-strings of another term.
If you do not like to use the formulas above, which are very efficient and most ideal, a simpler but longer way would be as follows:
select the animals--> Data--> Text to Columns, and split them into columns with the separator being a comma
Once this is done, do a countif on each column, and it will total it up for you. You will need to do 20 countifs though, so it is far from ideal
IE
=countifs(column which it could be in],[no.1 animal])+
countifs(column which it could be in],[no.2 animal])+...
countifs(column which it could be in],[no.20 animal])
This is easy to see how it works and if you receive more answers you will have to split them out again

Excel non-uniform data extraction

I've had a really hard time tracking down a solution for this--though I'm sure it's out there. Just not sure of the exact wording to get what I'm looking for.
I have a huge data set where some of the data is missing information so it is not uniform. I want to extract just the name into one column and the e-mail in to the next column.
The best way I can narrow this down is there is a space between each unique entry with the name always being in the first box.
Example:
John Doe
John Doe's Company
(555) 555-5555
John.doe#johndoe.com
John Doe
(555) 555-5555
John Doe
Jane Doe's Company
John.doe#johndoe.com
With the results wanted being (in two excel columns):
John Doe | john.doe#johndoe.com
John Doe |
John Doe | john.doe#johndoe.com
Any suggestions on the best way to do this would be appreciated it. To make it complicated if there was no e-mail I would want to ignore that set completely, but I could just manually check.
VBA coding:
1. Indicate in Row1 the initial row where the data begins.
2. Place a flag in this case the word "end" to indicate the end of the information.
3. Create a second sheet
Sub ToList()
Row1 = 1 'Row initial from data
Row2 = 1 'Row initial to put list
Do
Name = False
Do
field = Trim(Sheets(1).Cells(Row1, 1))
If field <> "" And LCase(field) <> "end" And Not Name Then
Sheets(2).Cells(Row2, 1) = field
Name = True
End If
Row1 = Row1 + 1
Loop Until (IIf(field = "" Or LCase(field) = "end", True, False))
fieldprev = Sheets(1).Cells(Row1 - 2, 1)
If InStr(fieldprev, "#") > 0 Then
Sheets(2).Cells(Row2, 2) = fieldprev
End If
Row2 = Row2 + 1
Loop Until (IIf(LCase(field) = "end", True, False))
End Sub
Extracting the e-mail address shouldn't be too difficult as you just need to is search for a string containing the # character. A series of search() and mid() functions can be used to separate out the individual words. Search for each instance of a space and use that value in a mid() function. Then search for # in the results and you should find the e-mail address. Extracting the name will be more difficult if the original data is very messy.
However I second the comment above about using an external script, especially for a large dataset. Excel isn't really designed for the sort of thing you are describing here.

Separating Data in the same excel column

I have a column of data with multiple value types in it. I am trying to separate out out each value type into a separate column. Below an example of the data:
6 - Cutler, Jay (Ovr: 83)
22 - Forte, Matt (Ovr: 88)
86 - Miller, Zach (Ovr: 80)
I tried to separate the data by a) going to data and clicking text to columns; however, the "Ovr: 80" portion of the data does not separate "Ovr" from 80. I also tried b) to convert to .csv file, but again was unable to separate "Ovr" from "80". Is there a formula I can use to separate this portion of the data from the rest?
I would like the data to be separated into different columns as show below:
6 | Cutler, | Jay | Ovr | 83
22 | Forte | Matt | Ovr | 88
86 | Miller | Zach | Ovr | 80
Any insight is much appreciated!
Select the cells you wish to process and run this macro to place results in the cells to the right of the selected cells:
Option Explicit
Sub dural()
Dim r As Range, s As String, ary
Dim i As Long, a
For Each r In Selection
s = r.Value
If s <> "" Then
s = Replace(Replace(s, "-", " "), ",", " ")
s = Replace(Replace(s, "(", " "), ")", " ")
s = Application.WorksheetFunction.Trim(Replace(s, ":", " "))
ary = Split(s, " ")
i = 1
For Each a In ary
r.Offset(0, i).Value = a
i = i + 1
Next a
End If
Next r
End Sub
using the method above your could do something like this...
first clean the text so its more manageable, using this formula and copying in a column you can clean it so it become a space delimited set
=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1,"- ",""),",",""),"(",""),")",""),":","")
from there just copy the values the formula give you to a new sheet maybe and then use 'Text To Columns to get it split into columns.
For the record I do not recommend this method if you are willing to do the text to column option.
Functions used for this solution are:
LEFT function
FIND function
MID function
for your first column of text use the following:
=left(A1,find(" ",A1))*1
That will pull out the first number presuming you do not have any leading spaces. The *1 converts from text to a number.
for your second column of last times use the following:
=MID(A1,FIND("-",A1)+2,FIND(",",A1)-(FIND("-",A1)+2))
Provided you have a coma and a dash as indicated in your example data you will not get an error and it should pull the last name without the coma.
For your third column of first names follow the same general technique as last names with the following,
=MID(A1,FIND(",",A1)+2,FIND("(",A1)-2-(FIND(",",A1)+2)+1)
Follow the similar pattern to get you over column
=MID(A1,FIND("(",A1)+1,FIND(":",A1)-1-(FIND("(",A1)+1)+1)
and finally to get your age column use this:
=MID(A1,FIND(":",A1)+2,FIND(")",A1)-1-(FIND(":",A1)+2)+1)
copy the above formulas down as far as you need to go.

Changing .Interior.ColorIndex has no effect

In Excel 2003, when I change Series.Interior.ColorIndex to a value I need, it has no effect. It has an effect only when I first manually change color and then run the macro. Apparently this triggers some update mechanism. Does anyone have an explanation for this? Is there a way to somehow trigger this in the chart?.. I.e. make sure that the color changes take effect.
In addition, when I step through the code and watch ColorIndex, it does not change even after value is assigned. Is this one of the many bugs in Excel?
The code looks like this:
Sub DoStuff()
Dim j As Long
For j = 1 To ActiveChart.SeriesCollection.Count
With ActiveChart.SeriesCollection(j)
Select Case ActiveChart.SeriesCollection(j).Name
Case "Milk"
.Interior.ColorIndex = 4
Case "Cookies"
.Interior.ColorIndex = 28
Case "Honey"
.Interior.ColorIndex = 26
End Select
End With
Next j
End Sub
Edit: I am working with bar chart.
Try setting the border as well.
.Interior.ColorIndex = 4
.Border.ColorIndex = 4
.Border.Weight = xlMedium
Edit: In response to comments & edits to the original question:
I laid out an example Excel file, and I was able to get your code to work. Here is how my data is laid out:
| A | B | C | D |
--------------------------------
1 | Milk | 3 | 1 | 4 |
2 | Cookies | 1 | 5 | 9 |
3 | Honey | 2 | 6 | 5 |
And the bar graph looks something like this:
._.
|C|
._.._. |C|._.
._. ._. |C||H| ._.|C||H|
|M|._.|H| ._.|C||H| |M||C||H|
|M||C||H| |M||C||H| |M||C||H|
---------------------------------
1 2 3
Where all of the bars labeled "M" in the above diagram belong to the "Milk" series, all of the bars labeled "C" belong to the "Cookies" series, and all of the bars labeled "H" belong to the "Honey" series.
When I run your code on this chart, the bar colors are changed as expected. Can you tell me what is different between my setup and yours? I'll try to figure it out, but I need more information :)
probably a bug in Excel, which version of Excel are you using?
make sure you service pack/patch it and try again to reproduce the problem.
I had the same problem, using excel 2007 and 2003.
But i fixed it by opening the workbook in 2003, then formatting the data series by right-clicking (etc) and setting it's fill color to Automatic. then when i ran my macro, the colorindex setting part would take hold.

Resources