For Each does not loop through sheets (without error) - excel

I need quick help to find my mistake.
The code below should loop through sheets and copy data to respective columns.
But it only copies from 1 sheet
I tried reseting varaiables but nothing helps..
I have similar macro where For each loop and the same If statement works with out problem.
Update:
It appears the problem is here no matter what kind of outer loop i write to jump to next row it does not jump, It just keeps overwriting cells..
For Each c In MyDataHeaders
i = Application.WorksheetFunction.Match(c.value, ColHeaders, 0) 'Finds the
matching column name Rng.Offset(, i - 1).value = Intersect(DataBlock.EntireRow,
c.EntireColumn).value 'Writes the values
Stop
Next c
Code below:
Sub CopyDataBlocks()
Dim sht As Worksheet
Dim SourceSheet As Worksheet 'The data to be copied is here
Dim TargetSheet As Worksheet 'The data will be copied here
Dim ColHeaders As Range 'Column headers on Target sheet
Dim MyDataHeaders As Range 'Column headers on Source sheet
Dim DataBlock As Range 'A single column of data
Dim c As Range 'a single cell
Dim Rng As Range 'The data will be copied here (="Place holder" for the first data cell)
Dim i As Integer
'Change the names to match your sheetnames:
'Set SourceSheet = Sheets("ws1")
Set TargetSheet = Sheets("Master")
With TargetSheet
Set ColHeaders = .Rows(1) '.Cells(1, 1), .Cells(1, .Columns.Count).End(xlToLeft) 'Or just .Range("A1:C1")
Set Rng = .Cells(.Rows.Count, 1).End(xlUp).Offset(1) 'Shoots up from the bottom of the sheet untill it bumps into something and steps one down
End With
For Each SourceSheet In ThisWorkbook.Worksheets
If SourceSheet.name Like "Sheet*" Then
With SourceSheet
Set MyDataHeaders = Intersect(.Rows(1), .UsedRange)
For Each c In MyDataHeaders
If Application.WorksheetFunction.CountIf(ColHeaders, c.value) = 0 Then
MsgBox "Can't find a matching header name for " & c.value & vbNewLine & "Make sure the column names are the same and try again."
Exit Sub
End If
Next c
'There was a match for each colum name.
'Set the first datablock to be copied:
Set DataBlock = .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp)) 'A2:A & the last cell with something on it on column A
'Resizes the target Rng to match the size of the datablock:
Set Rng = Rng.Resize(DataBlock.Rows.Count, 1)
'Copies the data one column at a time:
For Each c In MyDataHeaders
i = Application.WorksheetFunction.Match(c.value, ColHeaders, 0) 'Finds the matching column name
Rng.Offset(, i - 1).value = Intersect(DataBlock.EntireRow, c.EntireColumn).value 'Writes the values
Next c
End With
Set MyDataHeaders = Nothing
End If
Next SourceSheet
End Sub
Thanks!

Related

Running VBA code across multiple sheets issue

