VBA Macro Compile Error - vba

I'm attempting to write a simple VBA macro that will take the active cell's column and the user's input to add a range of cells on a single row together. The range is calculated by adding the integer the user inputs to the active column and that is the end column. The problem is that it gives me a "Compile Error: Invalid Qualifier" when I run it, and gets angry at the 'total' line.
Here is my code. I'm just starting in VBA, but it can't be that hard....right?
Sub Food()
Dim first As Variant
Dim last As Integer
Dim days As Integer
Dim month As Range
Dim total As Double
first = ActiveCell.Column
days = InputBox("Days in the month?")
last = first + days
Set month.Value = Range(Cells(first, 4), Cells(last, 4))
total.Value = WorksheetFunction.Sum(month)
Worksheets(1).Cells(1, 13).Value = total
End Sub

Looks like a syntax error. Try dropping the .value on month and total.
Sub Food()
Dim first As Variant
Dim last As Integer
Dim days As Integer
Dim month As Range
Dim total As Double
first = ActiveCell.Column
days = InputBox("Days in the month?")
last = first + days
Set month = Range(Cells(first, 4), Cells(last, 4))
total = WorksheetFunction.Sum(month)
Worksheets(1).Cells(1, 13).Value = total
End Sub
If you want to get the value of a range into a variable, you put the .value with the range instead of the variable. For example:
x = cells(1,2).value
The .value property returns the value in a range object. So it doesn't make sense to use it on a function and will cause excel to throw and error if you try. It also doesn't make sense to try to set the month variable as a value instead of a range since that would just make it an array. If you want month to be an array you would want to set it as a variant instead of a range.
For more information on the .value property, see this link:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-value-property-excel

Related

How to Sort, Index, Random generate Sequence of Number from a range of cells

I am trying to generate random number between the list like start year is 1950, and end year is 1960, the formula I'm trying is
=VLOOKUP(RANDBETWEEN($D$3,$D$4),'SP500 Returns2'!$A$3:$F$103,2,0)
I also tried this formula
=if($D$3 < $D$4, $D$3 + Randombetween(1,10),"")
but it gives me only the value up to the condition true and show me only 2 or 3 values but I need complete value between 1950-1960 but with different sequence every time I open the workbook or when the sheet is changed.
I have also a button of random generate that will populate the column B only from the value column A, I want a formula / function / VBA code that could generate a series between the selective numbers as I discuss above.
Here is overlook of my sheet.
How to add formula in Column A that should generate range between the selection of years? I also tried this formula
=Randombetween($D$3,$D$4) but it return duplicate values.
you could use this sub:
Sub GenerateRandomYearsBetween()
Dim myYear As Long, i As Long
Dim years As New Collection
For myYear = Range("D3") To Range("D4")
years.Add myYear
Next
For myYear = 1 To years.Count
i = Int((years.Count) * Rnd + 1)
Range("A8").Offset(myYear).Value = years(i)
years.Remove i
Next
End Sub
which you may call form the relevant event handler
OR you could use its corresponding Function():
Function GenerateRandomYearsBetween(startYear As Variant, endyear As Variant) As Variant
Application.Volatile
Dim myYear As Long, i As Long
Dim initialYears As New Collection
ReDim finalYears(1 To endyear - startYear + 1) As Long
For myYear = startYear To endyear
initialYears.Add myYear
Next
For myYear = 1 To initialYears.Count
i = Int((initialYears.Count) * Rnd + 1)
finalYears(myYear) = initialYears(i)
initialYears.Remove i
Next
GenerateRandomYearsBetween = finalYears
End Function
which you would place as "array formula" in the proper number of cells (i.e. as many cells as the number of years between the referenced ones) as
=GenerateRandomYearsBetween($D$3;$D$4)

Excel VBA with matches and index

