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

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

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])

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 :/

Excel VBA - how to find the largest substring value in a column

I have a column in a spreadsheet.
The format of the data in each cell is aa-0001-xx.
I need to examine the whole column to find the highest value of the sequence number. this would be the substring from column4 thru column7.
I can find the sequence number using Mid(ActiveWorkbook.Sheets("Sheet1").Range("B2:B2"), 4, 4)
But I need to find the max sequence in the whole column.
I am doing this in VBA.
Any help would be appreciated.
Here is my code so far:
Private Sub CommandButton1_Click()
Dim sQuoteNumber As String
Dim sFileName As String
Dim sPathName As String
Dim checkit As String
'Log the Quote
'First, open the log file and determine the next sequential log number.
sPathName = "C:\Users\Rich\Documents\Bryan\BigProject\"
sFileName = "QuoteLog2016.xlsx"
ControlFile = ActiveWorkbook.Name
Workbooks.Open Filename:=sPathName & sFileName
'Create the new Quote Number
checkit = Mid(ActiveWorkbook.Sheets("Sheet1").Range("B2:B2"), 4, 4) ' This is a temp test line
If Mid(ActiveWorkbook.Sheets("Sheet1").Range("B2:B2"), 4, 4) = "" Then
sQuoteNumber = "16-0001"
Else
'find the biggest number
'Here I was looking to like pass the mid function to a Max function of some sort.
sQuoteNumber = "16-0002"
End If
MsgBox ("The new Quote Number is: " + sQuoteNumber)
'Save the log entry
Workbooks(sFileName).Close
All of the comments made to your answer would work well for you. It's also true that there's no evidence in your code at having attempted something, however rudimentary, and this is why answers to a rather trivial task are not forthcoming for you. Perhaps, in future, have a go at some kind of solution ( even if it feels more guesswork than anything) and people on this site will be much more supportive of you.
To set you on your way, you could make use of the Split() function which converts a String into a String array, separated by a nominated value - in the case of your quotations, you could use "-" as your separator. This might be easier than your Mid function and will deal with the case of different sized quotations.
The code below will get you started but you'd want some error handling in there to test, for example, that each cell splits appropriately or that any cells aren't blank. I'll leave all of that to you.
Option Explicit
Private mLastQuote As Long
Public Sub Test()
Initialise 'call this routine just once at the start of your project
MsgBox GetNextQuote(16) 'use the GetNextQuote() function to get next number
MsgBox GetNextQuote(16)
MsgBox GetNextQuote(16)
End Sub
Private Function GetNextQuote(prefix As Integer) As String
mLastQuote = mLastQuote + 1
GetNextQuote = CStr(prefix) & "-" & _
Format(mLastQuote, "000#")
End Function
Private Sub Initialise()
Const PATH_NAME As String = "C:\Users\Rich\Documents\Bryan\BigProject\"
Const FILE_NAME As String = "QuoteLog2016.xlsx"
Const QUOTE_COL As String = "B"
Dim wb As Workbook
Dim ws As Worksheet
Dim v As Variant
Dim r As Long
Dim parts() As String
Dim num As Long
Application.ScreenUpdating = False
Set wb = Workbooks.Open(PATH_NAME & FILE_NAME, True, True)
Set ws = wb.Worksheets("Sheet1")
'Read quote values into variant array
With ws
v = .Range(.Cells(2, QUOTE_COL), _
.Cells(.Rows.Count, QUOTE_COL).End(xlUp)) _
.Value2
End With
'Find max quote
For r = 1 To UBound(v, 1)
parts = Split(v(r, 1), "-") 'splits quote into 3 parts
num = CLng(parts(1)) 'index (1) is the middle part
If num > mLastQuote Then mLastQuote = num
Next
wb.Close False
Application.ScreenUpdating = True
End Sub

Excel VBA Run-time error '13' Type mismatch8

I have done a "copy and paste" to a value after comparing the "road" number and the code number. If those two are matching, Excel VBA will copy and paste in a cell defined. I have created a loop to repeat it. But I discovered that up to 7000 my program was working properly, and when I replaced 7000 by 30000, Excel VBA displays
"Run-time error '13' Type mismatch "
after a certain time. I dont know why. Below is my program:
Private Sub assigment()
Dim road As Double
Dim code As Double
Dim i As Double
For i = 4 To 30000
For code = 2 To 22
For road = 4 To 65
If ActiveWorkbook.Sheets("assignment").Cells(i, 6)=ActiveWorkbook.Sheets("SSUSE").Cells(3, code) Then
If ActiveWorkbook.Sheets("assignment").Cells(i, 8) = ActiveWorkbook.Sheets("SSUSE").Cells(road, 1) Then
ActiveWorkbook.Sheets("SSUSE").Cells(road, code).Copy ActiveSheet.Paste Destination:=ActiveWorkbook.Sheets("assignment").Cells(i, 10)
End If
End If
Next
Next
Next
End Sub
Dim vSource as Variant, vCode as Variant, vRoad as Variant, vAssignment as Variant, vAddress as Variant
vSource = ActiveWorkbook.Sheets("assignment").Range("F4:F30000").Value
vCode = ActiveWorkbook.Sheets("SSUSE").Range("B3:V3").Value
vRoad = ActiveWorkbook.Sheets("SSUSE").Range("A4:A65").Value
vAddress = ActiveWorkbook.Sheets("SSUSE").Range("B4:V65").Value
vAssignment = ActiveWorkbook.Sheets("assignment").Range("H4:H30000").Value
For i = LBound(vSource,1) to UBound(vSource,1)
For code = LBound(vCode,2) to UBound(vCode,2)
For road = LBound(vRoad,1) to UBound(vRoad,1)
If (vSource(i,1) = vCode(1, code)) AND (vAssignment(i,1) = vRoad(road,1)) Then
ActiveWorkbook.Sheets("assignment").Cells(i+3, 10).Value = vAddress(Road,Code)
End If
Next
Next
Next

Compile Error: Object Required VBA

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.

Resources