Nested loops - multiple conditions

elysium

New Member
Joined
Feb 6, 2016
Messages
13
Hi All, seeking help for a possible VBA solution to a problem I am facing.

I will have 3 worksheets

First worksheet
Blank customer = applies to all customers
Blank product = applies to all products


MarketCustomerProductSiteRatio
USNew York0.7
USOrlando0.3
US999New York1
USAAA111New York1
USBBB222Orlando0.6
USBBB222New York0.4


Second worksheet is where all my customers are listed

MarketCustomer
USAAA
USBBB
USCCC
USDDD
USEEE


The 3rd worksheet is where the results will generate after macro runs:

I am still trying to figure out how to write this nested loop logic, any help would be much appreciated!

MarketCustomerProductSiteRatio
USAAANew York0.7
USAAAOrlando0.3
USBBBNew York0.7
USBBBOrlando0.3
USCCCNew York0.7
USCCCOrlando0.3
USDDDNew York0.7
USDDDOrlando0.3
USEEENew York0.7
USEEEOrlando0.3
USAAA999New York1
USBBB999New York1
USCCC999New York1
USDDD999New York1
USEEE999New York1
USAAA111New York1
USBBB222Orlando0.6
USBBB222New York0.4
 

Excel Facts

Pivot Table Drill Down
Double-click any number in a pivot table to create a new report showing all detail rows that make up that number
The following VBA will achieve this, though the output (3rd worksheet) will not be in the same order as you have above (which I presume does not matter). The Sheet names are hard coded and not doubt this could be more efficiently achieved with arrays, but this does what you're after. Take note of the instructions in the comments to subStart().

VBA Code:
Public iCustomer As Integer
Public iRow As Integer

Sub subStart()
' Run subStart to process.
' It requires sheets Sheet1, Sheet2 and Sheet3
' Sheet1 must have the format (with the heading row):
' Market|Customer|Product|Site|Ratio
' US|||New York|0.7
' Sheet2 must have the format (with the heading row)
' Market|customer
' US|AAA
' For both sheets the | denotes the next cell
' Sheet3 should be blank
Sheet3.Select
' Enter the headings to Sheet3
Range("A1").Value = "Market"
Range("B1").Value = "Customer"
Range("C1").Value = "Product"
Range("D1").Value = "Site"
Range("E1").Value = "Ratio"
' Now initialise and process Sheet2
iRow = 2
iCustomer = 2
Call subDoSheet2
End Sub

Sub subDoSheet2()
b = True
tempCustomer$ = ""
Do While b = True
    Sheet2.Select
    ' Get the next market/customer combination
    r$ = "A" & Trim(Str(iCustomer))
    Range(r$).Select
    market$ = ActiveCell.FormulaR1C1
    If market$ = "" Then
        ' When we get past the last market/customer we're finished
        Exit Do
    End If
    r$ = "B" & Trim(Str(iCustomer))
    Range(r$).Select
    customer$ = ActiveCell.FormulaR1C1
    ' Process Sheet1 with for market/customer
    Call subDoSheet1(market$, customer$)
Loop
End Sub

Sub subDoSheet1(marketS2$, customerS2$)
iLocal = 2
Do While iLocal > 0
    Sheet1.Select
    Range("A" & Trim(Str(iLocal))).Select
    marketS1$ = ActiveCell.FormulaR1C1
    If marketS1$ = "" Then
        iCustomer = iCustomer + 1
        Exit Do      ' end of the sheet
    End If
    Range("B" & Trim(Str(iLocal))).Select
    customerS1$ = ActiveCell.FormulaR1C1
    Range("C" & Trim(Str(iLocal))).Select
    productS1$ = ActiveCell.FormulaR1C1
    Range("D" & Trim(Str(iLocal))).Select
    siteS1$ = ActiveCell.FormulaR1C1
    Range("E" & Trim(Str(iLocal))).Select
    ratioS1$ = ActiveCell.FormulaR1C1
    Sheet3.Select
    ' When the customer is 'default' (not specified) we want that
    ' output for this customer
    If Len(customerS1$) = 0 Then
        Range("A" & Trim(Str(iRow))).Value = marketS2$
        Range("B" & Trim(Str(iRow))).Value = customerS2$
        Range("C" & Trim(Str(iRow))).Value = productS1$
        Range("D" & Trim(Str(iRow))).Value = siteS1$
        Range("E" & Trim(Str(iRow))).Value = ratioS1$
        iRow = iRow + 1
    ' When the customer matches we want that
    ' output for this customer
    ElseIf customerS1$ = customerS2$ Then
        Range("A" & Trim(Str(iRow))).Value = marketS2$
        Range("B" & Trim(Str(iRow))).Value = customerS2$
        Range("C" & Trim(Str(iRow))).Value = productS1$
        Range("D" & Trim(Str(iRow))).Value = siteS1$
        Range("E" & Trim(Str(iRow))).Value = ratioS1$
        iRow = iRow + 1
    End If ' else do nothing
    iLocal = iLocal + 1