I am currently using this code which goes through my worksheet and checks in the range O15:O300 to see if there are any cells that match the current date. If there is then it copies the entire row to worksheet "Today's Actions" then copies the site number (Situated in cell C3) to column AA in "Todays Actions".
I use the below code which works fine for this task for one specific sheet:
Sub rangecheck()
Application.ScreenUpdating = False
For Each cell In Range("O15:O300")
If cell.Value = Date Then
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Today's Actions").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
ActiveSheet.Range("C3").Copy
Sheets("Today's Actions").Range("AA" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
Next
Application.ScreenUpdating = True
End Sub
However, there are multiple sheets that I need to action this code for. So I use the below code to run this across all sheets:
Sub rangecheck_Set()
Dim ws As Worksheet
Dim starting_ws As Worksheet
Set starting_ws = ActiveSheet
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
ws.Activate
Call rangecheck
Next
starting_ws.Activate 'activate the worksheet that was originally active ("Today's Actions")
Application.ScreenUpdating = True
End Sub
This issue I'm having is that it seems to work fine but randomly whenever there are a lot of dates that match todays date in range O15:O300, it duplicates some lines up to or slightly exceeding 300 rows (So as an example, if there were 15 rows that 'should' be brought back to "Today's action" tab, it would bring them back but then have a few other rows randomly duplicated down to around row 300).
I get this might be due to the range going down to 300 but I even edited the range to go to 'last row' and it still brings back the same issue. Any thoughts? I've been trying to solve this for days now. Any help appreciated
Don't use implicit references to worksheets and ranges. It is most likely that this is the reason for your problem.
Also you don't need to select and copy - another source for unforeseeable errors.
Another reason for your error could be that you don't exclude "Today's Actions"-sheet from the copying routine.
I re-wrote your sub that is copying the data:
Sub copyTodaysRows(wsSource As Worksheet, wsTarget As Worksheet)
If wsSource is wsTarget then Exit Sub 'don't run this for the target sheet
Dim c As Range, wsTargetNewRow As Long
For Each c In wsSource.Range("O15:O300")
If c.Value = Date Then
With wsTarget
wsTargetNewRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
c.EntireRow.Copy Destination:=.Range("A" & wsTargetNewRow)
.Range("AA" & wsTargetNewRow).Value = wsSource.Range("C3").Value
End With
End If
Next
End Sub
It takes the source sheet and the target sheet as input parameters.
You will call it like this within your "outer" routine:
Sub rangecheck_Set()
Application.ScreenUpdating = False
Dim wsSource as worksheet
Dim wsTarget as worksheet
Set wsTarget = Thisworkbook.Worksheets("Today's Actions")
For Each wsSource In ThisWorkbook.Worksheets
copyTodaysRows wsSource, wsTarget
Next
Application.ScreenUpdating = True
End Sub
Copy Values of Criteria (Dates) Rows From Multiple Worksheets
Option Explicit
Sub RetrieveTodaysActions()
' Calls 'RetrieveTodaysActionsCall'.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet
For Each sws In ThisWorkbook.Worksheets
RetrieveTodaysActionsCall sws
Next sws
MsgBox "Today's actions retrieved.", vbInformation
End Sub
Sub RetrieveTodaysActionsCall(ByVal sws As Worksheet)
' Define constants.
' Source
Const sCriteriaColumnAddress As String = "O15:O300"
Const sCol1 As String = "A"
Const sCell2Address As String = "C3"
' Destination
Const dName As String = "Today's Actions"
Const dCol1 As String = "A"
Const dCol2 As String = "AA"
' Both
' Write the criteria date to a variable ('CriteriaDate').
Dim CriteriaDate As Date: CriteriaDate = Date ' today
' Exclude the destination worksheet.
If StrComp(sws.Name, dName, vbTextCompare) = 0 Then Exit Sub
' Reference the source criteria column range ('scrg').
Dim scrg As Range: Set scrg = sws.Range(sCriteriaColumnAddress)
' Check the number of matches, the number of rows to be copied
' to the destination worksheet.
If Application.CountIf(scrg, Date) = 0 Then Exit Sub
' Reference the range ('surg'), the range from the first cell
' in the source column ('sCol1') to the last cell of the used range.
Dim surg As Range
With sws.UsedRange
Set surg = sws.Range(sCol1 & 1, .Cells(.Rows.Count, .Columns.Count))
End With
' Reference the source range ('srg').
Dim srg As Range: Set srg = Intersect(scrg.EntireRow, surg)
If srg Is Nothing Then Exit Sub
' Write the number of columns of the source range to a variable (cCount).
Dim cCount As Long: cCount = srg.Columns.Count
' Write the criteria column number to a variable ('CriteriaColumn').
Dim CriteriaColumn As Long: CriteriaColumn = scrg.Column
' Write the values from the source range to an array ('Data').
Dim Data() As Variant: Data = srg.Value
Dim sValue As Variant ' Criteria Value in the Current Source Row
Dim sr As Long ' Current Source Row
Dim c As Long ' Current Source/Destination Column
Dim dr As Long ' Current Destination Row
' Loop through the rows of the array.
For sr = 1 To UBound(Data, 1)
' Write the value in the current row to a variable.
sValue = Data(sr, CriteriaColumn)
' Check if the current value is a date.
If IsDate(sValue) Then
' Check if the current value is equal to the criteria date.
If sValue = CriteriaDate Then
dr = dr + 1
' Write the values from the source row to the destination row.
For c = 1 To cCount
Data(dr, c) = Data(sr, c)
Next c
End If
End If
Next sr
' Reference the destination worksheet ('dws').
Dim dws As Worksheet: Set dws = sws.Parent.Worksheets(dName)
' Reference the destination first cell ('dfCell').
Dim dfCell As Range
Set dfCell = dws.Cells(dws.Rows.Count, dCol1).End(xlUp).Offset(1)
' Reference the destination range ('drg').
Dim drg As Range: Set drg = dfCell.Resize(dr, cCount)
' Write the values from the array to the destination range.
drg.Value = Data
' Reference the destination range 2 ('drg2').
Dim drg2 As Range: Set drg2 = drg.EntireRow.Columns(dCol2)
' Write the source cell 2 value to the destination range 2 ('drg2')
' (the same value to all cells of the range).
drg2.Value = sws.Range(sCell2Address).Value
End Sub
My process was different from the other responses, so I will still post it. I have also added a way of logging that a row has been logged because otherwise I saw that rows could be duplicated to the "Today's Actions" sheet.
Sub rangecheck(ByVal checkedSheet As Worksheet)
'#PARAM checkedSheet is the sheet to iterate through for like dates.
'Instantiate counter variables
Dim matchRow As Integer
matchRow = 0
Dim pasteRow As Integer
pasteRow = 0
Application.ScreenUpdating = False
For Each cell In checkedSheet.Range("O15:O300")
If cell.Value = Date Then
matchRow = cell.Row
'Checks if the row has been logged already (I use column "A" because I
'have no data in it, but this can be amy column in the row)
If checkedSheet.Cells(matchRow, 1) = "Logged" Then
'Do nothing
Else
'Sets value of "pasteRow" to one lower than the lowest used row in
column "AA"
pasteRow = Sheets("Today's Actions").Cells(Rows.Count,
27).End(xlUp).Row + 1
'Copies the values of the matchRow to the pasteRow
Sheets("Today's Actions").Rows(pasteRow).Value =
checkedSheet.Rows(matchRow).Value
'Copies the value of the Site Number to the paste row column "AA"
Sheets("Today's Actions").Cells(pasteRow, 27).Value =
checkedSheet.Cells(3, 3).Value
'Log that a row has been added to the "Today's Actions" sheet
checkedSheet.Cells(matchRow, 1) = "Logged"
End If
End If
Next
Application.ScreenUpdating = True
End Sub
I have also modifed your sub which calls the copying sub to check if it is trying to copy the "Today's Actions" sheet.
Sub rangecheck_Set()
Dim ws As Worksheet
Dim starting_ws As Worksheet
Set starting_ws = Worksheets("Today's Actions")
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
'Check if the ws to check is "Today's Actions"
If ws.Name = "Today's Actions" Then
'Do Nothing
Else
Call rangecheck(ws)
End If
Next
starting_ws.Activate 'activate the worksheet that was originally active
Application.ScreenUpdating = True
End Sub

Paste information in different sheets (would like to specify started at cell A1 in each sheet)

There are 3 groups (A,B,C) of data in excel sheet1, and in my workbook i already create 3 sheets named (A, B, C).
I have no problem to copy group A,B,C data into their corresponding sheet, e.g. copy group A data into sheet A, however i find in some cases the selected cell at the beginning of each sheet is not in A1, e.g. the selected cell at the beginning maybe at somewhere other cells in excel (e.g. B10), this make the presentation looks messy, i want the all the data in each sheet start at A1. I know some of you may said using the code Range("a1").selected can manage this situation, however we need to use the "Do loop" to loop over each row in sheet1 to identify that row is belong to A,B or C, then we paste that row into the corresponding sheet. I found if i include the code Range("a1").selected, then each time the program will paste the row in Sheet1 into the cell A1 in sheet A,B and C, and at the end there will only one row appear in each sheets. What should i improve the program below so that each time the data in each group can be appeared at the beginning of cell A1 in their worksheet even sometimes the selected cell of each sheet is not in cell A1? Thanks.
Sub data_category()
Dim y As Integer
Dim x As String
Sheets("sheet1").Activate
Range("a3").Select
Do Until ActiveCell.Value = ""
y = ActiveCell.Offset(0, 3).Value
If y < 90 Then
x = "A"
ElseIf y < 120 Then
x = "B"
Else
x = "C"
End If
ActiveCell.Offset(0, 4).Value = x
Range(ActiveCell, ActiveCell.End(xlToRight)).Copy
Sheets(x).Activate
Range("a1").Select
ActiveCell.PasteSpecial
ActiveCell.Offset(1, 0).Select
Sheets("sheet1").Activate
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Rather than the Do-Loop approach, I would do this slightly different for a faster execution.
Logic
Find last row in Sheet1 of Col A
Insert formula =IF(D3<90,"A",IF(D3<120,"B","C")) in Col E starting at row 3
Next I will use autofilter to filter column E on A first and copy all data in one go to Sheet A. I will repeat the process for B and C
My Assumptions
Row 2 has headers. If not, tweak the code accordingly.
Code
I have commented the code so you will not have a problem understanding it, but if you do, then simply ask.
Option Explicit
Dim ws As Worksheet
Dim rng As Range
Sub Sample()
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim lRow As Long
With ws
'~~> Remove any filters
.AutoFilterMode = False
'~~> Find last row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Insert formula in Col E
With .Range("E3:E" & lRow)
.Formula = "=IF(D3<90,""A"",IF(D3<120,""B"",""C""))"
.Value = .Value
End With
'~~> Identify the range to work with
Set rng = .Range("A2:E" & lRow)
'~~> Copy rows with relevant criteria
CopyData "A"
CopyData "B"
CopyData "C"
.AutoFilterMode = False
End With
End Sub
Private Sub CopyData(shName As String)
Dim rngToCopy As Range
'~~> Filter column E on the search string
With rng
.AutoFilter Field:=5, Criteria1:=shName
Set rngToCopy = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
End With
'~~> Copy all data in one go
If Not rngToCopy Is Nothing Then rngToCopy.Copy ThisWorkbook.Sheets(shName).Rows(1)
ws.AutoFilterMode = False
End Sub
In Action
Following from Sid's comment:
Sub data_category()
Dim y As Long
Dim x As String, c As Range, ws As Worksheet, wb As Workbook, cDest As Range
Set wb = ActiveWorkbook 'or ThisWorkbook: always good to be specific here
Set c = wb.Worksheets("sheet1").Range("a3") 'get a reference to the starting cell
Do Until Len(c.Value) = 0
y = c.Offset(0, 3).Value
Select Case y 'tidier then if...else if
Case Is < 90: x = "A"
Case Is < 120: x = "B"
Case Else: x = "C"
End Select
c.Offset(0, 4).Value = x
'direct copy to next empty row with no select/activate
Set cDest = wb.Worksheets(x).Cells(Rows.Count, 1).End(xlUp)
If Len(cDest).Value > 0 Then Set cDest = cDest.Offset(1, 0)
c.EntireRow.Copy cDest
Set c = c.Offset(1,0) '<<<<<<<<<<<<< edit - added
Loop
c.Parent.Activate
End Sub
Update Category Reports
Option Explicit
Sub UpdateCategoryReports()
Const sfRow As Long = 3 ' First Row (headers are in row 'sfRow - 1')
Const sfCol As Long = 1
Const dfRow As Long = 2 ' First Row (headers are in row 'dfRow - 1')
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets("Sheet1")
Dim slRow As Long: slRow = sws.Cells(sws.Rows.Count, "A").End(xlUp).Row
If slRow < sfRow Then Exit Sub ' no data (highly unlikely)
Dim slCol As Long
slCol = sws.Cells(sfRow - 1, sws.Columns.Count).End(xlToLeft).Column
Application.ScreenUpdating = False
Dim dws As Worksheet ' Destination Worksheet
Dim durg As Range ' Destination 'UsedRange'
Dim dcrg As Range ' Destination Clear Range
' Clear destination data.
For Each dws In wb.Worksheets(Array("A", "B", "C"))
Set durg = dws.UsedRange ' Destination Used Range
If durg.Rows.Count > 1 Then
' You don't want to clear the headers:
' e.g. if 'durg' is 'A1:J10' then 'dcrg' will be 'A2:J10'.
Set dcrg = durg.Resize(durg.Rows.Count - 1).Offset(1)
dcrg.Clear
End If
Next dws
Dim srrg As Range ' Source Row Range
Dim sRow As Long ' Source Row
Dim dfCell As Range ' Destination First Cell (Range)
Dim dRow As Long ' Destination (Available) Row
Dim sValue As Double ' Source Value
Dim dwsName As String ' Destination Worksheet Name
For sRow = sfRow To slRow
If IsNumeric(sws.Cells(sRow, "D").Value) Then
sValue = sws.Cells(sRow, "D").Value
If sValue < 90 Then
dwsName = "A"
ElseIf sValue < 120 Then
dwsName = "B"
Else
dwsName = "C"
End If
Set srrg = sws.Range(sws.Cells(sRow, "A"), sws.Cells(sRow, slCol))
sws.Cells(sRow, "E").Value = dwsName ' ?
Set dws = wb.Worksheets(dwsName)
dRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row + 1
Set dfCell = dws.Cells(dRow, "A")
' This will copy values, formats, and formulas. You may need another
' way. If there are formulas in source and you only need values,
' copying by assignment is the most efficient way. If you also need
' the formats you will have to use the least efficient PasteSpecial.
srrg.Copy Destination:=dfCell
'Else ' sValue is not numeric: do nothing
End If
Next sRow
'sws.Activate
'sws.Cells(1).Activate
Application.ScreenUpdating = True
MsgBox "Category reports updated.", vbInformation, "Category Reports"
End Sub

Copy first Row of Each Data after every empty Row

I have been trying to copy the first highlighted row of each new data after empty row and i have looked around to find a way which could do this but cannot find.
I can do this manually by putting name of rows to copy but code should be dynamic because rows order can be changed but there must be empty rows after new data.
Any help will be appreciated.
after copying and pasting the result would be like this.
My try
Sub copynextfirstrow()
lastRow = Sheets("Sheet1").Cells(.Rows.Count, "A").End(xlUp).Row
Sheets("Sheet1").Range("A1:A" & lastRow).Copy
Sheets("Sheet2").Range("A1").Cells.PasteSpecial
End Sub
Try the next code, please:
Sub copynextfirstrow()
Dim sh1 As Worksheet, sh2 As Worksheet, lastRow As Long, i As Long, rngCopy As Range
Set sh1 = Sheets("Sheet1")
Set sh2 = Sheets("Sheet2")
lastRow = sh1.cells(sh1.rows.count, "A").End(xlUp).row
For i = 1 To lastRow
If WorksheetFunction.CountA(sh1.rows(i)) = 0 And WorksheetFunction.CountA(sh1.rows(i + 1)) > 0 Then
If rngCopy Is Nothing Then
Set rngCopy = sh1.rows(i + 1)
Else
Set rngCopy = Union(rngCopy, sh1.rows(i + 1))
End If
ElseIf i = 1 And WorksheetFunction.CountA(sh1.rows(i)) > 0 Then
Set rngCopy = sh1.rows(i)
End If
If Not rngCopy Is Nothing Then
rngCopy.Copy
sh2.Range("A1").cells.PasteSpecial
End If
End Sub
It should be fast enough, firstly making a Union of the rows to be copied and pasting all the range at once.
I couldn't understand that an empty row is one having only a cell in A:A empty, so I created a piece of code which considers an empty row the one not having any record on all columns...
Quick example: search for blank cells and see if offset values exist:
Sub Blah()
Dim Cell As Range
Dim rng As Range
Set rng = Application.Intersect(Sheets("Sheet1").UsedRange, Sheets("Sheet1").Range("A:A")).SpecialCells(xlCellTypeBlanks)
For Each Cell In rng
If Cell.Offset(1, 0) <> "" Then Debug.Print Cell.Offset(1, 0)
Next Cell
End Sub

Choosing Specific Cells in VBA?

I've tried multiple codes without luck. I have an excel sheet with 1800 rows and the following columns: ProgramCode, StudyBoard, FacultyID and ProgramType.
In the StudyBoard column there are some cells that are empty. I will then find all the empty cells in StudyBoard and their corresponding information from the other columns. Once I've found the desired cells, they must be overwritten in a new sheet.
I have the following codes, and couldn't continue, because even what I try isn't working.
Dim ws As Worksheet
Dim StudyBoardCol As Range
Dim PromgramCodeCol As Range
Dim rndCell As Range
Dim foundId As Variant
Dim msg As String
Dim FacultyIdCol As Range
Dim ProgramTypeLetter As Range
Set ws = ThisWorkbook.Worksheets("SSBB")
Set StudyBoardCol = ws.Range("A2:A" & ws.Cells(ws.Rows.Count, "A").End(xlUp).Row)
Set ProgramCodeCol = ws.Range("B2:B" & ws.Cells(ws.Rows.Count, "B").End(xlUp).Row)
Set FacultyIdCol = ws.Range("C2:C" & ws.Cells(ws.Rows.Count, "C").End(xlUp).Row)
Set ProgramTypeLetter = ws.Range("D2:D" & ws.Cells(ws.Rows.Count, "D").End(xlUp).Row)
For i = 2 To 1800
Set rndCell = StudyBoardCol.Cells(Int(Rnd * StudyBoardCol.Cells.Count) + 1)
FacultyIdCol = Application.Match(rndCell.Value, ProgramCodeCol, 0)
ProgramTypeLetter = Application.Match(rndCell.Value, ProgramCodeCol, 0)
You could use SpecialCells to “isolate” blank ones
Dim cell As Range
Dim newSheet As Worksheet
Set newSheet = Sheets.Add
With ThisWorkbook.WorkSheets("SSBB") ‘reference “SSBB” sheet
For Each cell in .Range("A2", .Cells(.Rows.Count, "A").End(xlUp)).SpecialCells(xlCellTypeBlanks) ‘ loop through referenced sheet column A blank cells from row 2 down to last not empty one
cell.Resize(,3).Copy destination:=newSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1) ‘ copy range next to current cell and paste to newSheet column A first empty cell
Next
End With
Or use Autofilter (you probably want to add a test that cells are present to be copied before attempting to set rng
Option Explicit
Public Sub TransferBlankStudyBoard()
Dim rng As Range
With ThisWorkbook.Worksheets("SSBB").UsedRange 'Or limit to columns A:D
.AutoFilter
.AutoFilter Field:=1, Criteria1:="="
Set rng = ActiveSheet.AutoFilter.Range
rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
rng.Offset(1, 0).Resize(rng.Rows.Count - 1).EntireRow.Delete
.AutoFilter
End With
End Sub

VBA Lean Coding: Dynamic Multiple Sheet Vlookup Galore

Code below doesnt run. Poorly done over all. Please let me know if you have any questions. Willing to share file.
In a nutshell, what I am trying to do is as follows:
Source Sheet contains the PO forecast by Month. Output sheet is more organized has the same POs but formatted differently. Check screenshot link below before your brain starts hurting. I need to match the Monthly PO (stands for Purchase Order) forecast by month on the Sourcesheet to the POs by month on the output sheet.
If the outputsheet column E contains text "PO labor or PO materials" Then perform Vlookup, otherwise skip. Vlookup matches the PO monthly forecast in the sourcesheet to the output sheet. values must be matched to the month. Loop the if then function until end of outputsheet. After finishing copy and paste any cells in the defined output vlookup range to copy and paste value to reduce multiple coding. at the end you will find screen shots.
Sub NB_Run_Forecast_Upload()
Dim rng1 As Range 'Source Sheet this will set the range in which you want this formula to appear
Dim cl1 As Range
Dim rng2 As Range 'Output Sheet
Dim cl2 As Range 'Output Sheet
Dim rng3 As Range 'Outsheet Range for If Then Statement. Col C must have either "PO Labor" or "PO Materials" to execute Vlookup otherwise skip
Dim strFormula1 as String `string to hold the formula text
Dim SourceLastRow As Long
Dim OutputLastRow As Long
Dim sourceSheet As Worksheet
Dim outputSheet As Worksheet
Dim DataValidation As Worksheet
Set sourceSheet = Worksheets("NB & COAX PO Detail test")
Set outputSheet = Worksheets("New Build & Coax test")
Set DataValidation = Worksheets("Data Validation")
Set rng1 = sourceSheet.Range("I5:AB1339") 'Range hardcoded; need it to go to end
Set rng2 = outputSheet.Range("G1:R5000") 'Range hardcoded; need it to go to the end of rng3
Set rng3 = output.Sheet.Range("C1:C5000") 'Range for If Then statement
'nothing happens in sourceSheet. it is basically, the area where information is stored for vlookup
On Error Resume Next
With sourceSheet 'this might be a double declaration as rng1 does declare
SourceLastRow = .Cells(.Rows.Count, "I").End(xlUp).Row
End With
With outputSheet
'if statement to check if Col C contains either "PO Labor" or "PO Materials"
For Each cl1 In rng2 'my translation: for each cell in rng2 perform the below
If rng3.Value = "PO Materials" Then 'i would prefer to add OR statement to add "PO Labor" reduce redundancy
cl2.Forumla = MyLookupFormula
Else
If rng3.Value = "PO Labor" Then
c2.Forumla = MyLookupFormula
End If
Next rng2 'next col same row until after same row Col R it goes down the row in the outputsheet
End With
Function Colindexnum() As Integer 'i coded the Col number referenec for each month in the Outputsheet that corresponds to the same month in the Sourcesheet
'it's similar to =vlookup(A1, A2:C2, ColIndexNum,0) ColIndexNum changes to each month, its constant in the outputsheet but changes in the sourcesheet
'because every time period a month is deleted. final range is till Dec
Colindexnum = (Application.WorksheetFunction.VLookup(outputSheet.Range("G3:R3"), DataValidation.Range("H30:I41"), 2, False))
End Function
Function MyLookupFormula() As Variant
If Not IsError(Application.WorksheetFunction.VLookup(outputSheet.Range("E:E"), rng1, Colindexnum, False)) Then
MyLookupFormula = (Application.WorksheetFunction.VLookup(outputSheetRange("E:E"), rng1, Colindexnum, False))
Else: MyLookupFormula = vbNullString
End Function
'after each lookup I want to copy and paste the cell it looked up to avoid too much coding Rng2
With outputSheet
For Each rng2 In .UsedRange
If rng2.Formula Like "*VLOOKUP*" Then rng2.Formula = rng2.Value
Next rng2
End With
End Sub
(Output Sheet & Source Sheet Click the next image) http://imgur.com/SHANSLF&ydjQfb3#0
Finally finished this with the help of several genereous memebers of this community and Chandoo. here is the final code that I put together and that actually works.
Sub MakeFormulas()
Dim SourceLastRow As Long
Dim OutputLastRow As Long
Dim sourceSheet As Worksheet
Dim outputSheet As Worksheet
Dim X As Long
Dim Z As Long
'What are the names of our worksheets?
Set sourceSheet = Worksheets("Sheet1")
Set outputSheet = Worksheets("Sheet2")
'Determine last row of source
With sourceSheet
SourceLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With outputSheet
'Determine last row in col C
OutputLastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
For y = 17 To 28 'Q to AB
For X = 2 To OutputLastRow
If InStr(1, .Range("C" & X), "PO Materials") + InStr(1, .Range("C" & X), "PO Labor") > 0 And Cells(2, y) = "Forecast" Then
'Apply formula
.Cells(X, y).Value = _
Evaluate("=VLOOKUP($E" & X & ",'" & sourceSheet.Name & "'!$A$2:$L$" & SourceLastRow & ",Match(" & Cells(1, y).Address & ",'" & sourceSheet.Name & "'!$A$1:$AD$1,0),0)")
End If
Next
Next
End With
End Sub

Resources