Function not working because I use dates? - vba

I’m trying to write a function that depends on dates, but I can’t get it to work. Excel keeps telling me that a value that is used in this formula have the wrong data type. So it has to be the date, because I have another function that is exactly the same except for the add of a datevalue.
Someone writes a date in the Excel-cell C10 and then I wan’t the function to summarize certain numbers (predicted inflation rates, column P) from a table (on another sheet in the same workbook) in which it depends on begin-dates (column I) and end-dates (column J).
I’ve checked that Excel interprets cell C10 as a date, it does but with a serial number.
But I don’t see why that is a problem since I use it to compare with other dates (serial numbers)?
Public Function FetchFactorInflation(Product As String, ArgName As String) As Double
Dim Datum As Date
Datum = DateValue(Worksheets("InputTariff").Range("C10").Value)
Dim MinDatum, MaxDatum As Double
MinDatum = "<=" & Datum
MaxDatum = ">=" & Datum
FetchFactorInflation = Application.SumIfs(Worksheets("tariff").Range("P:P"), _
Worksheets("tariff").Range("I:I"), MinDatum, _
Worksheets("tariff").Range("J:J"), MaxDatum, _
Worksheets("tariff").Range("K:K"), Product, _
Worksheets("tariff").Range("L:L"), ArgName)
End Function

The wrong data type comes from here:
MaxDatum = ">=" & Datum
MaxDatum is a double, and you are giving >= to it. It cannot be converted to a Double. Try a way around.
The quickest solution would be to write like this:
Dim MinDatum, MaxDatum
instead of
Dim MinDatum, MaxDatum As Double
Thus MaxDatum would be easily converted to what you need, because it would be variant as well as MinDatum.

Related

Excel Data Conversion Macro Not Recognising Numbers with < at the Start

I am working with lots of laboratory test results that are presented within one column in excel however the results come in different units from different labs so I need to convert some of the data so that all of the lab data is in the same units.
I have created a macro that looks up the lab data that I want to change and will convert the data however some of the results are presented as <0.07 etc. however the macro will not recognise and convert anything with < at the start of the number.
Can anyone suggest a way that I can amend the following macro to also convert lab results that contain < at the start?
Sub CONVERT_UNITS()
'
' CONVERT_UNITS Macro
'
'
ActiveCell.FormulaR1C1 = _
"=IF(RC12=""ug/kg"",RC11/1000,IF(RC12=""mg/l"",RC11*1000,RC11))"
Range("M2").Select
Selection.AutoFill Destination:=Range("M2:M" & Range("L" & Rows.Count).End(xlUp).Row)
Range(Range("M2"), Range("M2").End(xlDown)).Select
End Sub
For reference my lab data is contained in column K with the units presented in column L. I want the converted lab results to be put in column M (see example data below). I am only converting results that are in ug/kg (divide result by 1000) and mg/l (multiply result by 1000), all the other results will remain as they are.
I would create a User Defined Function for that:
Public Function convertResults(ByVal result As Variant, ByVal unit As String) As Variant
Dim hasSmaller As Boolean
If Left(result,1) = "<" Then
hasSmaller = True
result = Replace(result, "<", "")
End If
If unit = "ug/kg" Then result = result / 1000
If unit = "mg/l" Then result = result * 1000
If hasSmaller Then result = "<" & result
convertResults = result
End Function
... and then (for example in cell M2) just write =convertResults(K2, L2).

Find the earliest date in VBA

I have a lot of dates in column D. I need to find the student with the earliest date, and show the following information in a messagebox:
Sub Finddate()
Dim Mn As Integer
Mn = Application.Match(Application.Min(Range("D2:D18288")), Range("D2:D18288"), 0)
MsgBox ("For the student with the earliest date (" & Range("D" & Mn) & ") the following information applies: " & Range("k" & Mn) & ", " & Range("L" & Mn) & " and " & Range("M" & Mn))
End Sub
However when i run the Macro it shows the wrong date. The earliest date in the sheet is 31-08-1996, but it says the earliest date is 01-02-2010 and if i write =min(D2:D18288) in Excel it finds the right date. But i need it to work in VBA as well. And if i change min to max it also finds the wrong date. But if i instead write:
Mn = Application.Match(Application.Max(Range("D2:D18288")), Range("D2:D18288"))
It shows the right date but i need to find the min date not the max date and when i change max to min I get a type mismatch error. I really don’t know what is wrong really hope someone can help me!
Your indexing is off by 1 ................because the data starts out a D2 rather than D1, Mn points to the cell just above the minimum.
When something like this happens, try to replicate the result, using a small sample. E.g. this one, hoping to return Peter6 for the smallest info:
Option Explicit
Public Sub TestMe()
Dim dateRanges As Range
Set dateRanges = Range("D1:D11")
Dim mn As Variant
With Application
mn = .Match(.Min(dateRanges), dateRanges, 0)
End With
MsgBox Range("E" & mn).Value2
End Sub
Once it works, try to fix it with your big example.
You will probably notice that mn should not be Integer as far as Integer is up to 32767 and this parsed to a date is 16-September-1989, which is long time ago. In your case it is not an error, because you are not referencing mn directly to a date, but it may happen at a later.

Assigning a variable declared as integer to a formula

