Find all other cells with same adjacent element - excel-formula

I have an excel spreadhseet with the following columns
A: City
B: State
C: Other cities that are in the same state as column A
For example, the result may look like this:
City State Other cities in State
--------------------------------------------------------------
Philadelphia Pennsylvania Pitsburgh
Pitsburgh Pennsylvania Philadelphia
San Diego California Palo Alto, Mountain View, LA, San Jose, Houston
Palo Alto California San Jose, Mountain View, San Diego
Mountain View California San Jose, LA, Palo Alto, San Diego
LA California San Jose, Mountain View, Palo Alto, San Diego
San Jose California LA, Mountain View, Palo Alto, San Diego
Austin Texas Houston, Dallas
Houston Texas Austin, Dallas
Dallas Texas Dallas, Houston
What formula could I use to generate the 'other cities in state' column?

Ragged edge string concatenation is difficult using Excel worksheet functions; even with the new Excel 2016/Office 365/Excel Online CONCAT and TEXTJOIN functions¹.
A well written UDF² can easily overcome the limitations.
Module1 code sheet
Option Explicit
Function CITYJOIN(rst As Range, sst As String, rct As Range, _
Optional sct As String = "", _
Optional bIncludeSelf As Boolean = False, _
Optional delim As String = ", ")
Dim r As Long
Static dict As Object
If dict Is Nothing Then
Set dict = CreateObject("Scripting.Dictionary")
dict.compareMode = vbTextCompare
End If
dict.RemoveAll
'truncate any full column references to the .UsedRange
Set rst = Intersect(rst, rst.Parent.UsedRange)
'set the cities to the same size as the states
Set rct = rct.Resize(rst.Rows.Count, rst.Columns.Count)
'loop through the cells to create unique dictionary keys
For r = 1 To rst.Cells.Count
If LCase(rst(r).Value2) = LCase(sst) Then
dict.Item(StrConv(rct(r).Value2, vbProperCase)) = vbNullString
End If
Next r
'get rid of 'self-city'
If Not bIncludeSelf Then
dict.Remove sct
End If
'return a delimited string
CITYJOIN = Join(dict.keys, delim)
End Function
      
The optional city (e.g. sct ) is only optional if you choose to include the city on the same row. By default the city on the same row is excluded and must be supplied as a parameter in order to remove it.
The static dict object means that you will only create the Scripting.Dictionary object once. The same object is used for subsequent calls to the function. This is particularly useful when filling down a long column with a formula containing this UDF.
¹ excel-2016 See What's new in Excel 2016 for Windows for more information.
² A User Defined Function (aka UDF) is placed into a standard module code sheet. Tap Alt+F11 and when the VBE opens, immediately use the pull-down menus to Insert ► Module (Alt+I,M). Paste the function code into the new module code sheet titled something like Book1 - Module1 (Code). Tap Alt+Q to return to your worksheet(s).

Related

Proper syntax for calling a particular UDF

