I have a big problem with my script VBA, I want to create a script VBA which will enable to make the sum of some cells on a sheet and to display them on another sheet according to some criteria.
But the function SumIfs is returning zero value.
This is my script:
If Worksheets("Test").Range("B2").Text = Worksheets("Nomen").Range("K3").Text Then
Worksheets("Test").Range("C23").Value = Application.WorksheetFunction.SumIfs(Worksheets("DETAILS").Range("H2:H174"), Worksheets("DETAILS").Range("B2:B174"), Worksheets("Nomen").Range("K3"), Worksheets("DETAILS").Range("J2:J174"), Worksheets("Test").Range("C2")
End If
Picture1
Picture2
You are trying to sum text hence zero.
I put into variables to make easier to debug.
Sub test()
Dim wb As Workbook
Set wb = ThisWorkbook
Dim sumRange As Range
Set sumRange = wb.Worksheets("DETAILS").Range("H2:H174")
Dim critRange1 As Range
Set critRange1 = Worksheets("DETAILS").Range("B2:B174")
Dim crit1 As Variant
crit1 = Worksheets("Nomen").Range("K3")
Dim critRange2 As Range
Set critRange2 = Worksheets("DETAILS").Range("J2:J174")
Dim crit2 As Variant
crit2 = Worksheets("Test").Range("C2")
MsgBox Application.WorksheetFunction.SumIfs(sumRange, critRange1, crit1, critRange2, crit2)
End Sub
If I fill each range with 1 and also try to match on one I get 174 back. If I populate sumRange with "A", in the same way you have used text, I get 0. i.e. if I replace all the 1's with A.
Related
As a learning exercise & possible use in future code I have created my first Excel VBA function to return the activecell row number in any Excel Table (as opposed to the sheet itself) . Essentially it simply finds the active row in the sheet, then finds the row number of the table header which is then subtracted from the cell row number to return the row number of the table which can then be used in subsequent code. However, while it works, it dosen't look the most efficient Can anyone improve it?
Sub TableRow()
Dim LORow As Integer
Dim TbleCell As Range
Set TbleCell = Activecell
Call FuncTableRow(TbleCell, LORow)
MsgBox LORow
End Sub
Public Function FuncTableRow(ByRef TbleCell As Range, LORow As Integer) As Range
Dim LOName As String
Dim LOHeaderRow, Row As Integer
LOName = Activecell.ListObject.Name
Row = Activecell.Row
LOHeaderRow = ActiveSheet.ListObjects(LOName).HeaderRowRange.Row
LORow = Row - LOHeaderRow
Debug.Print (LORow)
End Function
This question will probably get closed for not being specific enough but the most obvious item (to me) is your usage of a custom function. Your function is not actually returning anything, it's only running a debug print. To have your function actually return the row number, you would set it as a type Long (not integer) and include the function name = to the number.
I didn't actually test your function but assuming LORow is dubug printing the proper answer then it should work like this:
Public Function FuncTableRow(ByRef TbleCell As Range, LORow As Integer) As Long
Dim LOName As String
Dim LOHeaderRow, Row As Integer
LOName = Activecell.ListObject.Name
Row = Activecell.Row
LOHeaderRow = ActiveSheet.ListObjects(LOName).HeaderRowRange.Row
LORow = Row - LOHeaderRow
Debug.Print (LORow)
FuncTableRow = LORow
End Function
You also don't Call a function, you can just insert it as itself in a subroutine.
You are using LORow as an input variable but then changing it. That's typically a bad practice.
You should not be using ActiveSheet grab the worksheet from TbleCell.Worksheet
You would almost never use activecell as part of a Custom Formula.
Dim LOHeaderRow, Row As Integer should actually be Dim LOHeaderRow as Long, Row As Long. As you currently have it LOHeaderRow is undefined/Variant.
There's probably more. I would restart your process with a simpler task of returning the last used cell in a worksheet. There's a dozen ways to do this and lots of help examples.
Take a look at this TheSpreadsheetGuru.
Here are some variables that might help you.
Sub TableVariables()
Dim ol As ListObject: Set ol = ActiveSheet.ListObjects(1)
Dim olRng As Range: Set olRng = ol.Range ' table absolute address
Dim olRngStr As String: olRngStr = ol.Range.Address(False, False) ' table address without absolute reference '$'
Dim olRow As Integer: olRow = ol.Range.Row ' first row position
Dim olCol As Integer: olCol = ol.Range.Column ' first column position
Dim olRows As Long: olRows = ol.Range.Rows.Count ' table rows including header
Dim olCols As Long: olCols = ol.ListColumns.Count ' table columns
Dim olListRows As Long: olListRows = ol.ListRows.Count ' table rows without header
End Sub
I'm trying to write a VBA code thta helps me Vlookup value from another location on C Drive, but apparently only the first two cells work.
Could you help me correct this code? Really new to VBA and just trying my waters with the Do While Looops.
Sub Copy3()
Dim lookfor As Range
Dim table_array As Range
Dim table_array_col As Integer
Dim lookFor_col As Integer
Dim Wbk As Workbook
Dim Rows As Integer
Rows = 2
Do While Rows < 60
Set lookfor = Cells(Rows, 1)
Set Wbk = Workbooks.Open("C:\Users\XXX.xlsx")
Set table_array = Wbk.Sheets("Sheet1").Range("B2:H60")
table_array_col = 5
lookFor_col = ThisWorkbook.Sheets("Sheet1").UsedRange.Columns.Count - 2
ThisWorkbook.Sheets("Sheet1").Cells(Rows, lookFor_col).Formula = Application.VLookup(lookfor.Value, table_array, table_array_col, 0)
Rows = Rows + 1
Loop
End Sub
I think I found the error. Set lookfor = Cells(Rows, 1) was missing a qualifier, and was likely not referencing the correct workbook. Workbooks.Open changes the Active Workbook. Unqualified ranges are prone to cause errors when the Active Workbook changes during execution.
I corrected that by adding a reference to ThisWorkbook.Sheets("Sheet1") and also cleaned up some other minor problems that I noticed. Notably, Rows is one of the Range Objects built into Excel VBA. Its best to avoid using defined object names as your variable names when you can.
Sub Copy3()
Const table_array_col As Integer = 5
Dim lookfor As Range
Dim Row As Integer
Dim lookFor_col As Integer
lookFor_col = Sh.UsedRange.Columns.Count - 2
Dim Wbk As Workbook
Set Wbk = Workbooks.Open("C:\Users\XXX.xlsx")
Dim table_array As Range
Set table_array = Wbk.Sheets("Sheet1").Range("B2:H60")
Dim Sh As Worksheet
Set Sh = ThisWorkbook.Sheets("Sheet1")
For Row = 2 To 59
Set lookfor = Sh.Cells(Row, 1)
Sh.Cells(Row, lookFor_col).Value = Application.VLookup(lookfor.Value, table_array, table_array_col, 0)
Next Row
End Sub
I am currently working on a spreadsheet and would like to utilize vlookup, but would prefer if it was through VBA.
I attached two screenshots of sheets, so you guys could visually see what i am trying to do.
Essentially I am trying to pull the "Priority" from sheet IW38 column K and place it on sheet "IW47" column R, but by using the order number as the matching info. The order numbers are in Column "E" in sheet IW47 and Column "A" in sheet IW47.
Below is the current macro I attempted to use:
Sub PriorityNUM()
'Variables----------------------------------------
'Defining WorkBook
Dim wb As Workbook
'Defining Sheets----------------------------------------------
'Working Asset Sheet
Dim IW47ws As Worksheet
'Sheet for Parts List Submission
Dim IW38ws As Worksheet
'Setting Worksheets
Set IW47ws = Sheets("IW47")
Set IW38ws = Sheets("IW38")
'Defigning Ranges within Worksheets----------------------------
Dim IW38rng As Range
'Setting Ranges within Submit Worksheets-------------------
Set IW38rng = IW38ws.Range("A:Z")
'Defining the Last Cell in Each Task Column----------------
Dim IW47last As Long
'Assigning Values to Last Row Variables
IW47last = IW47ws.Range("E" & Rows.Count).End(xlUp).Row
'Updating Drawings Identified---------------------------------------------------
Dim PriorityCell As Range
Dim PriorityLookup As String
For Each PriorityCell In IW47ws.Range("R:R")
If IsEmpty(DICell.Offset(0, -13).Value) Then
Exit For
End If
On Error Resume Next
PriorityLookup = WorksheetFunction.VLookup(PriorityCell.Offset(0, -13), IW38rng, 11, False)
If Err = 0 Then
PriorityCell.Value = PriorityLookup
Else
Err.Clear
End If
On Error GoTo 0
Next PriorityCell
End Sub
Any help would be greatly appreciated.
Thanks,
Juan
Readability
OP, your code can be restructured like below. I also used some short hand variables to make things easier. Your variable names would ideally be concise (easy to read and short to type). Readability goes a long way in troubleshooting.
Let me know once you have seen this so I can delete
Sub PNum()
Dim ws47 As Worksheet: Set ws47 = ThisWorkbook.Sheets("IW47")
Dim ws38 As Worksheet: Set ws38 = ThisWorkbook.Sheets("IW38")
Dim Arr As Range: Set Arr = ws38.Range("A:K")
Dim LR As Long, MyCell As Range, Priority As String
LR = ws47.Range("E" & ws47.Rows.Count).End(xlUp).Row
For Each MyCell In ws47.Range("R2:R" & LR)
If IsEmpty(MyCell.Offset(-13)) Then Exit Sub
On Error Resume Next
Priority = WorksheetFunction.VLookup(MyCell.Offset(, -13), Arr, 11, 0)
If Err = 0 Then
MyCell = Priority
Else
Err.Clear
End If
On Error GoTo 0
Next MyCell
End Sub
I've been trying to look this up everywhere and I can't seem to find the answer or get it to work.
I have the code
'Define Variables for cell ranges'
Dim BidItem As Range
Dim BidItemDes As Range
Dim BidItemUnit As Range
Dim BidItemQTY As Range
Dim BidItemUP As Range
'Store the sheet range into the variables'
Set BidItem = Sheets("BidItems").Range("A1:A" & Range("A1").End(xlDown).Row)
Set BidItemDes = Sheets("BidItems").Range("B1:B" & Range("B1").End(xlDown).Row)
Set BidItemUnit = Sheets("BidItems").Range("C1:C" & Range("C1").End(xlDown).Row)
Set BidItemQTY = Sheets("BidItems").Range("D1:D" & Range("D1").End(xlDown).Row)
Set BidItemUP = Sheets("BidItems").Range("E1:E" & Range("E1").End(xlDown).Row)
Set BidItemValue = Sheets("BidItems").Range("F1:F" & Range("F1").End(xlDown).Row)
Set BidItemValue = Sheets("BidItems").Range("F1:F" & Range("F1").End(xlDown).Row)
What I need to do is have all the data in range BidItemQTY and Multiply it by the range BidItemUP
and then output that answer to the range BidItemValue.
I have the last line of code setup to start the function but
I can't seem to grasp on how to do math functions in VBA with Variables.
Consider this tiny example:
Sub dural()
Dim second As Range
Dim first As Range, prodt As Long
Set first = Range("A1:A3")
Set second = Range("B1:B3")
prodt = Application.WorksheetFunction.SumProduct(first, second)
MsgBox prodt
End Sub
EDIT#1:
To get the individual products stored in cells, use:
Sub dural()
Dim second As Range
Dim first As Range, prodt As Long
Dim third As Range
Set first = Range("A1:A3")
Set second = Range("B1:B3")
Set third = Range("C1:C3")
For i = 1 To 3
third(i, 1) = first(i, 1) * second(i, 1)
Next i
End Sub
Notes:
since the ranges are not single cells, we treat them as two-dimensional
it may be possible to avoid the loop using Transpose()
in this case the one-dimensional will also work:
For i = 1 To 3
third(i) = first(i) * second(i)
Next i
I want to use VLookup in VBA code to lookup values from a different workbook (Excel 2010 VBA). I'm getting the error above on the last line of the code below:
Sub GetFundValues(Source As String, Target As String, wb As Workbook)
Dim nIdx As Integer
Dim SourceSheet As Worksheet
Dim SourceFile As Workbook
Dim s2 As String
Dim s3 As String
Dim rng As Range
s2 = wb.Sheets(Target).Range("C2").Value
Set SourceFile = Application.Workbooks.Open("D:\Mydocs\Finance\inv.xls")
Set SourceSheet = SourceFile.Worksheets(Source)
s3 = SourceSheet.Range("A3").Value
Set rng = SourceSheet.Range("A3:A30")
nIdx = 3
With wb.Sheets(Target)
While wb.Sheets(Target).Range("H" & nIdx).Value <> ""
s2 = wb.Sheets(Target).Range("H" & nIdx).Value
wb.Sheets(Target).Range("B" & nIdx).Value = Application.WorksheetFunction.VLookup(s2, rng, 3, False)
The values of the s2, s3 and rng variables are set correctly (they are there for debugging purposes), and the value column in the Vlookup (column #3) contains valid values.
I can't think what other problem in the VLookup might be causing this. Any ideas??
Just spotted this:
Set rng = SourceSheet.Range("A3:A30")
The range you are looking in is only 1 column wide. As you are trying to return data from the 3rd column, your range needs to be at least 3 columns wide:
Set rng = SourceSheet.Range("A3:C30")