I'm trying to use a variable inside a formula, which has previously been declared as integer in the code, can someone help me with this matter?
So basically I have:
Dim R_count As Integer
R_count = Range("C" & Rows.Count).End(xlUp).Row
which counts the number of row. Then I am trying to use the variable R_count in the min formula as being the bottom of my range, such as:
Range("n2").FormulaR1C1 = "=min((RC[-9]:R[&R_count]c[-9]))"
but VBa does not read R_count as an integer in the formula.
Your value you are assigning for your range is a string, so you will need to concatenate the string formula with your variable. Try the following:
Range("n2").FormulaR1C1 = "=min((RC[-9]:R[" & R_count & "]c[-9]))"
Concatenating in VBA
You cannot directly reference variables from vba in a formula, because the formula is a string that will be evaluated in a different place that does not know about your code. You will need to insert the value in your formula like so :
Range("n2").FormulaR1C1 = "=min((RC[-9]:R[" & R_count & "]c[-9]))"
Which will produce a formula that will look like this (lets assume that R_Count is equal to 42 for this exemple)
=min((RC[-9]:R[42]c[-9]))

Using named range in VBA function for VLOOKUP

I have a the following on my worksheet:
A cell that shows a currency [in A1]
A range of cells (two columns, one for the currency, and the other for a corresponding commission percentage) [defined as/named RANGE, and scoped to the worksheet]
A cell that [is trying] to determine the calculated commission percentage based on A1 and RANGE
I then have a VBA function called Calculate, as follows:
Function Calculate(LookupValue As Double, LookupRange As Range) As Double
Calculate = [VLOOKUP(LookupValue, LookupRange, 2)]
End Function
The cell that determines the percentage has the following:
=Calculate(A1, RANGE)
Problem is that the cell just returns #VALUE!...
Any idea what I could be doing wrong?
I have tried several things like type-hinting to Range(), passing LookupRange.Value2 to VLOOKUP, etc, none of which worked.
I have also tried to debug, noting that LookupRange does actually contain the range required in Value2, which is is why I tried to pass it to the function.
Side Note: The function and layout mentioned above is just a dummy - the actual function is somewhat more complex as it relies on negotiated rates, monthly margins, etc. This is why I'm using VBA in the first place. I know that I'm doing something wrong with the lookup, as it is the only thing that seems to be failing within the function - everything else corresponds and calculates.
From MSDN:
The advantage of using square brackets is that the code is shorter. The advantage of using Evaluate is that the argument is a string, so you can either construct the string in your code or use a Visual Basic variable.
in other words you can use
Calculate = [VLOOKUP(3, A1:B100, 2)]
but you can not use
LookupValue = 3
LookupRange = Range("A1:B100")
'or
'LookupRange = "A1:B100"
Calculate = [VLOOKUP(LookupValue, LookupRange, 2)]
What you can do is:
Option 1:
Function Calculate(LookupValue As Double, LookupRange As Range) As Double
Calculate = Evaluate("VLOOKUP(" & LookupValue & "," & LookupRange.Address & ", 2")
End Function
or better:
Function Calculate(LookupValue As Double, LookupRange As Range) As Double
Calculate = Evaluate("VLOOKUP(" & LookupValue & ",'" & _
LookupRange.Parent.Name & "'!" & LookupRange.Address & ", 2")
End Function
However I suggest:
Option 2:
Function Calculate(LookupValue As Double, LookupRange As Range) As Double
Calculate = Application.VLookup(LookupValue, LookupRange, 2)
End Function
I hope you know about meaning of 4th parameter:
If TRUE or omitted, an exact or approximate match is returned. If an exact match is not found, the next largest value that is less than lookup_value is returned.
The values in the first column of table_array must be placed in ascending sort order; otherwise, VLOOKUP may not give the correct value. You can put the values in ascending order by choosing the Sort command from the Data menu and selecting Ascending.
Btw, Calculate is not good name for UDF, since VBA already has function Application.Calculate. I'd rename it to avoid confusion.

VBA Type Mismatch on Year Function as CountIfs criteria

I'm getting a type mismatch error from the following code:
blattZFq3.Cells(month, siaw) = Application.WorksheetFunction.CountIfs(Worksheets(i).Range("AF10:AF290"), month, Year(Worksheets(i).Range("AE10:AE290")), minYear)
I'm guessing it's a problem with the second criteria, more specifically the Year function as criteria for a range since the code worked fine in a previous version with just the first criteria and using countif.
minYear is declared as Variant and has been assigned the value of 2012 by a previous function.
Basically I want the cell in the range blattZFq3 to contain the number of times a number matching month occurs in a column, but only if the year of a date in the same row but different column matches minYear.
Does anybody have any suggestions?
Thanks in advance....
You can't do this function to the array: Year(Worksheets(i).Range("AE10:AE290")) as it's expecting a range for the second area to check.
Also, I would avoid using the word Month as a variable name, as it's also the name of a function.
You will have to write the function with 3 criteria to get around the restriction, or write a formula into the target area.
Function with 3 criteria:
blattZFq3.Cells(MyMonth, siaw) = _
WorksheetFunction.CountIfs(Worksheets(i).Range("AF10:AF290"), MyMonth, _
Worksheets(i).Range("AE10:AE290"), ">=" & DateSerial(minYear, 1, 1), _
Worksheets(i).Range("AE10:AE290"), "<=" & DateSerial(minYear, 12, 31))
As a formula into the cell:
blattZFq3.Cells(MyMonth, siaw).Formula = _
"=SUMPRODUCT(--(SheetName!AF10:AF290=" & MyMonth & ")," & _
"--(YEAR(SheetName!AE10:AE290)=" & minYear & "))"
Work with date sometimes is tricky. Are you using english version?
You can try to write the same formula code in Excel and test it before you put it VBA. You can also try something like:
blattZFq3.Cells(month, siaw) = "=CONTIFS(.....)"