Compile Error: Object Required VBA - excel

I'm new to VBA. I'm trying to write a script that cleans up some data from an experiment. I keep getting an error saying "Object Required" and it highlights pold. Does anyone have any idea why?
As for the script, I'm trying to go down a column of participant numbers and map out what range each participant is in. There are around 30 lines per participant, and I want to define that as values in an array.
Sub Cleanthismofoup()
Dim pranges(1 To 50) As Long
Dim pbegin As Range
Dim pend As Range
Dim pold As Integer
Dim pnew As Integer
Dim pcell As Range
Dim pcounter As Long
Dim i As Long
Set pcell = Range("A1:A1")
Set pbegin = Range("A2:A2")
Set pold = Range("B2:B2").Value
pcounter = 0
'for every item, store value in pnew
' move down one line. Check pnew = pold
' if it is, do again. else create new range
For i = 1 To rngl
pcell = pcell.Offset(-1, 0)
pnew = pcell.Cells.Value
If pnnew <> pold Then pcell = pend
If pcell = pend Then
counter = counter + 1
pranges(counter) = pbegin
counter = counter + 1
pranges(counter) = pend
pbegin = pcell.Offset(-1, 0)
Else: pold = pnew
End If
i = i + 1
Next
End Sub

The error is because you are using a Set keyword which is used to assign reference to the object. Since the output on the RHS of Set pold = Range("B2:B2").Value is an Integer, vba gives you an error. To resolve it simply remove the Set keyword. However I also noticed that you are using rng1 in the for loop without initializing the rng1 variable, in which case your for loop will never execute. You might also want to rectify that.

Related

Is there a way to reassign a Range variable to a different range?

