I have tried to fix a code from the answers that I have found in the forum, but I can't manage.
My issue is:
I have a list of recipes names in the sheet weeks, and I want to decide with a 1 or a 0 which ones I want to meal prep for next week. In sheet Recipes, I have the Recipes listed with their ingredients list below. I would like to have an output of what I need to shop in Sheet 5. In sheet Weeks If column B = 1, take recipe name in column A; Hlookup recipe name in sheet Recipes row 3, and return list of ingredients below to sheet 3 (the shopping list).
Sub Output_Shoopinglist()
Dim ws As Worksheet ' define worksheet
Set ws = ThisWorkbook.Worksheets("Weeks")
Dim LastRow As Long ' get last used row in column b
LastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
Dim DataRange As Range ' get data range
Set DataRange = ws.Range("B3", "C20" & LastRow)
Dim DataArray() As Variant ' read data into an array (for fast processing)
DataArray = DataRange.Value
Dim OutputData As Collection ' create a collection where we collect all desired data
Set OutputData = New Collection
' check each data row and if desired add to collection
Dim iRow As Long
For iRow = LBound(DataArray, 1) To UBound(DataArray, 1)
If DataArray(iRow, 2) = 1 Then
OutputData.Add DataArray(iRow, 1)
End If
Next iRow
Dim wsTemplate As Worksheet
Set wsTemplate = ThisWorkbook.Worksheets("Recipes")
Dim wsVolume As Worksheet
Set wsVolume = ThisWorkbook.Worksheets("Shopping list")
'Lookup Value in Tab Recipes in row 3, and return Ingrediants list one below the other in tab Shopping list in Column B
'Here I am missing code:
End Sub
I have left comments in few area to explain what the code is doing in general.
As mentioned in the comment - The basic idea is to perform a Find
method along the row containing the recipe name and if it is found, the column number of the found cell will be used to pull out the list of ingredients (and the amount that is 1 column before) that is written below the recipe names.
Once the list has been retrieved in an array, it will be used to write into the shopping list worksheet at once.
Option Explicit
Const WSNAME_WEEK As String = "Weeks"
Const WSNAME_RECIPES As String = "Recipes"
Const WSNAME_SHOPPING As String = "Shopping list"
Sub Output_Shoppinglist()
Dim ws As Worksheet ' define worksheet
Set ws = ThisWorkbook.Worksheets(WSNAME_WEEK)
Dim lastRow As Long ' get last used row in column b
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
Dim DataRange As Range ' get data range
Set DataRange = ws.Range("B4:C" & lastRow)
Dim DataArray() As Variant ' read data into an array (for fast processing)
DataArray = DataRange.Value
Dim OutputData As Collection ' create a collection where we collect all desired data
Set OutputData = New Collection
' check each data row and if desired add to collection
Dim iRow As Long
For iRow = LBound(DataArray, 1) To UBound(DataArray, 1)
If DataArray(iRow, 2) = 1 Then
OutputData.Add DataArray(iRow, 1)
End If
Next iRow
If OutputData.Count <> 0 Then
' Uncomment if you need to clear the shopping list prior to inserting this batch of list of ingredients
' With ThisWorkbook.Worksheets(WSNAME_SHOPPING)
' Dim shoppingLastRow As Long
' shoppingLastRow = .Cells(.Rows.Count, 2).Row
' .Range("A2:B" & shoppingLastRow).Value = ""
' End With
'1. Loop through the collection,
'2. Pass the recipe name to GetIngredients to retrieve the list of ingredients (in an array) from Recipes worksheet
'3. Pass the array to WriteToShoppingList for writing into the Shopping list worksheet
Dim i As Long
For i = 1 To OutputData.Count
'Get the ingredient list from Recipes sheet
Dim ingredList As Variant
ingredList = GetIngredients(OutputData(i))
If Not IsEmpty(ingredList) Then WriteToShoppingList ingredList
Next i
End If
MsgBox "Done!"
End Sub
Function GetIngredients(argRecipeName As String) As Variant
Const firstRow As Long = 7 'Change this to whichever row the first ingredient should be on
Const recipesNameRow As Long = 3
Dim wsTemplate As Worksheet
Set wsTemplate = ThisWorkbook.Worksheets(WSNAME_RECIPES)
'==== Do a Find on row with the recipe names
Dim findCell As Range
Set findCell = wsTemplate.Rows(recipesNameRow).Find(argRecipeName, LookIn:=xlValues, LookAt:=xlWhole)
If Not findCell Is Nothing Then
'==== If found, assign the value of the ingredients (from firstRow to the last row) into an array
Dim lastRow As Long
lastRow = wsTemplate.Cells(firstRow, findCell.Column).End(xlDown).Row
Dim ingredRng As Range
Set ingredRng = wsTemplate.Range(wsTemplate.Cells(firstRow, findCell.Column), wsTemplate.Cells(lastRow, findCell.Column)).Offset(, -1).Resize(, 2)
Dim ingredList As Variant
ingredList = ingredRng.Value
GetIngredients = ingredList
End If
End Function
Sub WriteToShoppingList(argIngredients As Variant)
Dim wsVolume As Worksheet
Set wsVolume = ThisWorkbook.Worksheets(WSNAME_SHOPPING)
Dim lastRow As Long
lastRow = wsVolume.Cells(wsVolume.Rows.Count, 2).End(xlUp).Row
wsVolume.Cells(lastRow + 1, 1).Resize(UBound(argIngredients, 1), 2).Value = argIngredients
End Sub