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


                                       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


               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


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