Loop
End Sub
 
Upvote 0
Hi Kennypete,

Thank you! This works but unfortunately I have easily over a few hundred customers and I gave up after running this for 20 mins as excel stops responding.

Hoping there is a faster solution.

Regards,
Erica


The following VBA will achieve this, though the output (3rd worksheet) will not be in the same order as you have above (which I presume does not matter). The Sheet names are hard coded and not doubt this could be more efficiently achieved with arrays, but this does what you're after. Take note of the instructions in the comments to subStart().

VBA Code:
Public iCustomer As Integer
Public iRow As Integer

Sub subStart()
' Run subStart to process.
' It requires sheets Sheet1, Sheet2 and Sheet3
' Sheet1 must have the format (with the heading row):
' Market|Customer|Product|Site|Ratio
' US|||New York|0.7
' Sheet2 must have the format (with the heading row)
' Market|customer
' US|AAA
' For both sheets the | denotes the next cell
' Sheet3 should be blank
Sheet3.Select
' Enter the headings to Sheet3
Range("A1").Value = "Market"
Range("B1").Value = "Customer"
Range("C1").Value = "Product"
Range("D1").Value = "Site"
Range("E1").Value = "Ratio"
' Now initialise and process Sheet2
iRow = 2
iCustomer = 2
Call subDoSheet2
End Sub

Sub subDoSheet2()
b = True
tempCustomer$ = ""
Do While b = True
    Sheet2.Select
    ' Get the next market/customer combination
    r$ = "A" & Trim(Str(iCustomer))
    Range(r$).Select
    market$ = ActiveCell.FormulaR1C1
    If market$ = "" Then
        ' When we get past the last market/customer we're finished
        Exit Do
    End If
    r$ = "B" & Trim(Str(iCustomer))
    Range(r$).Select
    customer$ = ActiveCell.FormulaR1C1
    ' Process Sheet1 with for market/customer
    Call subDoSheet1(market$, customer$)
Loop
End Sub

Sub subDoSheet1(marketS2$, customerS2$)
iLocal = 2
Do While iLocal > 0
    Sheet1.Select
    Range("A" & Trim(Str(iLocal))).Select
    marketS1$ = ActiveCell.FormulaR1C1
    If marketS1$ = "" Then
        iCustomer = iCustomer + 1
        Exit Do      ' end of the sheet
    End If
    Range("B" & Trim(Str(iLocal))).Select
    customerS1$ = ActiveCell.FormulaR1C1
    Range("C" & Trim(Str(iLocal))).Select
    productS1$ = ActiveCell.FormulaR1C1
    Range("D" & Trim(Str(iLocal))).Select
    siteS1$ = ActiveCell.FormulaR1C1
    Range("E" & Trim(Str(iLocal))).Select
    ratioS1$ = ActiveCell.FormulaR1C1
    Sheet3.Select
    ' When the customer is 'default' (not specified) we want that
    ' output for this customer
    If Len(customerS1$) = 0 Then
        Range("A" & Trim(Str(iRow))).Value = marketS2$
        Range("B" & Trim(Str(iRow))).Value = customerS2$
        Range("C" & Trim(Str(iRow))).Value = productS1$
        Range("D" & Trim(Str(iRow))).Value = siteS1$
        Range("E" & Trim(Str(iRow))).Value = ratioS1$
        iRow = iRow + 1
    ' When the customer matches we want that
    ' output for this customer
    ElseIf customerS1$ = customerS2$ Then
        Range("A" & Trim(Str(iRow))).Value = marketS2$
        Range("B" & Trim(Str(iRow))).Value = customerS2$
        Range("C" & Trim(Str(iRow))).Value = productS1$
        Range("D" & Trim(Str(iRow))).Value = siteS1$
        Range("E" & Trim(Str(iRow))).Value = ratioS1$
        iRow = iRow + 1
    End If ' else do nothing
    iLocal = iLocal + 1
