Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - DarrenDickens

Pages: [1] 2
1
Is this another undocumented feature?

I have a script that, given an object (element, parameter, method, tagged value etc), it prints a "fully qualified name", i.e. the path to the object. For example, given an operation parameter it would show "<root package>::<class (great-grand-parent) package>::<class (grand-parent) package>::<class (parent) package>::<class name>::<operation name>::<parameter name>"

This necessitated a recursive lookup of .Name and .Parent objects (noting some item types have alternatives to .Name and .Parent) and takes a (relatively) long time to calculate.

Whilst in the Excel VBA editor I noticed the property...
Code: [Select]
Function GetFormattedName(GUID, FlagInclude As Long, Separator, FlagFormat As Long) As String
    Member of EA.Repository
    Returns a qualified name of the specified element with formatting applied

I could not find this in the Help nor online anywhere via a Google search. It prints a (slightly different) fully qualified name but much quicker than I can generate with my recursive routine. I would like to use it but don't fully understand its quirks (bound to be some).

From my limited testing (more ongoing) I have found the following (my best guess)

Code: [Select]
GUID - string
    e.g. "{C2E97806-3E66-4b75-B42A-ABF565D8A28D}" (without quotes)

Code: [Select]
FlagInclude - long
    Const nFlagIncludeOperationName_c As Long = 1
    Const nFlagIncludeObjectName_c    As Long = 2
    Const nFlagIncludeParentsName_c   As Long = 8
    Const nFlagIncludeModelName_c     As Long = 16

Code: [Select]
Separator - string
    e.g. "::" (without quotes)

Code: [Select]
FlagFormat - long
    Const nFlagFormatNormal_c            As Long = 0
    Const nFlagFormatSpaceToUnderscore_c As Long = 1
    Const nFlagFormatLowerCase_c         As Long = 2

I have not managed to work out any other bit flag meanings as of yet.

