Proper syntax for calling a particular UDF - excel

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).

Related

Find all other cells with same adjacent element

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).

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

using "Large if" in vba

I am working on a spreadsheet in which I have data of quarter-wise sales by co. and sector. My data is arranged in below mentioned format:
Row 1 has date
Data starts from row 2
Column B: Company Name
Column C: Sector Name of the co. for ex. energy, materials, technology etc
Column D: Sales figure of co.
Column E, F, G: Price, shares, volume of co.
Column H: Blank
From next column onwards I have same data fields for next quarter
Column I: Company Name
Column J: Sector Name of the co. for ex. energy, materials, technology etc
Column K: Sales figure of co
So on and so forth
Now, in another worksheet I need to get name and sales figures for top 3/5/10/15 etc (top n co.s depending on user input) within each sector. For ex. sales figures and co. name of top 3 companies in Energy sector.
I have been trying to write a vba code for this but I am struggling. I have mentioned below the code I was trying but its not flexible at all since in my code I have given reference of column C and D which would actually change after each quarter
Sub try()
Dim r As Long
n = Range("topcos").Value + 5
For r = 5 To n
p = 1
Worksheets("Top co. share with co name").Activate
Cells(r, 16).Select
Selection.FormulaArray = "=LARGE(IF('Co Wise'!$C$3:$C$600=P$3,'Co Wise'!$D$3:$D$600,""""),p)"
p = p + 1
Next r
End Sub
It seems that you merely forgot that p is a variable and should be treated as such in the formula:
Selection.FormulaArray = "=LARGE(IF('Co Wise'!$C$3:$C$600=P$3,'Co Wise'!$D$3:$D$600,"""")," & p & ")"
Alternatively:
Sub SO()
Sheets("Top co. share with co name").Range("P5:P" & [topcos] + 5).FormulaArray = _
"=LARGE(IF('Co Wise'!$C$3:$C$600=P$3,'Co Wise'!$D$3:$D$600,""""),ROW()-4)"
End Sub
Would do the same thing without the need for loops and variables.

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.

Compare 2 tables in MsExcel

Sorry, Here is an additional question:
I have 2 tables with large amount of data:
Example -
table 1:
Course code Region
100201-200 New York
100201-210 New York
100201-220 New York
101201-300 Los Angeles
101201-310 Los Angeles
101201-320 Los Angeles
101201-330 Los Angeles
102201-400 San Diego
102201-410 San Diego
102201-420 San Diego
...........
table 2 (table 2 contains many fields - doesn't matter what's inside)
Course Code Course Date Course Time etc...........
100201-200 .......................................
100201-210
101201-300 ......................................
101201-320
I need to compare "table 2" against "table 1" and find Course Code from "table 2" which matches Course Code in "table 1" to display what Region from "table 1" associated with "table 2".
Do I have to use vlookup function in MsExcel?
If yes, how exactly...?
Huge thanx for your help!
You need to use VLOOKUP. Here is the syntax for it:
VLOOKUP( value, table_array, index_number, [not_exact_match] )
Have a look at the examples here on MSDN VLOOKUP Manual Page
See also:
Function: HLOOKUP, Function: LOOKUP, Excel Lookup Functions

Resources