I have an excel sheet and I am trying to use a countifs formula to count the number or records meeting multiple conditions, however in one of the columns there are multiple criterias so I used SUMPRODUCT together with the COUNTIFS function.
I got it to work fine in the sheet but I have no idea on how to get it to work in VBA.
This is what I tried:
Dim lastrow As Long
lastrow = Sheet2.Cells(Sheet2.Rows.Count, "M").End(xlUp).Row
FirstDate = Sheets("Sheet1").Range("C7")
SecondDate = Sheets("Sheet1").Range("E7")
Application.Worksheetfunction.Sumproduct(CountIfs(Sheet2.Range("E2:E" & lastrow), ">=" & FirstDate, Sheet2.Range("E2:E" & lastrow), "<=" & SecondDate, Sheet2.Range("P2:P" & lastrow), {"John";"James";"Peter"}))
I keep getting an error when using the above formula. Can you please tell me what I'm doing wrong.
Thanks in advance.
EDIT: This is the formula I'm trying to mimic:
=Sumproduct(CountIfs(Sheet2!E2:E1000000,">="&Sheet1!C7,Sheet2!E2:E1000000,"<="&Sheet1!E7,Sheet2!E2:E1000000,{"John";"James";"Peter"}))
I don't want VBA to insert this formula into the cell, I'd rather have it calculate the value and then insert the result into the chosen cell.
Seems to work for me:
Sub Tester()
Dim v, wsf
Dim lastrow As Long
lastrow = Sheet2.Cells(Sheet2.Rows.Count, "M").End(xlUp).Row
Set wsf = Application.WorksheetFunction
v = Application.WorksheetFunction.SumProduct(wsf.CountIfs( _
Sheet2.Range("E1:E" & lastrow), ">=" & Sheet1.Range("C7").Value, _
Sheet2.Range("E1:E" & lastrow), "<=" & Sheet1.Range("E7").Value, _
Sheet2.Range("P1:P" & lastrow), Array("John", "James", "Peter")))
Debug.Print v
End Sub
Related
I'm creating a Macro (Excel)
I'm saving the amount of rows used on the sheet via a variable and I need to pass it to a filter range, hope this code helps to explain what I'm trying to do...
Sub Filtering()
Rows("11:11").Select
Selection.AutoFilter
'save the amount of rows used on the sheet
Dim lastRow As Long
lastRow = Range("AC" & Rows.Count).End(xlUp).Row
ActiveSheet.Range("$A$11:$AC$lastRow").AutoFilter Field:=18, Criteria1:=">10", _
Operator:=xlAnd
End Sub
The filter will always be on row 11 and columns will always be from A to AC but the number of rows is different on each Excel file. can you guys help? pls
You are very close. Similar approach to when you defined your range for the last row. The variable has to be outside the " "
Option Explicit
Sub Filtering()
'Rows("11:11").Select 'Redudant
'Selection.AutoFilter 'Redudant
'save the amount of rows used on the sheet
Dim lastRow As Long
lastRow = Range("AC" & Rows.Count).End(xlUp).Row
ActiveSheet.Range("$A$11:$AC" & lastRow).AutoFilter Field:=18, Criteria1:=">10", _
Operator:=xlAnd
End Sub
Result
I'm trying to clculate a formula that takes number from Column D and calcultes this number minus 14 in column C.
Then, I'm triyng to autofill the range down to the first cell I calculate.
at first it was working, but now it shows me an error:
appliction-defined or object-defined error
to this line of code
Selection.AutoFill Destination:=ActiveCell.Range("A1:A" & lastrow)
If someone would help me to solve this prblem I'll be glad.
OP_wb.Sheets("Optic Main").Activate
Dim FirstRow As Range
Dim lastrow As Range
Set FirstRow = Range("C1").End(xlDown).Offset(1, 0)
Set lastrow = Range("E1").End(xlDown).Offset(0, -2)
Range("E1").End(xlDown).Offset(0, -2).Select
Range(FirstRow, lastrow).FormulaR1C1 = "=(c4-14)"
Selection.AutoFill Destination:=ActiveCell.Range("A1:A" & lastrow)
Instead of
Selection.AutoFill Destination:=ActiveCell.Range("A1:A" & lastrow)
try
Selection.AutoFill Destination:=ActiveCell.Range("A1:A" & lastrow.Row)
I have made two functions that makes a calculation from two different linest (UpperCalc and LowerCalc). This works fine.
Then I will need to fill in formulas for an unknown number of cells (depending on the input on another sheet). I have been able to fill in formulas for the correct number of cells. But when I try to include an "IF"-formula in the VBA programming together with the function names, it does not work? My VBA code to fill in the formula looks like this now;
Dim lastRow As Long, i As Long, ws1 As Worksheet, ws2 As Worksheet
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
lastRow = ws1.Range("B" & Rows.Count).End(xlUp).Row
With ws1
For i = 2 To lastRow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then _
ws2.Range("A" & i).Value = ws1.Range("A" & i).Value
ws2.Range("B" & i).Value = ws1.Range("B" & i).Value
ws2.Range("C" & i).Formula = "=IF(RC[-1]>R4C12,UpperCalc(RC[-1]),LowerCalc(RC[-1]))"
Next i
End With
End If
I am able to insert formula with one of these functions (for instance ws2.Range("C" & i).Formula = "=UpperCalc(RC[-1])", and also only with an "IF" formula (for instance ws2.Range("C" & i).Formula = "=IF(RC[-1]>R4C12,RC[-1],RC[-1]^2)" - This is of course not the actual calculation needed - only to test the "IF"-function).
Since the calculation behind UpperCalc and LowerCalc is rather "dirty", I would like to utilize the functions. Any ideas?
I have an issue. I am filtering from a big product table (with about 32'000 rows) the products that I need and sort it first by the product name and then by the delivery number.
My issue is, that if I wanna filter and sort numbers as product names (which is also possible), it does not sort correctly (see picture).
Picture of the filtered and sorted table
My code is this one:
'*************************************************************
'Filter Product Code
Set myrange = Range("A1:A" & lastrow)
For Each c In myrange
If Len(c.Value) <> 0 Then
ThisWorkbook.Worksheets(Worksheets.Count).Columns("A:D").AdvancedFilter xlFilterCopy, _
Sheet1.Range("A1:A" & lastrow), Sheet1.Range("G1"), False
End If
Next
'Sheet1.Range("51:100").RemoveDuplicates Columns:=3, Header:=xlYes
'*******************************************************************
'Sort the filtered list first by Product Code then by the Delivery number
Dim lngRow As Long
Dim lngRowMax As Long
Dim wsf As WorksheetFunction
With Sheet1
lastrow = Cells(Rows.Count, 8).End(xlUp).Row
Range("G2:J" & lastrow).Sort Key1:=Range("G2:G" & lastrow), _
Order1:=xlAscending, Key2:=Range("I2:I" & lastrow), _
Order1:=xlAscending, Header:=xlNo
Set wsf = Application.WorksheetFunction
lngRowMax = .UsedRange.Rows.Count
End With
How can I proceed to have it sorted correctly. First the same product codes, then by the delivery number (ascending) as I want to sell the oldest products first.
Thank you for your reply.
Now I found the solution for it. Only a small adjustment. The code for the sorting looks as follows now:
Dim lngRow As Long
Dim lngRowMax As Long
Dim wsf As WorksheetFunction
With Sheet1
lastrow = Cells(Rows.Count, 8).End(xlUp).Row
Range("G1:J" & lastrow).Sort Key1:=Range("G1:G" & lastrow), _
Order1:=xlAscending, Key2:=Range("I1:I" & lastrow), _
Order2:=xlAscending, Header:=xlYes, DataOption1:=xlSortTextAsNumbers
Set wsf = Application.WorksheetFunction
lngRowMax = .UsedRange.Rows.Count
End With
VBA is throwing the above given error on the line Sheets("Sheet1").Range("A" & i).Copy Destination:=Sheets("Sheet2").Range("A" & i & "A" & LastCol - 1)
What I am trying to do is actually to copy the "A" & i cell (in first iteration it's A2) to a range in the second worksheet named Sheet2.
Sub FindFill()
Dim DatesRange As Range
Dim i As Integer
Dim TransposeThis As Range
Dim LastCol As Integer
If WorksheetFunction.CountA(Cells) > 0 Then
LastColumn = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
End If
With Sheets("Sheet1")
Set DatesRange = Range("B2" & LastCol)
End With
i = 1
Do While i <= ActiveSheet.Rows.Count
Sheets("Sheet1").Range("A" & i + 1).Copy Destination:=Sheets("Sheet2").Range("A" & i & "A" & LastCol - 1)
i = i + 1
Loop
End
End Sub
You are missing a ":" before "A"
Range("A" & i & ":A" & LastCol - 1)
FOLLOWUP
After I went through your comments, I saw lot of errors in your code
1) You have dimmed i as Integer. This can give you an error in Excel 2007 onwards if your last row is beyond 32,767. Change it to Long I would recommend having a look at this link.
Topic: The Integer, Long, and Byte Data Types
Link: http://msdn.microsoft.com/en-us/library/aa164754%28v=office.10%29.aspx
Quote from the above link
Integer variables can hold values between -32,768 and 32,767, while Long variables can range from -2,147,483,648 to 2,147,483,647
2) You are finding the Last Column But in Which Sheet? You have to fully qualify the path Like this.
If WorksheetFunction.CountA(Sheets("Sheet1").Cells) > 0 Then
LastCol = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
End If
Same is the case with
With Sheets("Sheet1")
Set DatesRange = Range("B2" & LastCol)
End With
You are missing a DOT before Range
This is the correct way...
.Range("B2....
Also Range("B2" & LastCol) will not give you the range that you want. See the code below on how to create your range.
3) You are using a variable LastColumn but using LastCol. I would strongly advise using Option Explicit I would also recommend having a look at this link (SEE POINT 2 in the link).
Topic: To ‘Err’ is Human
Link: http://www.siddharthrout.com/2011/08/01/to-err-is-human/
4) What happens if there .CountA(Sheets("Sheet1").Cells) = 0? :) I would suggest you this code instead
If WorksheetFunction.CountA(Sheets("Sheet1").Cells) > 0 Then
LastCol = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
Else
MsgBox "No Data Found"
Exit Sub
End If
5) ActiveSheet.Rows.Count will not give you the last active row. It will give you the total number of rows in that sheet. I would recommend getting the last row of Col A which has data.
You can use this for that
With Sheets("Sheet")
LastRow =.Range("A" & .Rows.Count).End(xlup).row
End With
Now use LastRow instead of ActiveSheet.Rows.Count You also might want to use a For Loop so that you don't have to increment i every time. For example
For i = 1 to LastRow
6) Finally You should never use End. Reason is quite simple. It's like Switching your Computer using the POWER OFF button. The End statement stops code execution abruptly, without invoking the Unload, QueryUnload, or Terminate event, or any other Visual Basic code. Also the Object references held (if any) by other programs are invalidated.
7) Based on your image in Chat, I believe you are trying to do this? This uses a code which doesn't use any loops.
Option Explicit
Sub FindFill()
Dim wsI As Worksheet, wsO As Worksheet
Dim DatesRange As Range
Dim LastCol As Long, LastRow As Long
If Application.WorksheetFunction.CountA(Sheets("Sheet1").Cells) = 0 Then
MsgBox "No Data Found"
Exit Sub
End If
Set wsI = Sheets("Sheet1")
Set wsO = Sheets("Sheet2")
With wsI
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set DatesRange = .Range("B1:" & Split(Cells(, LastCol).Address, "$")(1) & 1)
.Columns(1).Copy wsO.Columns(1)
DatesRange.Copy
wsO.Range("B2").PasteSpecial xlPasteValues, _
xlPasteSpecialOperationNone, False, True
.Range("B2:" & Split(Cells(, LastCol).Address, "$")(1) & LastCol).Copy
wsO.Range("C2").PasteSpecial xlPasteValues
End With
End Sub