Loop
End Sub
 
Upvote 0
I don't understand what you want with this query, but if you have a lot of data, you can do it with MsAccess.
Full example here

rptElysium

MarketCustomerProductSiteRatio
USAAA
New York
0.7​
USAAA
Orlando
0.3​
USBBB
New York
0.7​
USBBB
Orlando
0.3​
USCCC
New York
0.7​
USCCC
Orlando
0.3​
USDDD
New York
0.7​
USDDD
Orlando
0.3​
USEEE
New York
0.7​
USEEE
Orlando
0.3​
USAAA
111​
New York
1​
USBBB
222​
New York
0.4​
USBBB
222​
Orlando
0.6​
USAAA
999​
New York
1​
USBBB
999​
New York
1​
USCCC
999​
New York
1​
USDDD
999​
New York
1​
USEEE
999​
New York
1​


SQL:
SELECT master.Market, customers.Customer, master.Product, master.Site, master.Ratio
FROM customers, master
where isnull(master.product)
union
SELECT master.Market, customers.Customer, master.Product, master.Site, master.Ratio
FROM customers, master
where isnull(master.customer)
union
SELECT master.Market, master.Customer, master.Product, master.Site, master.Ratio
FROM master
where (not isnull(master.customer) and not isnull(master.product))
ORDER BY master.Product;
 
Upvote 0
No Access

I don't understand what you want with this query, but if you have a lot of data, you can do it with MsAccess.
Full example here

rptElysium

MarketCustomerProductSiteRatio
USAAA
New York
0.7​
USAAA
Orlando
0.3​
USBBB
New York
0.7​
USBBB
Orlando
0.3​
USCCC
New York
0.7​
USCCC
Orlando
0.3​
USDDD
New York
0.7​
USDDD
Orlando
0.3​
USEEE
New York
0.7​
USEEE
Orlando
0.3​
USAAA
111​
New York
1​
USBBB
222​
New York
0.4​
USBBB
222​
Orlando
0.6​
USAAA
999​
New York
1​
USBBB
999​
New York
1​
USCCC
999​
New York
1​
USDDD
999​
New York
1​
USEEE
999​
New York
1​


SQL:
SELECT master.Market, customers.Customer, master.Product, master.Site, master.Ratio
FROM customers, master
where isnull(master.product)
union
SELECT master.Market, customers.Customer, master.Product, master.Site, master.Ratio
FROM customers, master
where isnull(master.customer)
union
SELECT master.Market, master.Customer, master.Product, master.Site, master.Ratio
FROM master
where (not isnull(master.customer) and not isnull(master.product))
ORDER BY master.Product;
 
Upvote 0
Are you saying what you will more data and then you are writing, no Access

?.

MsAccess is a very good choice/ option for you, reports, excellent for create forms, querys, recordsets, export to Excel, and much much more. I fact everything that you can do in Excel, is possible in Access
But, finally it is your your questions and you know better, the answer what you want
?.
Access is a very good option for you, reports, excellent for create forms, querys, recordsets, export to Excel,
and much much more.
But, finally it is your your questions and you know better, the answer what you want.
 
Upvote 0
Try this:
I assumed:
- data is in sheet1, sheet2, sheet3
- data in "sheet2" is sorted by col A (Market).
VBA Code:
Sub a1118750a()
'https://www.mrexcel.com/board/threads/nested-loops-multiple-conditions.1118750/#post-5393973