This has reference to SO question Find all other cells with same adjacent element and data reproduced below to avoid cross reference.
I have an excel spreadsheet with the following columns
• A: City
• B: State
• C: Other cities that are in the same state as column A
For example, the result may look like this:
City
State
Other cities in State
Philadelphia
Pennsylvania
Pitsburgh
Pitsburgh
Pennsylvania
Philadelphia
San Diego
California
Palo Alto, Mountain View, LA, San Jose, Houston
Palo Alto
California
San Jose, Mountain View, San Diego
Mountain View
California
San Jose, LA, Palo Alto, San Diego
LA
California
San Jose, Mountain View, Palo Alto, San Diego
San Jose
California
LA, Mountain View, Palo Alto, San Diego
Austin
Texas
Houston, Dallas
Houston
Texas
Austin, Dallas
Dallas
Texas
Dallas, Houston
It was answered by user4039065 who advised to use an UDF and the code is as follows.
Option Explicit
Function CITYJOIN(rst As Range, sst As String, rct As Range, _
Optional sct As String = "", _
Optional bIncludeSelf As Boolean = False, _
Optional delim As String = ", ")
Dim r As Long
Static dict As Object
If dict Is Nothing Then
Set dict = CreateObject("Scripting.Dictionary")
dict.compareMode = vbTextCompare
End If
dict.RemoveAll
'truncate any full column references to the .UsedRange
Set rst = Intersect(rst, rst.Parent.UsedRange)
'set the cities to the same size as the states
Set rct = rct.Resize(rst.Rows.Count, rst.Columns.Count)
'loop through the cells to create unique dictionary keys
For r = 1 To rst.Cells.Count
If LCase(rst(r).Value2) = LCase(sst) Then
dict.Item(StrConv(rct(r).Value2, vbProperCase)) = vbNullString
End If
Next r
'get rid of 'self-city'
If Not bIncludeSelf Then
dict.Remove sct
End If
'return a delimited string
CITYJOIN = Join(dict.keys, delim)
End Function
It gives correct answer when used in worksheet as per following formula.
=CITYJOIN(B:B,B2,A:A,A2)
My level in VBA is elementary and I want to understand the Function code fully by stepping through the code using F8 key. With this in view I coded the following Test sub.
Sub test()
Call CITYJOIN("B: B", B2, "A: A", A2)
'CITYJOIN B: B , B2, A: A , A2
End Sub
I am getting an error at the following line in Function code stating compiler error.
CITYJOIN = Join(dict.keys, delim)
Can someone help me and provide proper code of test sub explaining the mistake in the above code of test sub.
Thanks
Please, call the function in this way:
Sub test()
Debug.print CITYJOIN(Range("B:B"), Range("B2").value, Range("A:A"), Range("A2").value)
End Sub
And see the result in Immediate Window (Ctrl + G being in VBE (Visual Basic for Applications Editor).

Excel validation dropdown long list

Does excel dropdown validation list have a limit.
Trying to put the list of states but it doesn't show all of them:
Source: Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware, District of Columbia, Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana, Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana, Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina, North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina, South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia, Wisconsin, Wyoming
Place all 50 States in a column (you can hide the column), then allow a List and select the cells with the States
Put the list in a worksheet and reference that instead of putting the list in manually:
There are limits to the number of items that will show in a data validation drop down list:
The list can show up to show 32,767 items from a list on the worksheet.
If you type the items into the data validation dialog box (a delimited list), the limit is 256 characters, including the separators.
From http://www.contextures.com/xlDataVal08.html#itemlimit

Unable to seperate the STRING in EXCEL in the desired way as it contains more than one ","

The first column is written manually and I want the rest to be automated using the functions MID and FIND, if possible.
If not then by using any other functions.
I am using Excel 2016.
Screenshot of the problem in Excel:
The data to test:-
911 FORRESTAL DR, ARLINGTON, TX 76010
92 4th Street North, Providence, RI 02904
405 Fieldstone Drive, Dawsonville, GA 30534
551 Franklin Street, Circle Pines, MN 55014
545 Ashley Court, Fort Walton Beach, FL 32547
B1 = =LEFT(A1,FIND(",",A1)-1)
C1 = =MID(A1,FIND(",",A1)+2,FIND(",",A1,FIND(",",A1)+1)-FIND(",",A1)-2)
D1 = =MID(A1,FIND(",",A1,FIND(",",A1)+1)+2,2)
E1 = =RIGHT(A1,5)
fully tested against your sample data

Categorize single column of text into multiple columns

I am trying to create a macro that will categorize data in one column into multiple columns based on the item type. The data I am trying to categorize is a list of contracts with meta-data on the items in the contract.
The raw data looks like this:
Contract No Contract Name Item Type Item Description
111111 Chocolate Supplies POTS 5"
111111 Chocolate Supplies POTS 10"
111111 Chocolate Supplies POTS 15"
111111 Chocolate Supplies PANS 5"
111111 Chocolate Supplies PANS 10"
111111 Chocolate Supplies PANS 15"
111111 Chocolate Supplies KNIVES Paring knife
111111 Chocolate Supplies SILVERWARE Salad fork
111111 Chocolate Supplies SILVERWARE Dinner fork
111111 Chocolate Supplies SILVERWARE Dessert fork
111111 Chocolate Supplies SILVERWARE Dessert spoon
111111 Chocolate Supplies SILVERWARE Soup spoon
22222 Soups and Salads Order POTS 10"
22222 Soups and Salads Order POTS 15"
22222 Soups and Salads Order PANS 15"
22222 Soups and Salads Order KNIVES Butter knife
22222 Soups and Salads Order KNIVES Bread knife
22222 Soups and Salads Order KNIVES Paring knife
22222 Soups and Salads Order SILVERWARE Soup spoon
The final data needs to look like this (edited to include image):
Contract Contract Name POTS PANS KNIVES SILVERWARE
111111 Chocolate Supplies 5" 5" Paring knife Salad fork
10" 10" Dinner fork
15" 15" Dessert fork
Dessert spoon
Soup spoon
22222 Soups and Salads Order 10" 15" Butter knife Soup spoon
15" Bread knife
Paring knife
# What I've tried so far #
The current crude solution I am using is to:
- Run the query
- Paste the data into excel
- Create a pivot
- Use a series of count, offset and indirect formulas to reorganize the data as needed
- Since the above process leaves empty rows between each section of contracts, I copy-paste the data into a new worksheet, put an Autofilter and remove the blank rows
... and voila, that's the final report.
# Possible VBA solution #
I found this tutorial which seems to do exactly what I want, except for the problem where I need the macro to start a new section when the contract no. changes. I don't know how to get the VBA code below to also check for the contract no.
I'd love any help you could send my way. Thanks in advance!
# Code from tutorial on get-digital-help [dot] com by Oscar. #
This is not my code, and I give complete credit to Oscar's tutorial for getting me going in the right direction.
Sub Categorizedatatocolumns()
Dim rng As Range
Dim dest As Range
Dim vrb As Boolean
Dim i As Integer
Set rng = Sheets("Sheet1").Range("A4")
vrb = False
Do While rng <> ""
Set dest = Sheets("Sheet1").Range("A20")
Do While dest <> ""
If rng.Value = dest.Value Then
vrb = True
End If
Set dest = dest.Offset(0, 1)
Loop
If vrb = False Then
dest.Value = rng.Value
dest.Font.bold = True
End If
vrb = False
Set rng = rng.Offset(1, 0)
Loop
Set rng = Sheets("Sheet1").Range("A4")
Do While rng <> ""
Set dest = Sheets("Sheet1").Range("A20")
Do While dest <> ""
If rng.Value = dest.Value Then
i = 0
Do While dest <> ""
Set dest = dest.Offset(1, 0)
i = i + 1
Loop
Set rng = rng.Offset(0, 1)
dest.Value = rng.Value
Set rng = rng.Offset(0, -1)
Set dest = dest.Offset(-i, 0)
End If
Set dest = dest.Offset(0, 1)
Loop
Set rng = rng.Offset(1, 0)
Loop
End Sub
You may consider using pivot table which will give similar output.
Turn off the Subtotal and show data in tabular form for all fields.

use Cube Functions to get filtered dimensions

How do you get a list of filtered dimentions from a cube function
say I had a dimention table of addresses:
1234 Any Street Detroit MI 48229
55588 187th St E Seattle WA 98888
4 Blossum Ave Wescotte AL 66554
How could I get a CUBERANKEDMEMBER list of street addresses with a certain zip?
You could use
=cubeset("powerpivot", "nonempty([City].[Zip].children, [Measure].[Count of City])", "set")
and then use
=Cuberankmember("powerpivot", set, 1)
=Cuberankmember("powerpivot", set, 2)
....
where set is the name of cell where first formula is.

Resources