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
Related
Using VBA, I am trying to search for each value in column A of sheet 1, and match it with column A of sheet 2. If a value is found in sheet 2, update column B to "Yes"
Sheet 1
Sheet 2
So far I have:
Sub UpdateStatus()
Dim list() As Variant
Dim item As Integer
'Assign range to a variable
list = Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row)
'Loop Through Rows
For item = 1 To UBound(list)
'this is where I am stuck
Next item
End Sub
Sheet 2 should look like this afterwards:
Why loop if you can use Excel's engine?
Solution using Excel formulas
Sub Update_Status()
Dim Formula As String
Dim searchRng As Range
Dim valueRng As Range
Dim statusRng As Range
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
Set valueRng = ws1.Range("A2:A" & LastRow("A", ws1)) ' A2, since you have header
Set searchRng = ws2.Range("A1:A" & LastRow("A", ws2))
Set statusRng = valueRng.Offset(0, 1)
' =IF(COUNTIFS(Sheet2!$A$2:$A$4,Sheet1!A2),"Yes","No")
Formula = "=IF(COUNTIFS(" & _
searchRng.Address(True, True) & "," & _
valueRng.Cells(1, 1).Address(False, False) & _
"),""Yes"",""No"")"
statusRng.Formula = Formula
' In case calculation is turned off
Application.Calculate
' If we prefer hardcoded values
statusRng.Copy
statusRng.PasteSpecial xlPasteValues
Application.CutCopyMode = False ' Flush clipboard
End Sub
Private Function LastRow(Col As String, Ws As Worksheet) As Long
LastRow = Ws.Range(Col & Rows.Count).End(xlUp).Row
End Function
This seems to work:
Sub UpdateStatus()
Dim list() As Variant
Dim item As Integer
Dim FoundCell As Range
Dim SearchValue As String
Dim Sheet2 As Worksheet
Set Sheet2 = Worksheets("Sheet2")
'Assign range to a variable
list = Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row)
'Loop Through Rows
For item = 1 To UBound(list)
SearchValue = list(item, 1)
Set FoundCell = Sheet2.Range("A2:A6").Find(What:=SearchValue)
If Not FoundCell Is Nothing Then
Sheet2.Range("B" & FoundCell.Row).Value = "Yes"
Else
MsgBox (SearchValue & " not found")
End If
Next item
End Sub
wht i want is if cell value in column A is 60 then cell value in the same row in column C must equal FF code below.
Sub column_check2()
Dim c As Range
Dim alastrow As Long
Dim clastrow As Long
alastrow = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).Row
clastrow = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).Row
For Each c In Range("A2:A3" & alastrow & ",C2:C3" & clastrow)
If Not c.Value = "60" And c.Value = "FF" Then
MsgBox "error" & c.Address
End If
Next c
End Sub
You just need to loop through each value in Column A and check your criteria (Cell = 60). You can then adjust the value in Column C by using Offset to navigate 2 cells to the right from the current cell in the loop
Sub Looper()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1") 'Update Sheet Name
Dim lr As Long, Target As Range
lr = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
For Each Target In ws.Range("A2:A" & lr)
If Target = 60 Then
Target.Offset(0, 2) = "FF"
End If
Next Target
End Sub
Even better, consider the way you would likely do this manually. Filter Column A for your target value and then just modify the resultant cells in Column C. Recreating this in VBA results in a solution more efficient than a loop (the larger the data set, the larger the efficiency gains)
Sub Filter()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim lr As Long: lr = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
ws.Range("A1:A" & lr).AutoFilter Field:=1, Criteria1:=60 'Filter
ws.Range("C2:C" & lr).SpecialCells(xlCellTypeVisible).Value = "FF" 'Apply Values
ws.AutoFilterMode = False 'Remove Filter
End Sub
I want to calculate the Average of column Q and place the answer 2 cells below the last value in column Q. The code I'm using performs the calculation and gives me the average of the values between Q2 and the end of column Q if I insert a msgbox but I can't get it to put the answer into the correct cell.
Sub AverageRates()
With ActiveSheet
'Determine last row
Dim lastRow As Long
Dim cellRange As Range
Dim myAvg As Double
lastRow = .Cells(.Rows.Count, "D").End(xlUp).Row
'Average rate calculation
myAvg = Application.WorksheetFunction.Average(Range("Q1:Q" & lastRow))
Range("Q2:Q" & lastRow).Value = myAvg
'place the calculated average value 2 cells below the last cell in column Q
Set cellRange = Range("Q" & Lastrow").offset(2,0).select
End With
End Sub
You were pretty close ... try:
Option Explicit
Sub AverageRates()
Dim lastRow As Long
Dim myAvg As Double
With ActiveSheet
lastRow = .Cells(.Rows.Count, "Q").End(xlUp).Row
myAvg = Application.WorksheetFunction.Average(Range("Q1:Q" & lastRow))
Range("Q" & lastRow).Offset(2, 0).Value = myAvg
End With
End Sub
For a multi-column answer, assuming the columns are not equal in length (if so, then you could use an approach like #BigBen suggests), then you could do something like:
Sub AverageRates2()
Dim mySheet As Worksheet
Dim myColumn As Range
Dim myDataSet As Range
Dim lastRow As Long
Dim myAvg As Double
Set mySheet = ActiveSheet
For Each myColumn In mySheet.Range("J:Q").Columns
lastRow = mySheet.Cells(mySheet.Rows.Count, myColumn.Column).End(xlUp).Row
myAvg = Application.WorksheetFunction.Average(myColumn.Rows(1).Resize(lastRow, 1))
myColumn.Rows(lastRow).Offset(2, 0).Value = myAvg
Next
End Sub
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!
My objective is to compare data in a range in Ws1 with data in a range in ws2, and copy those values that repeat in ws3.
Ideally I would like to copy the value found and the rest of the information to the right of that cell (from ws2), but for now I am happy just copying the value found.
I decided to use a loop for this but I was getting an infinite looping, and now that I re-summarize; I am getting:
range of object _ global failed" error and it points to: "With
Range(ws3.cells(i, 1))
Sub quicktests()
Dim ws1, ws2, ws3 As Worksheet
Dim ColNum, ColNum2 As Long
Dim rng, Range2 As Range
Dim lRow1, lRow2, lCol2 As Integer
ColNum = 9
ColNum2 = 14
lRow1 = 347
Set ws2 = Sheets("Filled today")
With ws2
lCol2 = .cells(1, .Columns.Count).End(xlToLeft).Column
'MsgBox lCol2
lRow2 = .cells(.Rows.Count, 1).End(xlUp).Row
'MsgBox lRow2
Set Range2 = .Range(.cells(1, ColNum2), .cells(lRow2, lCol2))
End With
Set ws3 = Sheets("Duplicates filled and hiring")
Set ws1 = Sheets("Reconciliated Recruiment Plan")
For i = 1 To lRow1
With ws1
Set rng = .cells(i, ColNum)
End With
With Range(ws3.cells(i, 1))
.Formula = "=VLookup(rng, Range2, ColNum, False)"
.Value = .Value
End With
Next i
End Sub
Looking at just the part with the VLOOKUP:
You can't used range with one cells() it needs a begining and an end, remove the Range wrapper.
The Vlookup; You need to remove the vba part from the string and concatenate it.
With ws3.cells(i, 1)
.Formula = "=VLookup(" & rng.Address(0,0) & "," & Range2.Address(0,0) & "," & ColNum & ", False)"
.Value = .Value
End With