TechNote Excel VBA Example
Example of Using OpenDSS COM Interface Via Excel VBA
This example could serve as a starting point for using OpenDSS in academic projects. This illustrates driving theOpenDSS from VBA to find the lowest loss solution using the Branch Exchange method (per Civanlar). Some of the details have been omitted for brevity, but you should get the general idea.
The exchange algorithm is “greedy” and will always try to make a switch exchange. The main stopping criterion is when the losses increase after an exchange, meaning the algorithm has found and passed through a local minimum. The exchange method should never create a loop nor isolate a load. If either occurs, the loop halts under what might be considered an error condition.
This is an excerpt from an upcoming EPRI report: "Example Assessments of Distribution Automation Using OpenDSS"
Private Sub Preamble()
gPath = Range("DataPath") ' Read the model file and path names from Excel sheet
gBase = Range("BaseFile")
Set eng = CreateObject("OpenDSSEngine.DSS") ' Starts OpenDSS
eng.start (0)
Set txt = eng.Text ' Load base file name using the Text interface of OpenDSS
txt.Command = "clear"
txt.Command = "compile " & gPath & gBase
Set ckt = eng.ActiveCircuit ' Circuit interface
Set swt = ckt.SwtControls ' new SwtControl interface on the active circuit
Set cap = ckt.CapControls ' CapControl interface
Set reg = ckt.RegControls ' RegControl interface
Set mon = ckt.Monitors ' Monitors interface
Set mtr = ckt.Meters ' (Energy)Meters interface
Set topo = ckt.Topology ' new Topology interface
End Sub
Public Sub BranchExchange()
Dim iter, c, r, i, k As Integer
Dim done As Boolean
Dim Vdiff, Vmax As Double
Dim LastLoss, ThisLoss As Double
Dim ToClose, ToOpen, LowBus As String
Preamble ' Starts OpenDSS, loads in circuit description and defines some vard
Set ws = ActiveWorkbook.Worksheets("Switching")
iter = 1 this is the number of branch exchange trials, limited to 10
done = False
LastLoss = 1E+99
While Not done
r = iter + 1
ws.Cells(r, 10) = iter
ckt.Solution.Solve solve the current system
ThisLoss = ckt.Losses(0)
ws.Cells(r, 11) = ThisLoss write current losses, # loops, # isolated loads to sheet
ws.Cells(r, 12) = CStr(ckt.Topology.NumLoops) & " _ " & CStr(ckt.Topology.NumIsolatedLoads)
Vmax = 0# track the maximum voltage difference across any open switch
ToClose = ""
ToOpen = ""
LowBus = ""
c = 14 column number for output
i = swt.First check all SwtControls
While i > 0 ' find the open switch with biggest deltaV
If swt.Action = dssActionOpen Then check only open switches
ws.Cells(r, c) = swt.name
Set elem = ckt.CktElements(swt.SwitchedObj)
Vdiff = Abs(elem.SeqVoltages(1) elem.
SeqVoltages(4)) V1 across switch
If Vdiff > Vmax Then if highest V1 difference so far…
LowBus = FindLowBus which side of open switch has lowest V?
topo.BusName = LowBus start from that bus in the topology
Set elem = ckt.ActiveCktElement
k = 1
While (Not elem.HasSwitchControl) And (k > 0) trace back from low bus to src
k = topo.BackwardBranch until we find a closed switch
Wend
If elem.HasSwitchControl Then if we found a switch to close…
Vmax = Vdiff 'keep this as the highest voltage difference found
ToClose = swt.name 'we will close this currently open switch
ToOpen = Mid(elem.Controller, 12) and open the switch from backtrace
End If
End If
c = c + 1
End If
i = swt.Next
Wend
ws.Cells(r, 13) = CStr(Vmax)
done = True ' unless we found a switch pair to exchange
If Len(ToOpen) > 0 And Len(ToClose) > 0 Then found a switch pair to exchange
swt.name = ToClose do the switch closeopen
via SwtControl interface
swt.Action = dssActionClose
swt.name = ToOpen
swt.Action = dssActionOpen
done = False ' try again i.e., run solution again and look for the next exchange
End If
iter = r
' stop if too many iterations, system is nonradial, or losses go up
If iter > 10 Or ckt.Topology.NumIsolatedLoads > 0 Or ThisLoss > LastLoss Then
done = True met one of the three stopping criteria
End If
LastLoss = ThisLoss best loss total found so far
Wend
End Sub
' This function is called from the loop above
' “elem” is a CktElement already set to the open branch, from the loop calling FindLowBus
Private Function FindLowBus() As String
Dim i As Integer
Dim v As Double
FindLowBus = ""
v = 9.9E+100
For i = 0 To elem.NumTerminals – 1 loop over all element terminals
If elem.BusNames(i) <> "0" Then
Set b = ckt.Buses(elem.BusNames(i)) look up the Bus connected to terminal
If b.SeqVoltages(1) < v Then track the lowest bus positive sequence voltage
v = b.SeqVoltages(1)
FindLowBus = elem.BusNames(i) return name of bus with lowest V1
End If
End If
Next i
End Function