Dim i As Long, j As Long, k As Long
Dim va, vb, x
Dim d As Object

Application.ScreenUpdating = False
Sheets("Sheet2").Activate
Set d = CreateObject("scripting.dictionary")
d.CompareMode = vbTextCompare

va = Range("A1:B" & Cells(Rows.Count, "A").End(xlUp).Row)
For i = 2 To UBound(va, 1)
 j = i
    Do
        i = i + 1
        If i > UBound(va, 1) Then Exit Do
    Loop While va(i, 1) = va(i - 1, 1)
    i = i - 1

    d(va(i, 1)) = Application.Transpose(Range(Cells(j, "B"), Cells(i, "B")).Value)

Next

Sheets("Sheet1").Activate
va = Range("A2:E" & Cells(Rows.Count, "A").End(xlUp).Row)
ReDim vb(1 To 1000000, 1 To 5)

    For i = 1 To UBound(va, 1)
        If d.Exists(va(i, 1)) Then
            If va(i, 2) = "" Then
                For Each x In d(va(i, 1))
                    k = k + 1
                    vb(k, 1) = va(i, 1)
                    vb(k, 2) = x
                    vb(k, 3) = va(i, 3)
                    vb(k, 4) = va(i, 4)
                    vb(k, 5) = va(i, 5)
                Next
            
            Else
                    k = k + 1
                    vb(k, 1) = va(i, 1)
                    vb(k, 2) = va(i, 2)
                    vb(k, 3) = va(i, 3)
                    vb(k, 4) = va(i, 4)
                    vb(k, 5) = va(i, 5)
        
            End If
        
        End If
    
    Next

Sheets("Sheet3").Activate
Cells.ClearContents
Range("A1").Resize(, 5).Value = Sheets("Sheet1").Range("A1").Resize(, 5).Value
Range("A2").Resize(k, 5) = vb

Application.ScreenUpdating = True
End Sub

Example:
Book1
ABCDE
1MarketCustomerProductSiteRatio
2USNew York0.7
3USOrlando0.3
4US999New York1
5USAAA111New York1
6USBBB222Orlando0.6
7USBBB222New York0.4
8ChinaBeijing3
9ChinaGGG77Beijing4
10ChinaBBB88Hong Kong5
Sheet1

Book1
AB
1MarketCustomer
2ChinaAAA
3ChinaBBB
4ChinaGGG
5USAAA
6USBBB
7USCCC
8USDDD
9USEEE
Sheet2

Book1
ABCDE
1MarketCustomerProductSiteRatio
2USAAANew York0.7
3USBBBNew York0.7
4USCCCNew York0.7
5USDDDNew York0.7
6USEEENew York0.7
7USAAAOrlando0.3
8USBBBOrlando0.3
9USCCCOrlando0.3
10USDDDOrlando0.3
11USEEEOrlando0.3
12USAAA999New York1
13USBBB999New York1
14USCCC999New York1
15USDDD999New York1
16USEEE999New York1
17USAAA111New York1
18USBBB222Orlando0.6
19USBBB222New York0.4
20ChinaAAABeijing3
21ChinaBBBBeijing3
22ChinaGGGBeijing3
23ChinaGGG77Beijing4
24ChinaBBB88Hong Kong5
Sheet3
 
Upvote 0
Sorry for not elaborating but I am on a company laptop and do not have MSAccess available.. Can I do this on spyder?


?.

MsAccess is a very good choice/ option for you, reports, excellent for create forms, querys, recordsets, export to Excel, and much much more. I fact everything that you can do in Excel, is possible in Access
But, finally it is your your questions and you know better, the answer what you want
?.
Access is a very good option for you, reports, excellent for create forms, querys, recordsets, export to Excel,
and much much more.
But, finally it is your your questions and you know better, the answer what you want.
 
Upvote 0

Forum statistics

Threads
1,223,982
Messages
6,175,776
Members
452,668
Latest member
mrider123

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top