EDIT: Forgot to mention that I am using version 12.0.1214 (don't laugh - we are forced to use a specific version)

2
Bugs and Issues / Re: Change the order of template parameters
« on: February 20, 2018, 11:03:40 pm »
I have had a formal reply from Sparx that confirms my suspicion that (in EA 12.0.1214 the version that I am forced to use) that there is no GUI method to change the order of template parameters.

3
Bugs and Issues / Re: Change the order of template parameters
« on: January 24, 2018, 01:55:31 am »
Thanks Geert but I already tried that combination, sadly it doesn't work in this window  :'( >:(

4
Bugs and Issues / Change the order of template parameters
« on: January 23, 2018, 11:39:34 pm »
I have a class with template parameters (representing an Ada generic package). I need to add a new parameter in the middle of the list of existing parameters so I get the properties window for the class and select the Templates "tab" in the list on the left hand side. I click the "Add" button under "Template Parameter(s)" and add the new parameter and it gets added to the bottom of the list.

How can I move the newly created parameter upwards in the list to its correct position (in relation to my Ada generic package source code)? I cannot see any Up or Down arrows in the properties window. I searched the Help system for keyboard shortcuts. I tried combinations of Ctrl+SHIFT+Alt+UpArrow but no joy. I know that I can do it via Automation but I want a GUI version for end users.

Can someone enlighten me please?

Thanks
Darren

5
Sparx have confirmed this is a bug. I am using build 1214. Sparx have confirmed the bug is now logged to be fixed (implying that the bug exists in the current EA build 1351). Sparx have provided the workaround below. I have confirmed that it does work.

  • To restore the ORDER BY (part of the original SQL query) sort order add an extra field in the SELECT <fields> FROM … in the SQL query, re-run the SQL query (click "Yes" to save the search), now remove the extra field, re-run the SQL query (click "Yes" to save the search - it should now be back as your original SQL query).

Note, the extra field can be anything valid, I managed to just add a ", 1" (without the quotes) to the end of <fields> before the FROM clause.

Hope this helps someone else in the future.
Darren

6
Bug report/feature request sent to Sparx. I'll keep this thread posted on any outcome.

7
If I create an SQL query under Edit-->"Search in Model" it gets loaded into the "My Searches" list. If I run the query then I get the results in the bottom pane. I can click on any column heading to sort the results on that column heading (with an up arrow icon at the far right of the column heading), clicking again reverses the sort order (now with a down arrow). All pretty normal stuff just like in Windows Explorer, nice.

My question is "How do I turn the ordering off and revert back to the ORDER BY ordering mentioned in my SQL query"? Clicking the column heading a 3rd time does not turn that ordering off. If I close my EA project and open another one and run my query the clicked column is remembered and the up/down arrow is shown. This is getting a bit annoying since I had my SQL with a nice ORDER BY ordering that is no longer being obeyed.

Thanks
Darren

8
Ouchie.

Well, Repository.Execute() is undocumented and unsupported, but I'd be surprised if it was missing altogether. There aren't two versions of the API, are there? Are you sure it's not just missing from IntelliSense in your IDE?

I seem to recall using it in an Add-In, but I may be wrong about that.

/U

Unfortunately, I guess, we'll never know from Sparx (since it is unsupported). I was just repeating other people's posts about it.

9
"Dim myString As EA.Attribute" isn't typing myString, it's just letting EA's intellisense know. "Dim myString As String" fails because EA's intellisense doesn't know about Strings, just the EA Object Model.

Thanks for the clarification

10
Just in case anyone comes across this thread and tries the SendKeys solution that I proposed...there is a problem with SendKeys in that sometimes it will turn off the NumLock key! My final code ended up like this...

  • This is Excel VBA code
  • OutputInternalError is a little routine I wrote that is effectively the same as Debug.Print
Code: [Select]
Option Explicit

' This module was based on https://www.mrexcel.com/forum/excel-questions/677200-vba-remember-numlock-state.html

#If VBA7 Then
Private Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Long
#Else
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Long
#End If

' The SendKeys routine will sometimes turn off NumLock
' This routine fixes it
Public Sub FixSendKeys(ByVal sAppTitle As String, _
                       ByVal sKeys As String)
    Dim lSavedNumLockState As Boolean
   
    ' Save the current NumLock state
    lSavedNumLockState = NumLockStateIsOn

    ' Activate the required application and then send the keys to it
    '
    ' This might change (usually turn off) the NumLock key (the fault being fixed by this whole routine)
    AppActivate sAppTitle
    Application.SendKeys sKeys, True

    ' Check to see if the NumLock state has changed (fault of SendKeys)
    If lSavedNumLockState <> NumLockStateIsOn Then
        ' Simulate pressing NumLock key to set it back again
        Application.SendKeys "{NUMLOCK}", True
   
        ' Check again to make sure it has now changed
        If lSavedNumLockState <> NumLockStateIsOn Then
            ' Still hasn't changed
            OutputInternalError "NUMLOCK key still wrong"
        End If
    End If
End Sub

Private Function NumLockStateIsOn() As Boolean
    Const VK_NUMLOCK As Long = &H90
   
    ' IMPORTANT NOTE: It is necessary to call DoEvents to force a refresh of the keyboard state
    '                 Without DoEvents the keyboard state will sometimes return an old cached version
    DoEvents
    NumLockStateIsOn = (GetKeyState(VK_NUMLOCK) = 1)
End Function

and

Code: [Select]

Public Function GetEAWindowTitle() As String
    Dim sResult As String
    Dim vArr As Variant
   
   
   
    If IsModelEap() Then
        vArr = Split(mRep.ConnectionString, "\")
        sResult = vArr(UBound(vArr))
        sResult = Left(sResult, Len(sResult) - 4)
    Else
        vArr = Split(mRep.ConnectionString, " ---")
        sResult = vArr(0)
    End If
   
    sResult = sResult & " - Enterprise Architect"
   
    GetEAWindowTitle = sResult
End Function

Public Sub CloseEAProjectBrowser()
    ' Alt+0     View->Project Browser   (always opens the project browser - even if already open)
    ' Ctrl+F4   Close                   (closes the open window, i.e. the project browser)
    Call FixSendKeys(GetEAWindowTitle, "%0^{F4}")
End Sub

Public Sub OpenEAProjectBrowser()
    ' Alt+0     View->Project Browser   (always opens the project browser - even if already open)
    Call FixSendKeys(GetEAWindowTitle, "%0")
End Sub

11
Firstly an aside
I don't want to start a war on whether VBScript has types or not but the following didn't work in my in-EA script
Code: [Select]
Dim myString As String
I got "Expected end of statement". I would have thought String was a simple enough type for VBScript to handle. Removing "As String" worked. I also note that "Dim myString As EA.Attribute" worked. Did I define a string wrongly? Either way, it was the "catch type-related errors" that I was after so I couldn't use VBScript.




The main point I wanted to add was that one thing that I do miss with my out-of-EA scripts is not having the ability to use Repository.Execute(sqlString) to UPDATE the underlying database tables. This seems to be an undocumented feature of EA, i.e. not in the help file but mentioned in several forums (thanks Geert). Some bits of my EA model could not be updated via the Automation interface (COM?) so I had to resort to SQL UPDATE commands. I had to run a very small in-EA script that waited for SQL UPDATE requests via a control file (and some other handshaking) that would be written to by my large out-of-EA script. One example of this problem is linking an Action to an Operation (equivalent to dragging an operation onto an action in a diagram and creating a CallOperation Action).

If someone can tell me another way of updating the SQL tables I would be interested to hear. My workaround is OK but it does require me to start the in-EA script before my out-of-EA script. Also I need to run the in-EA script each time I load a new model.

12
I use VBA running from within Excel.

I started using that because I knew VBA/Excel rather than VBScript, JScript or JavaScript. These 3 "unknown to me" languages would have meant that I could run my scripts inside or outside EA.

However, I felt getting started with EA in VBA (a familiar environment) was more useful to me. I liked VBA's use of typing such as "Dim oAttribute As EA.Attribute" which would stop me writing stupid code trying to assign a parameter to the attribute (should have assigned it to an EA.Method). I would get a VBA compilation error rather than in VBScript (which doesn't have types) everything is a Variant and so stupid coding mistakes get hidden and pop up during testing instead. I felt I needed the hand-holding of the type system.

I have looked at Geert's examples on his website and other forums and found them very useful. Thanks Geert.

Any other language, e.g Java inside Eclipse, would not be executable inside EA. You would need to convert it to JavaScript later, much like I would have to convert VBA to VBScript. I have seen some benefits of running scripts inside EA and some outside EA. It all depends on what you want to do.

Hope that helps.

@ any guru - If I have said anything that is wrong please feel free to correct me; I'm open to being educated.

Darren

13
Is it possible to minimise the "Project Browser" via the Automation interface?

I ask because I am running a script (from Excel VBA) outside EA which is adding and deleting items in the model. While this is going on the Project Browser is flickering away as items are being added/deleted.

My script sets the following before updating
Code: [Select]
mRep.BatchAppend = True
mRep.EnableCache = True
mRep.EnableUIUpdates = False

My script sets the following after updating
Code: [Select]
mRep.EnableUIUpdates = True
mRep.EnableCache = False
mRep.BatchAppend = False
Call mRep.RefreshModelView(0)

According to the documentation I would have expected this to prevent the Project Browser from getting updated. Am I doing something wrong?

As an alternative is it possible to remove the Project Browser from the visible windows in EA via Automation? If the answer is yes, is it also possible to control the scripting window and other main EA windows?

I have managed to use AppActivate and SendKeys "%0^{F4}" but this is a bit of a fudge as there is a (small) possibility that another window gets focus and receives the keys. It also messes up my workflow when the focus is taken away from my main application (if the VBA script is running in the background). The "%0" is Alt+0 which (fortunately) always displays the Project Browser, i.e. doesn't toggle it. The "^{F4}" is Ctrl+F4 which hides the Project Browser.

Thanks
Darren

14
I raised a ticket with Sparx so we'll see if they can shed any light on my questions.
Thanks
Darren

15
I am attempting to edit an instantiation's "actual value" and am having difficulties. Can you help?

I have a class called GenericClass with a "formal parameter" Timer_expired.
I have a class called InstanceClass with a Generalization connector to GenericClass. The connector has a single TemplateBinding with .FormalName="Timer_expired" and .ActualName="20" showing that I am instantiating the generic with the value 20.

I now want to change the value to add "-a" via Automation.

I have noticed that the Help system says that the ActualName is Read/Write so I had...

Code: [Select]
' version 1
Set oInstanceClass = mrep.GetElementByGUID(<guid of InstanceClass>)    ' p1 = INPUT, return = EA.Element
Set oTemplateBinding = GetTemplateBinding(oInstanceClass, "Timer_expired")   ' p1, p2 = INPUT, return = EA.TemplateBinding
oTemplateBinding.ActualName = oTemplateBinding.ActualName & "-a"   ' Change the name a bit
Debug.Print oTemplateBinding.Update
Debug.Print oTemplateBinding.ActualName

The above sometimes prints False indicating a failure to update and the name is not altered. I need to know the FULL reason. I have a guess from my results below but this may only be half the story.



The GetTemplateBinding is a routine that I wrote since there is no Repository.GetTemplateBindingByGUID. I can get the GUID from an SQL query on t_xref with "Timer_expired". The GetTemplateBinding returns the template binding by taking the oInstanceClass to get the generalization connector (iterating over oInstanceClass.Connectors). From the generalization connector I then iterate over oConnector.TemplateBindings looking for .FormalName = the input string, i.e. "Timer_expired". When (if) I find it then I return the found object else return Nothing.

Interestingly if I take the code from my GetTemplateBinding and insert it inline into the above code then I get the following code

Code: [Select]
' version 2
Set oInstanceClass = mrep.GetElementByGUID(<guid of InstanceClass>)    ' p1 = INPUT, return = EA.Element
For Each oConnector In oInstanceClass.Connectors
    If oConnector.Type = "Generalization" Then
        Set oGeneralizationConnector = oConnector
    End If
Next oConnector
For Each oParameter In oGeneralizationConnector.TemplateBindings
    If oParameter.FormalName = "Timer_expired" Then
        Set oTemplateBinding = oParameter
    End If
Next oParameter
oTemplateBinding.ActualName = oTemplateBinding.ActualName & "-a"   ' Change the name a bit
Debug.Print oTemplateBinding.Update
Debug.Print oTemplateBinding.ActualName

Now the .Update prints True meaning that the update worked, and the name gets "-a" added, so the name prints out longer each time the code is run.

Interestingly, if I insert the extra line "Set oGeneralizationConnector = Nothing" to give this new code

Code: [Select]
' version 3
Set oInstanceClass = mrep.GetElementByGUID(<guid of InstanceClass>)    ' p1 = INPUT, return = EA.Element
For Each oConnector In oInstanceClass.Connectors
    If oConnector.Type = "Generalization" Then
        Set oGeneralizationConnector = oConnector
    End If
Next oConnector
For Each oParameter In oGeneralizationConnector.TemplateBindings
    If oParameter.FormalName = "Timer_expired" Then
        Set oTemplateBinding = oParameter
    End If
Next oParameter
Set oGeneralizationConnector = Nothing
oTemplateBinding.ActualName = oTemplateBinding.ActualName & "-a"   ' Change the name a bit
Debug.Print oTemplateBinding.Update
Debug.Print oTemplateBinding.ActualName

Now the .Update still prints True but the name does not get added to; as though EA says "I've successfully updated it but I haven't really".

This gave me the idea to return the Generalization connector at the same time as the TemplateBinding item so my code now looks like

Code: [Select]
' Version 4
Set oInstanceClass = mrep.GetElementByGUID(<guid of InstanceClass>)    ' p1 = INPUT, return = EA.Element
Call GetTemplateBinding(oInstanceClass, "Timer_expired", oGeneralizationConnector, oTemplateBinding)   ' p1, p2 = INPUT, p3, p4 = OUTPUT
oTemplateBinding.ActualName = oTemplateBinding.ActualName & "-a"   ' Change the name a bit
Debug.Print oTemplateBinding.Update
Debug.Print oTemplateBinding.ActualName

The above code now prints True and the name gets longer each time it runs. Interestingly I do not have to use the oGeneralizationConnector in this code at all. It seems that just the existence of the connector is enough to make everything work OK.

If I run the v2 code serveral times then v4 code everything works as expected. If I then call v1 or v3 then the first call to it will work (name gets increased) but subsequent calls the name stays the same length. If I then call v2 or v4 then the first call the name stays the same length (it doesn't work) but subsequent calls start working again (name gets increased). Weird.

I have noticed that the Help system says that the "TemplateBinding Class" attribute ActualName is Read/Write but the "Connector Class" attribute TemplateBinding is Read only. Perhaps this is part of the story, but I couldn't find anything in the help to help!

Question 1 - Why do I need the connector object in scope when I edit the TemplateBinding?
Question 2 - Are there any other things I need "in scope" or is just the connector and the TemplateBinding the whole solution?
Question 3 - Why does jumping between v2/v4 and v1/v3 cause the first call between jumps to change behaviour?
Question 4 - What other items in EA automation have this same "feature"?

Thanks
Darren


Pages: [1] 2