I've noticed something new today that will cause me problems in the future regarding Excel's Solver, so I want to get a jump on it.
I'm using VBA to sequentially apply solver moving down a sheet (let's say this sheet belongs to 'workbook 1'). This all works fine and I'm happy with the results of Solver. Yay... My concern is this: When I have a second rather large workbook open (let's call this 'workbook 2'), WHICH HAS ABOSOLUTELY NO LINKS TO MY CURRENT WORKBOOK, Solver takes around 20 times as long to run.
Naturally the most reasonable thing to do is not have 'workbook 2' open when Solver is running. For now that's my solution, however, in the very near future I will need to have both workbooks open simultaneously. So I pose the following question:
Why would solver take longer to run with two books open even though it's not even touching one of them?
In case skeptics are concerned that my code is doing something unusual here it is:
Sub ExampleSeqSolver()
Dim Iter As Long
Dim Time0 As Double
Dim Duration As Double
Application.ScreenUpdating = False
' Solver requires that it is working on the 'active sheet', silly but w/e
Sheets("Sheet1").Activate
' watch optimization efficiency
Time0 = Timer
For Iter = 2 To 13
' my data are sometimes related to adjacent rows so I was considering supplying an initial solution to reduce the number of runs
' Sheets("Sheet1").Range("$AC$" & ITER & ":$AI$" & ITER) = _
' Sheets("Sheet1").Range("$AC$" & ITER - 1 & ":$AI$" & ITER - 1)
If Cells(Iter, 1) <> 0 Then
SolverReset
SolverOptions AssumeNonNeg:=True, Iterations:=100
SolverAdd CellRef:="$AK" & Iter, Relation:=2, FormulaText:="1"
SolverOK SetCell:="$AW$" & Iter, MaxMinVal:="2", ByChange:=Sheets("Sheet1").Range("$AC$" & Iter & ":$AI$" & Iter), Engine:=1
SolverSolve True
End If
Next Iter
' report optimization duration
Duration = Round(Timer - Time0, 2)
MsgBox "Optimization finished in " & Duration & " seconds", vbInformation
Application.ScreenUpdating = True
End Sub
The presence of 'workbook 2' is correlated but not causal. In my case there is one particular workbook that causes the solver slowdown; most others don't. The workbook that causes the slowdown is about 4mb. Much larger workbooks do not cause a slowdown. The one causing the slowdown does not to the best of my knowledge contain either macros or VB. I recommend that this problem be shown to Frontline systems who developed the original solver.
Related
Sorry, this is another VBA Solver looping problem. I've read many of the other questions/answers posted here and elsewhere, but being new to VBA (this is the first thing I am attempting), I'm unable to pinpoint my error.
I wish to set cell Ii to 0 while changing cells Ji and Ki (keeping results), where i are rows 3 to 21.
My current code does not come up with any errors, but the results only keep on the last row of the loop- please advise! I've tried using range() and range.offset (from other examples) instead of cells(), and also setting the active worksheet to no avail.
I am using Excel 2011 for Mac.
Sub SolveTwo()
'Not sure if this is necessary
Dim row As Integer
'Begin loop
For row = 3 To 21
'Test code shows it is stepping through loop
Cells(row, "U").Value = row
'Grab starting values from other columns
Cells(row, "J").Value = Cells(row, "S").Value
Cells(row, "K").Value = Cells(row, "T").Value
'Solver Code
SolverReset
SolverOptions Precision:=1e-05
SolverOk SetCell:=Cells(row, "I").Address, _
MaxMinVal:=3, ValueOf:=0, _
ByChange:=Cells(row, "J").Address & "," & Cells(row, "K").Address, _
Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve UserFinish:=True
SolverFinish KeepFinal:=1
'Not sure if below is necessary
'SolverSave SaveArea:=Cells(row, "J").Address & "," & Cells(row,"K").Address
Next row
End Sub
Had the same problem, i.e. only retaining the solutions to the last solver call.
It's caused by Excel for Mac's solver operating asynchronously, and the solver macro only starts once the calling code has completed. Hence the solver parameters are reset repeatedly by the calling code, but the solver doesn't run until the last iteration.
There is no solution forthcoming currently but here are two workarounds. The first one is to have two modules: a regular module calling solver once, and a second class module which fires whenever the sheet calculates (solver kicks off a re-calc when finishing), and calls the second one. Iterate back and forth in a loop. See here for great solution by J Peltier which I've admittedly not tried: solution 1
Solution 2 which I used is to call solver from an Apple Script. Here's an example. The control flow in the macro uses worksheet cells for the loop counters etc, and my macro was called by shift-opt-cmd-O. My solver usually finished in 10 sec, so I waited 15.
on run {input, parameters}
-- Click “Microsoft Excel” in the Dock.
set timeoutSeconds to 2.0
set uiScript to "click UI Element \"Microsoft Excel\" of list 1 of application process \"Dock\""
my doWithTimeout(uiScript, timeoutSeconds)
-- Press ⇧⌥⌘O
repeat 496 times
set timeoutSeconds to 2.0
set uiScript to "keystroke \"Ø\" using {shift down, option down, command down}"
my doWithTimeout(uiScript, timeoutSeconds)
delay 15
say "done"
end repeat
return input
end run
Hope that helps!
Try something like this:
Sub SolveTwo()
Dim myRow As Integer
For myRow = 3 To 21
With Worksheets(2)
.Cells(myRow, "U") = myRow
.Cells(myRow, "J") = Worksheets(1).Cells(myRow, "S")
.Cells(myRow, "K") = Worksheets(1).Cells(myRow, "T")
End With
'add your solver code here.
Next myRow
End Sub
It will generate some results in Worksheets(2), if the sheet you are executing is the first one. Furthermore, do not use Row as a variable name, because it is used in the VBEditor.
I have a workbook that I am using to solve a system of non-linear equations, and then display the solution on a chart. The chart has a large amount of content (basically the result of solving the system of equations for a few standard cases), which references a table of about 1200 cells. That content is static, and so for aesthetics I keep the calculations table on sheet1 and graph on sheet2.
Then on the graph sheet I allow user input to two cells which are referenced in the calculations on sheet1 to build three dynamic instances of the system of equations. Pretty lightweight for solver to handle one at a time.
I use a Worksheet_Change event on sheet2 to watch for the user to modify those two cells and then it calls a sub that runs the solver.
The event code:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If (Target.Address = "$C$3") Or (Target.Address = "$D$3") Then
Application.ScreenUpdating = False
Application.EnableEvents = False
SolverEQN 178, 180
Application.ScreenUpdating = True
Application.EnableEvents = True
End If
End Sub
The Solver code:
Sub SolverEQN(rw, rwend As Integer)
Dim iter As Integer
For iter = rw To rwend
If Sheets(1).Cells(iter, 14) <> 0 Then
SolverReset
SolverOptions AssumeNonNeg:=False
SolverOK SetCell:="'Sheet1'!$N$" & iter, MaxMinVal:="3", ValueOf:="0", ByChange:="'Sheet1'!$H$" & iter
SolverSolve True
End If
Next iter
End Sub
Here is where the problem is encountered. Solver runs on sheet2, despite my assigning it to run on sheet1, meaning the system of equations don't exist where they should and solver quickly optimizes to 0 = 0 in the middle of my active sheet.
There are two workarounds that I've found:
1 - Set my activesheet to be sheet1 before running solver and then set activesheet back to sheet2 after solver runs. This causes a short pause and screen flicker, so the experience would not be 'seamless' for a user.
2 - Solve the dynamic system of equations on the graph sheet and hide them in a crude way (white font, stuff them behind my graph, YUCK!).
I will handle this with option 2 if I have to, but do you creative folks have any ideas on how to keep the calculations on my calculations sheet?
Input much appreciated.
Cheers.
I am currently facing a very anoying issue with my Excel workbook, and I would like to ask you for help.
My workbook works as a quotation tool and generates a PDF afterwards.
First, you need to enter data from different sources (for e.g. PDFs, Excel Workbooks, etc.) to a Worksheet called Master. You can do some calculation with simple formulas and can export the results into another sheet called Calc_Overview. In this process, the data is also formatted to the right font, color and size.
With ActiveWorkbook.Worksheets("Master")
For i = 12 To .UsedRange.rows.Count
If .Cells(i, 2) <> "" Then
.Cells(i, 2).Copy Destination:=Target.Cells(k, 4)
.Range(.Cells(i, 4), .Cells(i, 5)).Copy _
Target.Range("F" + k, "G" + k).PasteSpecial xlPasteValues
.Range(.Cells(i, 6), .Cells(i, 7)).Copy _
Destination:=Target.Range("I" + k, "J" + k)
.Cells(i, 8).Copy _
Destination:=Target.Cells(k, 8)
k = k + 1
End If
Next i
End With
After this operation, the user can see a summary of his entered and calculated data. With another macro, which copies the rows into 3 different worksheets (depending on the kind), the calculation process is finished.
This is my copy function :
Function CopyTable(Typ As String, Counter As Integer, Count As Integer) As Integer
With Worksheets("Calc_Overview")
.Range("A" & Count & ":" & "D" & Count).Copy _
Destination:=Sheets(Typ).Range("A" & 5 + Counter)
.Range("G" & Count & ":" & "H" & Count).Copy _
Destination:=Worksheets(Typ).Range("E" & 5 + Counter)
End With
CopyTable = Counter + 1
End Function
Now my problem:
If you try to edit the data which was transfered into the final worksheet, it often happens that Excel crashes without any reason. After editing a cell value,pressing enter or clicking another cell will let Excel crash.
I already turned off the 'Automatically Flash Fill' and 'Show Quick Analysis' option, but the problem still occurs..
Has anyone a clue what might cause this problem? I already replaced the final worksheets by new ones without copying anything from the 'broken' ones - also without any success. I am using a Windows 10 PC (x64) with an 32-Bit Microsoft Office 2013.
I am really looking fowards to any tips or solutions regarding this problem!
Many thanks
Moritz
I have an update for you:
changing the copy method does not change anything - the problem still occurs.
This is how is looks after you edit the cell - the cell expands and excel is freezing without any reason with a very high cpu load
I have a problem and I think it's complicated. It's regarding importing data/information from a another Excel file and the data/information needed is on 2 sheets.
The code is working but not the way It should be it doesn't seem to import the data and down below it will explain what we cannot do in it, ("me and my friend that are working in this project that was demand by our company don't know almost nothing about this category VBA and we are just researching info about this but get always stuck").
We need to extract from the file (the link is in the description), and the file is created every week(semana) so somehow it needs to extract the newest every week.
Down below there's the Excel file that is responsible for the extraction of the data for security reason we deleted most of the information on it and changed names.
Workbook with the Macro - Used for importing The sheet is the number 2 and also It's called Dev.Pag the macro is associated to the button "IMPORT DATA" in the same file.
Source Workbook - Contains the data This is where it gets the values(exports) from once again the name and some data was erased because It might compromise the company.
If there's anything I can edited or change please tell me. Thanks in advance for any reply.
Also will post the code down below:
Option Explicit
Sub ImportData()
Application.ScreenUpdating = False
Dim Path As String, Lstrw As Long
Dim SourceWb As Workbook
Dim TargetWb As Workbook
'Change this to your company workbook path
Path = "C:\Users\DZPH8SH\Desktop\Status 496 800 semana 12 2015.xls"
Workbooks.Open (Path)
'Change "Source" to the name of your company workbook
Set SourceWb = Workbooks("Status 496 800 semana 12 2015.xls")
'Part that needs some adjustments in down below
'This part is working good but probably some error in the data
'transferance may be intrefering with the integridty
'change the file address
Set TargetWb = Workbooks("Master_Atual_2015.xlsm")
Lstrw = SourceWb.Sheets(1).Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).Row
With SourceWb.Sheets(1)
.Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & _
Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw)).Copy _
Destination:=TargetWb.Sheets(1).Range("A3")
End With
SourceWb.Close savechanges:=False
Application.ScreenUpdating = True
End Sub
It was pretty hard to understand your code for several reasons:
You just reference the sheets by index. Thus they are hard to find. Better reference them by name
you reference ranges only by addresses, it would be better to define named ranges
Another point to make it more readable/ debuggable, set the union to an own range object to be able to watch the content and be sure that this is what you want to have.
With SourceWb.Sheets(1)
Set objTargetRange = .Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw))
objTargetRange.Copy Destination:=TargetWb.Sheets(1).Range("A3")
End With
When printing out the objTargetRange's addresses it looks like this (You can do that by simply pressing ctrl+g and writing ?objTargetRange.Address)
$D$2:$D$9;$F$2:$F$9;$I$2:$I$9;$M$2:$M$9
So you selected four columns, each of them has 8 cells. When adding this to A3, it will be added side by side, it doesn't have any offset.
So cells A3-D10 will be overwritten by your data, the code works. It was not visible that it does that, because comparing state before and state after was pretty complicated. You can make visible, that the changes actually happen by just
temporary removing your actual data from the sheet
temporary adding some empty rows
I am having difficulty with solver. I have tried to develop a for-loop that would call solver many times but I am having issues. I have already added the reference of solver to the workbook from tools/references. I have successfully gotten the loop to work with the solver; unfortunately, solver won't change my input cells automatically. I felt that this issue could be resolved by the SolverReset function but every time I use it it fails, and the loop can no longer find a solution without manually re-solving the system. My code is as follows.
Sub Go_Click()
'Variable Types
Dim x As Double
Dim First_Variable As Range
Dim Second_Variable As Range
Dim Number_of_Calculations As Double
Dim Input_Cells As Range
Dim First_Dimension_Lower As Double
Dim y As Double
Number_of_Calculations = 6
x = (First_Dimension_Upper_Bound - First_Dimension_Lower_Bound) / Number_of_Calculations
For y = 1 To Number_of_Calculations
' x is the integer that the first dimension of the solve will increase by.
' by finding the difference between the upper and lower bound and dividing by the number of calculations
' then the rest is just a for loop, adding the value "x" to each loop
SolverOk SetCell:="First_Dimension", _
MaxMinVal:=3, _
ValueOf:=First_Dimension_Lower_Bound, _
ByChange:="Input_Cells", _
Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve
'Just to test the results
MsgBox (Range("b4"))
'increase in the lower first dimension bound
First_Dimension_Lower_Bound = First_Dimension_Lower_Bound + x
Next y
End Sub
Check the return result of SolverSolve to discover if it completed successfully:
If a Solver problem has not been completely defined, SolverSolve
returns the #N/A error value. Otherwise the Solver runs, and
SolverSolve returns an integer value corresponding to the message that
appears in the Solver Results dialog box.
The linked page lists the possible integer values that are returned. For example, 5 indicates "Solver could not find a feasible solution".
You can also supply a Function name as the ShowRef argument to SolverSolve:
SolverSolve(UserFinish, ShowRef)
This Function will be called if Solver pauses for one of the reasons listed in the linked page. For example, 2 means:
Function called because the Max Time limit in the Solver Options
dialog box was exceeded.