I've written some VBA code with two matches and index formula. I need to pick the unique value from a sheet and compare it with the other sheet. However it is not working. I get some errors. (unable to get the match property of the worksheetfunction class vba - this is the error)
Here is my code :
Sub Post_Attendance()
Sheets("DB").Activate
'On Error Resume Next
Dim myvalue As String
Dim mydate As String
Dim mypost As String
(the date value entered in a cell)
Dim Dt As String
Dt = Range("C7").Value
(the unique id entered in a cell)
Dim empid As String
empid = Range("C8").Value
(activating another worksheet , from a cell value)
Dim strWsName As String
strWsName = Sheets("DB").Range("A7")
Sheets(Left(strWsName, 3)).Select
(match function to find the row and columns number for indexing)
mydate = WorksheetFunction.Match(Dt, Range("B1:Q1"), 0)
myvalue = WorksheetFunction.Match(empid, Range("A5:A500"), 0)
mypost = WorksheetFunction.Index(Range("B2:Q6"), myvalue, mydate)
End Sub
First off, WorksheetFunction.Match never returns a string; it either returns a number (a long integer) or an error. It is not the value from the match, it is the row or column number where the match was found.
Next, you cannot catch an #N/A error from no match with WorksheetFunction.Match but you can catch it with Application.Match into a variant.
Real dates are numbers, not strings. The raw underlying value is another long integer; e.g. a positive whole number with no decimal portion. If you had time or a datetime then you would have a decimal portion.
Resolve and reference your parent worksheet properly; do not rely upon Select or Activate.
The number returned from MATCH is the position within the range of cells searched. You are looking for a row number from row 5 to row 500 then using that to find a row within row 2 to 6; any match above row 9 (match returning 6 or above) in the original is going to be out-of-range.
If the empid values are numbers then deal with numbers; you cannot find a match to a true number from text-that-looks-like-a-number; e.g. 99 <> "99". I'm going to assume that empid should be alphanumeric and not a true number but given the errors with the previous variable assignments, it is up to you to determine the correct assignment.
Here is my best guess at an error controlled sub procedure (given that you have shown no sample data).
Option Explicit
Sub Post_Attendance()
'On Error Resume Next
Dim myvalueRow As Variant, mydateCol As Variant, dt As Long, empid As String, mypost As Variant
dt = Worksheets("DB").Range("C7").Value2
empid = Worksheets("DB").Range("C8").Value2
With Worksheets(Left(Worksheets("DB").Range("A7").Value2, 3))
'locate the column for the date
mydateCol = Application.Match(dt, .Range("B1:Q1"), 0)
If IsError(mydateCol) Then _
mydateCol = Application.Match(CStr(Worksheets("DB").Range("C7").Value2), .Range("B1:Q1"), 0)
If IsError(mydateCol) Then
Debug.Print "dt not found in row 1"
Exit Sub
End If
'locate the row for the value
myvalueRow = Application.Match(empid, .Columns("A"), 0)
If IsError(myvalueRow) Then
Debug.Print "empid not found in column A"
Exit Sub
End If
mypost = Application.Index(.Range("B:Q"), myvalueRow, mydateCol)
End With
End Sub

function not appropriately defined within userform subroutine

I apologize if this is a dumb question but I've been unable to find an answer to my current issue. I am attempting to create a userform which searches spreadsheet data based on input in the combobox for username, a start date, and an end date.
There is one user column and all other columns correspond to dates. The data is a daily workload productivity number (e.g., 87 widgets). The goal is to be able to enter inputs and copy the data from the raw data spreadsheet to a results spreadsheet, showing information for one user during that date range.
I keep getting an error ("Compile error: Sub or Function not defined") regarding my attempt to use the function to define columns for the appropriate dates. I'd appreciate any input. Thanks.
'Function changes column number to column name
Public Function fnColumnToLetter_CellAdressReplace(ByVal ColumnNumber As Integer)
fnColumnToLetter_CellAdressReplace = Replace(Replace(Cells(1, ColumnNumber).Address, "1", ""), "$", "")
End Function
Private Sub SearchButton1_Click()
'Dim variables
Dim sheet As Worksheet
Dim name1 As String
Dim date1 As Date
Dim date2 As Date
Dim STARTcol As String
Dim ENDcol As String
Dim pharmcol1 As String
Dim pharmcol2 As String
Set sheet = ActiveWorkbook.Sheets("Data")
Set Results = ActiveWorkbook.Sheets("Results")
'Variables for entries input into userform
name1 = userform1.NameBox1.Value
date1 = userform1.DateBox1.Value
date2 = userform1.DateBox2.Value
'Define row based on pharmacist name
rowno = Application.WorksheetFunction.Match(name1, Range("A:A"), 0)
pharmrow = "a" + rowno
'Find first column from start date
STARTcol = Application.WorksheetFunction.Match(date1, Range("A1:AZZ1"), 0)
'Find last column from end date
ENDcol = Application.WorksheetFunction.Match(date2, Range("A1:AZZ1"), 0)
'Call function to replace column number to column name
pharmcol1 = fnColumnToLetter_CellAddressReplace(STARTcol) + rowno
pharmcol2 = fnColumnToLetter_CellAddressReplace(ENDcol) + rowno
'Copy table array to RESULTS worksheet
sheet.Range("pharmcol1:pharmcol2").Copy Destination = Results.Range("A1")
End Sub
Compile error: Sub or Function not defined
Whenever I see this error I usually look for grammatical errors between the function/sub and the call. In your case you have spelled Address differently between the two.
Public Function fnColumnToLetter_CellAdressReplace(ByVal ColumnNumber As Integer)
pharmcol1 = fnColumnToLetter_CellAddressReplace(STARTcol) + rowno
pharmcol2 = fnColumnToLetter_CellAddressReplace(ENDcol) + rowno
Hope this helps.

lookup a number and increment value in another cell within same row