I am very new to VBA, having started programming it yesterday. I am writing a data processing program which requires keeping track of two cells, one on each spreadsheet. The code which reproduces the errors I am experiencing is below. When I call the sub moveCell() in sub Processor(), nothing happens to DIRow and DIColumn, and the code spits out error 1004 at the line indicated. I have tried using DICell = DICell.Offset(), but it returns the same error.
How can I redefine a Range variable to be a different cell?
'<<Main Processor Code>>'
Sub Processor()
Dim PDRow As Integer
Dim PDColumn As Integer
Dim DIRow As Integer
Dim DIColumn As Integer
PDRow = 1
PDColumn = 1
DIRow = 1
DIColumn = 1
Dim PDCell As Range
Dim DICell As Range
Set PDCell = Worksheets("Processed Data").Cells(PDRow, PDColumn)
Set DICell = Worksheets("Data Input").Cells(DIRow, DIColumn)
Call moveCell(2, 0, "Data Input")
End Sub
'<<Function which moves the cell which defines the range>>'
Sub moveCell(r As Integer, c As Integer, sheet As String)
If sheet = "Processed Data" Then
PDRow = PDRow + r
PDColumn = PDColumn + c
Set PDCell = Worksheets("Data Input").Cells(PDRow, PDColumn)
ElseIf sheet = "Data Input" Then
DIRow = DIRow + r '<<<<<<This line does nothing to DIRow's value
DIColumn = DIColumn + c
Set DICell = Worksheets("Data Input").Cells(DIRow, DIColumn) '<<<<<<This line causes error 1004
End If
End Sub
As far as I can tell, you could instead use a quick Function instead. There doesn't seem to be any difference in your If statement results in the moveCell() function, except which worksheet you're using.
We can make this simpler by referring to the Range you're passing to moveCell.
Option Explicit ' forces you to declare all variables
Sub something()
Dim PDCell As Range
Set PDCell = Worksheets("Processed Data").Cells(1, 1)
Dim DICell As Range
Set DICell = Worksheets("Data Input").Cells(1, 1)
PDCell.Select ' can remove
Set PDCell = moveCell(2, 0, PDCell, PDCell.Worksheet.Name)
PDCell.Select ' can remove
Worksheets(DICell.Worksheet.Name).Activate ' can remove
DICell.Select ' can remove
Set DICell = moveCell(5, 0, DICell, DICell.Worksheet.Name)
DICell.Select ' can remove
End Sub
Function moveCell(rowsToMove As Long, colsToMove As Long, cel As Range, ws As String) As Range
Set moveCell = Worksheets(ws).Cells(cel.Row + rowsToMove, cel.Column + colsToMove)
End Function
I've included some rows you don't need (which I've marked with a comment afterwards), but that will show you how the routine works. You can step through with F8 to help see it step-by-step.
Edit: Although, you don't need a separate function at all. Just use OFFSET().
Set PDCell = ...whatever originally
Set PDCell = PDCell.Offset([rows],[cols])

Goal seek Run-time 1004 error when using application.run from another Workbook

I have a run-time error that I can't solve despite having searched deeply into many forum.
Here is the problem: I am using a Macro in a Model looking for a optimal allocation through a Goal-Seek function.
When I use it within that model (let's call it Model 1), the macro works perfectly.
However, i need to work in that model and in another one, to get data that will fill a table located in a 3rd excel file, which is then my "main file" (let's call it Model 3).
Thus, I need to call that macro located in Model 1 via an Application.run from Model 3.
And when I do so, I get a "Run-time error '1004': Reference isn't valid." which relates to the Goal-seek function that I use in Model 1.
Furthermore, if after that I come back to Model 1 and try to use the macro, I get the exact same error message while it was working before.
Here are my codes:
Model 3 (main):
Sub Test_Optim()
Dim JFMPath As String
Dim MacroPath As String
JFMPath = Sheets("Inputs").Range("D2")
MacroPath = Sheets("Inputs").Range("A3")
Workbooks.Open JFMPath
Application.Run (MacroPath)
End Sub
Model 1:
Option Explicit
Option Base 1
Sub Optimization_Alloc()
'Definitions
Dim i As Integer
Dim k As Integer
Dim IRR As Single
Dim IRRDelta As Single
Dim vIRR() As Single
Dim MinIRR As Single
Dim vPPA() As Single
Dim PPALevel As Single
Dim MinPPA As Single
Dim Position As Integer
Dim FlipYearIterations As Integer
Dim IterTF As Boolean
Dim IterStep As Single
Dim FlipYear As Integer
Dim OptFlipYear As Integer
Dim vFlipYear() As Integer
Dim xDistribution As Single
Dim OptxDistribution As Single
Dim vXDistribution() As Single
'enables goal-seek iterations, MaxIterations is the number you would wanna change
IterTF = Application.Iteration = True
IterStep = Application.MaxIterations
With Application
.Iteration = True
.MaxIterations = 500
.MaxChange = 0.0001
End With
FlipYearIterations = 10
ReDim vPPA(FlipYearIterations) As Single
ReDim vFlipYear(FlipYearIterations) As Integer
ReDim vXDistribution(FlipYearIterations) As Single
ReDim vIRR(FlipYearIterations) As Single
For i = 1 To FlipYearIterations
vFlipYear(i) = 2027 + i - 1
Next i
'Loops through different FlipYears. For every year, optimal allocation of cash/tax is calculated by goalseek.
For k = 1 To FlipYearIterations
Worksheets("As_Yr").Cells(345, 9) = vFlipYear(k) 'Optimal flip year
Worksheets("As_Yr").Cells(350, 9).GoalSeek Goal:=0, ChangingCell:=Worksheets("As_Yr").Cells(346, 9)
'Here is the Goalseek function from which I get the run-time error
xDistribution = Worksheets("As_Yr").Cells(346, 9)
PPALevel = Worksheets("Cockpit & As_Gen").Cells(48, 9)
vXDistribution(k) = xDistribution
vPPA(k) = PPALevel
vIRR(k) = Worksheets("As_Yr").Cells(348, 9)
Next k
'Determines optimal FlipYear
MinIRR = WorksheetFunction.Max(vIRR)
Position = WorksheetFunction.Match(MinIRR, vIRR, False)
OptFlipYear = vFlipYear(Position)
OptxDistribution = vXDistribution(Position)
'Prints optimal setting to Excel
Worksheets("As_Yr").Cells(345, 9) = OptFlipYear 'Optimal flip year
Worksheets("As_Yr").Cells(346, 9) = OptxDistribution 'Optimal CF distrib
'restores to the original goal-seek iterations setting
IterTF = Application.Iteration = True
IterStep = Application.MaxIterations
With Application
.MaxIterations = IterStep
.Iteration = IterTF
.MaxChange = 0.001
End With
End Sub
Is this something that one of you could help me with?
I guess it is a dummy mistake, but I can't figure that out.
Many thanks,
Alice

VBa Looping through RecordSets is too slow for my program

I have a RecordSet loop inside another RecordSet loop. It'd work well if it didn't take 45 secs for the .OpenRecordSet to run, and the table it'll open has 445k registers.
The reason for the inside loop is because I need to filter results obtained from another RecordSet, and then get these new results and compare.
Would it be better to use other methods, or other way? Is there another way to get specific data from a table(a faster way, of course)? Should I try multithreading?
Since people might need my code:
Private Sub btnGetQ_Click()
Dim tabEQ As DAO.Recordset: Dim tabT7 As DAO.Recordset: Dim tabPesqC As DAO.Recordset: Dim PesqCqdf As DAO.QueryDef
Dim index As Integer: Dim qtdL As Long: Dim qtdL2 As Long
Dim arrC() As String: Dim arrC2() As String: Dim arrC3() As String
Set tabEQ = dbC.OpenRecordset("EQuery", dbOpenSnapshot)
Set tabT7 = dbC.OpenRecordset("T7Query", dbOpenSnapshot)
If Not tabEQ.EOF Then
tabEQ.MoveFirst
qtdL = tabEQ.RecordCount - 1
ReDim arrC(qtdL): ReDim arrC2(qtdL)
If Not tabT7.EOF Then
tabT7.MoveFirst: index = 0
Do Until tabT7.EOF
arrC(index) = tabT7.Fields("CCO"): arrC2(index) = tabT7.Fields("CCE")
Set PesqCqdf = dbC.QueryDefs("pesqCCO")
PesqCqdf.Parameters("CCO") = arrC(index)
Set tabPesqC = PesqCqdf.OpenRecordset(dbOpenSnapshot)
qtdL2 = tabPesqConj.RecordCount - 1
If qtdL2 > 0 Then
ReDim arrC3(qtdL2)
Dim i As Integer
For i = 0 To UBound(arrC3)
arrC3(i) = tabPesqC.Fields("CCE")
tabPesqC.MoveNext
Next
End If
On Error GoTo ERROR_TabT7
index = index + 1: tabT7.MoveNext
Loop
End If
ERROR_TabT7:
Set tabT7 = Nothing
End If
If IsObject(tabEQ) Then Set tabEQ = Nothing
End Sub
I created tables linked with what i wanted :/

Offset Function in VBA

Dim temp_match As Single
Dim mid_value As Single
Dim offset1 As Range
Dim offset2 As Range
Dim off_val1 As Range
Dim off_val2 As Range
temp_match = Application.Match(temp_time, Range("B2:B20"), 1) - 1
Set offset1 = Workbooks("Zero Curve").Worksheets("Sheet1").Range("B2:B20")
Set offset2 = Workbooks("Zero Curve").Worksheets("Sheet1").Range("D1:D20")
off_val1 = Evaluate("Offset(offset1, temp_match, 0,2)")
off_val2 = Evaluate("Offset(offset2, temp_match, 0,2)")
mid_value = Application.Forecast(temp_time, off_val2, off_val1)
This code shows an error:
"Object variable or With block variable not set".
Please help.
You have a few issues there. Frst you have to use Set to assign an object variable. Second you can't refer to a VBA variable in a formula string like that. Third there is no need for Evaluate there:
Set offset1 = Workbooks("Zero Curve").Worksheets("Sheet1").Range("B2:B20")
Set offset2 = Workbooks("Zero Curve").Worksheets("Sheet1").Range("D1:D20")
Set off_val1 = offset1.Offset(temp_match, 0).Resize(2)
Set off_val2 = offset2.Offset(temp_match, 0).Resize(2)

Application-defined or object-defined error in Excel VBA

I'm getting said error in using VBA in Excel on the following code:
Private Sub XMLGen(mapRangeA, mapRangeB, ticketSize, mapping)
Dim fieldOneArr As Variant
Dim fieldTwoArr As Variant
Dim row As Long
Dim column As Long
Dim infoCol As Long
Dim endInfo As Long
Dim objDom As DOMDocument
Dim objNode As IXMLDOMNode
Dim objXMLRootelement As IXMLDOMElement
Dim objXMLelement As IXMLDOMElement
Dim objXMLattr As IXMLDOMAttribute
Set ws = Worksheets("StockData")
Dim wsName As String
Set objDom = New DOMDocument
If ticketSize = 8 Then
wsName = "A7Tickets"
ElseIf ticketSize = 16 Then
wsName = "A8Tickets"
Else
wsName = "A5Tickets"
End If
Set ps = Worksheets(wsName)
'create processing instruction
Set objNode = objDom.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'")
objDom.appendChild objNode
'create root element
Set objXMLRootelement = objDom.createElement("fields")
objDom.appendChild objXMLRootelement
'create Attribute to the Field Element and set value
Set objXMLattr = objDom.createAttribute("xmlns:xfdf")
objXMLattr.NodeValue = "http://ns.adobe.com/xfdf-transition/"
objXMLRootelement.setAttributeNode objXMLattr
infoCol = 1
fieldOneArr = Worksheets(mapping).range(mapRangeA)
fieldTwoArr = Worksheets(mapping).range(mapRangeB)
For row = 1 To UBound(fieldOneArr, 1)
For column = 1 To UBound(fieldOneArr, 2)
'create Heading element
Set objXMLelement = objDom.createElement(fieldOneArr(row, column))
objXMLRootelement.appendChild objXMLelement
'create Attribute to the Heading Element and set value
Set objXMLattr = objDom.createAttribute("xfdf:original")
objXMLattr.NodeValue = (fieldTwoArr(row, column))
objXMLelement.setAttributeNode objXMLattr
objXMLelement.Text = ps.Cells(row, infoCol)
infoCol = infoCol + 1
endInfo = endInfo + 1
If endInfo = 4 Then
infoCol = 1
End If
Next column
Next row
'save XML data to a file
If ticketSize = 2 Then
objDom.Save ("C:\ExportTestA5.xml")
MsgBox "A5 XML created"
ElseIf ticketSize = 8 Then
objDom.Save ("C:\ExportTestA7.xml")
MsgBox "A7 XML created"
Else
objDom.Save ("C:\ExportTestA8.xml")
MsgBox "A8 XML created"
End If
End Sub
When I hit debug it points to this line:
fieldOneArr = Worksheets(mapping).range(mapRangeA)
I know that .Range is supposed to be upper case but it keeps on setting it to lower case automatically whenever I correct it.
This code is meant to create an XML file and then write the details from the chosen worksheet (based on the ticketSize variable) into the correct XML fields. Hence I have a mapping worksheet from which I write the field and attribute names, and then write in the info from the correct ticket size worksheet into the text property of the element.
You should define the types of your function parameters, in this case mapRangeA As String. Office object methods and properties are often not very helpful with their error messages, so it's better to have a type mismatch error if you have a problem with a parameter.

Resources