I would like to create a macro in excel that lets me increment the counts of a part whenever I press a command button.
Currently, my concept is to use vlookup to get the existing counts for that part using the following. However, it does not increment the actual counts value in the cell, which is what I want. I suspect it's cos vlookup is only used to return a value within the cell, but the cell is not activated in the process for actual increment. Can someone please advise how I can correct it? I'm still new to vba. Thanks!!! :)
E.g. Vlookup finds C1value in Cell A5 of Sheets("Location"). It will automatically increment the value in Cell C5 by 1.
Sub FindAddTools()
Dim C1Qnty As Double
C1value = Sheets("Issue").Range("D11")
Sheets("Location").Activate
C1Qnty = WorksheetFunction.VLookup(C1value, Range("A:D"), 3, False)
C1Qnty = C1Qnty + 1
End Sub
ADD ON: an add-on to my original question. I was wondering if it is possible to do the same for an entire range?
E.g. C1value is now a range of Sheets("Issue").Range("D11:D20"). I want to find all values within this range in Sheets("Location") and increment their corresponding counts in Column C.
Is there a way to do this without repeating the same procedure for all cells of the range?
Thanks! :)
Here's my shot at it. If the value isn't matched nothing happens:
Sub FindAddTools()
Dim RangeToMatch As Excel.Range
Dim cell As Excel.Range
Dim C1Value As Variant
Dim C1Row As Variant
Set RangeToMatch = Sheets("Issue").Range("D2:D11")
For Each cell In RangeToMatch
C1Value = cell.Value
With Sheets("Location")
C1Row = Application.Match(C1Value, .Range("A:A"), 0)
If Not IsError(C1Row) Then
.Range("C" & C1Row).Value = .Range("C" & C1Row).Value + 1
End If
End With
Next cell
End Sub
I edited it so that it cycles through a range of cells to match. That range is set to D2:D11 above.
Based on your comments, I think this should do it.
NB: you don't have to Activate worksheets to perform the functions referencing their cells/ranges.
Sub FindAddTools()
Dim shIssue as WOrksheet: Set shIssue = Sheets("Issue")
Dim shLoc as Worksheet: Set shLoc = Sheets("Location")
Dim allC1Values as Range
Dim C1Value as Variant
Dim C1Qnty As Double
Dim foundRow as Long
Set allC1Values = shIssue.Range("D11:D100") '## Modify as needed.
For each C1Value in allC1Values.Cells
C1Qnty = WorksheetFunction.VLookup(C1value, shLoc.Range("A:D"), 3, False)
C1Qnty = C1Qnty + 1
foundRow = WorksheetFunction.Match(c1Value,shLoc.Range("A:A"),False)
shLoc.Range("C" & foundRow).Value = CqQnty
Next
End Sub
Be careful with this. You're immediately writing to the same cell you just "found" with the VLOOKUP function, so, obviously if you run this macro again, you're going to increment it again. But, this may be the desired functionality, if so, no problem.
NOTE: There is no error trapping for if C1Value is not found in the VLOOKUP or MATCH functions.

Why is VLookup in VBA failing with runtime error 1004?

Spreadsheet "Sheet3" looks like this:
S&P 500 DJIA
1/1/1991 795.4476 2973.09
1/2/1991 786.3856 2947.1
1/3/1991 775.4636 2905.19
1/4/1991 773.5364 2896.8
1/7/1991 760.2996 2847.9
1/8/1991 759.0029 2832.81
1/9/1991 750.8416 2788.67
1/10/1991 758.1719 2820.8
Also Cell "F2" is literally a copy and paste of 1/7/1991 cell.
VBA Code looks like this:
Sub badlook3()
Dim BenchSI As Variant
Dim BRange As Range
Dim SIDate As Date
Set BRange = Worksheets("Sheet3").Range("A2:C9")
MsgBox BRange.Address
SIDate = Worksheets("Sheet3").Range("F2").Value
BenchSI = Application.WorksheetFunction.VLookup(SIDate, BRange, 2, True)
End Sub
I am getting the "Unable to get the VLOOKUP property of the WorkSheet Function class" error.
What am I missing here? Column A is in the right order. They are dates. What does Excel want from me?
The problem is with using SIDate as Date(Visual Basic date type)
My guess would be that visual basic date type and excel date type do not match, that's why you're getting an error
Instead declare SIDate as a Range, and it will work
Here's the code:
Sub badlook3()
Dim BenchSI As Variant
Dim BRange As Range
Dim SIDate As Range
Set BRange = Worksheets("Sheet3").Range("A2:C9")
MsgBox BRange.Address
Set SIDate = Worksheets("Sheet3").Range("F2")
BenchSI = Application.WorksheetFunction.VLookup(SIDate, BRange, 2, True)
End Sub
You are asking vLookup to return on a 2 column range, against a 1 column range. Change BRange = "A2:B9" to make your vLookup pick up the S&P Value.
Alternatively, you can change the range to A2:C9 and change the 2 to a 3 in your vLookup and get the DJ average.
In short, vLookup can only return a column reference to the greatest amount of columns in a range. It can return the 1st, 2nd, 0r 3rd column reference in a 3 column range, but not the 4th, because there is no 4th column.