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 - Geert Bellekens

Pages: [1] 2 3 ... 884
1
Automation Interface, Add-Ins and Tools / Re: Assign Color to Tab
« on: February 07, 2025, 08:44:53 pm »
You can't control the tabpages from EA.

What you can do is within your user interface create your own tabcontrol and color those.

Geert

2
General Board / Re: Replace an element in a diagram with another element
« on: February 05, 2025, 06:44:19 pm »
I use a script to do the same:
It uses some functions defined in my framework scripts that can be found here: https://github.com/GeertBellekens/Enterprise-Architect-VBScript-Library/tree/master/Framework
Code: [Select]
!INC Wrappers.Include
!INC Local Scripts.EAConstants-VBScript

'
' Script Name: MergeDuplicatesMain
' Author: Geert Bellekens
' Purpose: Merge duplicated elements into one
' Date: 2022-05-13
'
'name of the output tab
const outPutName = "Merge Duplicates"

sub Merge
'exit if not on element
if Repository.GetContextItemType() <> otElement then
msgbox "Script only works on elements. Please select an element before executing this script"
exit sub
end if
'get selected element
dim selectedElement as EA.Element
set selectedElement = Repository.GetContextObject()
'Let the user select the original object
msgbox "Please select the original object"
dim originalElement as EA.Element
set originalElement = getUserSelectedElement(selectedElement)
'check if user selected
if originalElement is nothing then
msgbox "User cancelled script"
exit sub
end if

'check if user did not select the same element twice
if originalElement.ElementID = selectedElement.ElementID then
msgbox "Please select a different element"
exit sub
end if
'check if the name and type of the element are the same
if originalElement.Name <> selectedElement.Name _
  or originalElement.Type <> selectedElement.Type then
msgbox "Please select an element with the same name and type"
exit sub
end if
'Ask user if he is sure
dim response
response = msgbox("Merge '" & selectedElement.FQName & "' to '" & originalElement.FQName & "'?" , vbYesNo+vbQuestion, "Merge Elements?")
if response <> vbYes then
'user did not confirm
exit sub
end if
'create output tab
Repository.CreateOutputTab outPutName
Repository.ClearOutput outPutName
Repository.EnsureOutputVisible outPutName
'set timestamp
Repository.WriteOutput outPutName, now() & " Starting merge of '" & selectedElement.Name & "'", selectedElement.ElementID
'start with diagram usages
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Diagrams for '" & selectedElement.Name & "'", selectedElement.ElementID
fixDiagrams selectedElement, originalElement
'then process relations
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Relations for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeRelations selectedElement, originalElement
'then process instances
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Instances for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeInstances selectedElement, originalElement
'process nested elements
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Nested Elements for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeNestedElements selectedElement, originalElement
'process nested diagrams
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Nested Diagrams for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeNestedDiagrams selectedElement, originalElement
'process attributes using this entity as type
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Attributes for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeUsingAttributes selectedElement, originalElement
'process parameters using this entity as type
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Parameters for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeUsingParameters selectedElement, originalElement
'process operations using this enity as return type
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Operations for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeUsingOperations selectedElement, originalElement
'set timestamp
Repository.WriteOutput outPutName, now() & " Fixing Conveying Informationflows for '" & selectedElement.Name & "'", selectedElement.ElementID
mergeConveyingInformationFlows selectedElement, originalElement
'refresh
'Repository.RefreshModelView(0)
response = msgbox("Delete '" & selectedElement.FQName & "'?" , vbYesNo+vbQuestion, "Delete Element?")
if response = vbYes then
'user confirmed
deleteElement selectedElement
end if
'set timestamp
Repository.WriteOutput outPutName, now() & " Finished merge of '" & selectedElement.Name & "'", selectedElement.ElementID
end sub

function deleteElement(element)
dim owner as EA.Element
if element.ParentID > 0 then
set owner = Repository.GetElementByID(element.ParentID)
else
set owner = Repository.GetPackageByID(element.PackageID)
end if
dim i
for i = 0 to owner.Elements.Count -1
dim temp
set temp = owner.Elements(i)
if temp.ElementID = element.ElementID then
owner.Elements.DeleteAt i, false
exit function
end if
next
end function

function mergeConveyingInformationFlows(duplicateElement, originalElement)
'find operations that have the element as type of a parameter (or returntype)
dim sqlUpdate
sqlUpdate = "update x set x.Description = replace(x.Description, '" & duplicateElement.ElementGUID & "', '" & originalElement.ElementGUID & "')    " & vbNewLine & _
" from t_xref x                                                                                                                          " & vbNewLine & _
" where x.Behavior = 'conveyed'                                                                                                          " & vbNewLine & _
" and x.Description like '%" & duplicateElement.ElementGUID & "%'                                                                        "

'execute update statement
Repository.Execute sqlUpdate
end function

function mergeUsingOperations(duplicateElement, originalElement)
'find operations that have the element as type of a parameter (or returntype)
dim sqlGetOperations
sqlGetOperations = "select op.OperationID from t_operation op where op.Classifier = " & duplicateElement.ElementID
dim operations
set operations = getOperationsFromQuery(sqlGetOperations)
'loop operations
dim operation as EA.Method
for each operation in operations
operation.ClassifierID = originalElement.ElementID
operation.ReturnType = originalElement.Name
operation.Update
next
end function

function mergeUsingParameters(duplicateElement, originalElement)
'find operations that have the element as type of a parameter (or returntype)
dim sqlGetOperations
sqlGetOperations = "select distinct opr.OperationID from t_operationparams opr where opr.Classifier = " & duplicateElement.ElementID
dim operations
set operations = getOperationsFromQuery(sqlGetOperations)
'loop operations
dim operation as EA.Method
for each operation in operations
'loop parameters
dim parameter as EA.Parameter
for each parameter in operation.Parameters
if parameter.ClassifierID = CStr(duplicateElement.ElementID) then 'need to convert to string because parameter.ClassifierID is a string and not a long
parameter.ClassifierID = originalElement.ElementID
parameter.Type = originalElement.Name
parameter.Update
end if
next
next
end function

function mergeUsingAttributes(duplicateElement, originalElement)
'find using attributes
dim sqlGetAttributes
sqlGetAttributes = "select a.ID from t_attribute a where a.Classifier = " & duplicateElement.ElementID
dim attributes
set attributes = getattributesFromQuery(sqlGetAttributes)
'loop attributes
dim attribute as EA.Attribute
for each attribute in attributes
attribute.ClassifierID = originalElement.ElementID
attribute.Type = originalElement.Name
attribute.Update
next
end function

function mergeNestedDiagrams(duplicateElement, originalElement)
dim nestedDiagram as EA.Diagram
for each nestedDiagram in duplicateElement.Diagrams
nestedDiagram.ParentID = originalElement.ElementID
nestedDiagram.PackageID = originalElement.PackageID
nestedDiagram.Update
next
end function

function mergeNestedElements(duplicateElement, originalElement)
dim nestedElement as EA.Element
for each nestedElement in duplicateElement.Elements
nestedElement.ParentID = originalElement.ElementID
nestedElement.Update
next
end function

function mergeInstances(duplicateElement, originalElement)
'find all instances
dim sqlFindInstances
sqlFindInstances = "select  o.Object_ID from t_object o where o.Classifier = " & duplicateElement.ElementID
dim instances
set instances = getElementsFromQuery(sqlFindInstances)
'loop instances
dim instance as EA.Element
for each instance in instances
instance.ClassifierID = originalElement.ElementID
instance.Update
next
end function


'move all relations from and to the duplicate element to the original element
function mergeRelations(duplicateElement, originalElement)
'move all relations from the dupliate element to the original element
dim relation as EA.Connector
for each relation in duplicateElement.Connectors
'move the relation to the original element
'set source
if relation.ClientID = duplicateElement.ElementID then
relation.ClientID = originalElement.ElementID
end if
'set target
if relation.SupplierID = duplicateElement.ElementID then
relation.SupplierID = originalElement.ElementID
end if
'check if such relation already exists
dim mergedDuplicate as EA.Connector
set mergedDuplicate = getMergedExistingRelation(relation, originalElement)
if not mergedDuplicate is nothing then
'save the possible changed to the merged duplicate
mergedDuplicate.Update
else
'save the changes
relation.Update
end if
next
end function

'check if a relation already exists
function getMergedExistingRelation(relation, originalElement)
'initialize at nothing
set getMergedExistingRelation = nothing
dim orgRelation as EA.Connector
for each orgRelation in originalElement.Connectors
do 'do loop to be able to skip to next
'check all parameters to skip to the next
if relation.Type <> orgRelation.Type _
or relation.ClientID <> orgRelation.ClientID _
or relation.SupplierID <> orgRelation.SupplierID _
or relation.ConnectorID = orgRelation.ConnectorID then 'if it's the same then we skip as well
exit do 'skip to next
end if
'set the name equal if empty
if relation.Name <> orgRelation.Name then
if len(orgRelation.Name) = 0 then
orgRelation.Name = relation.Name
end if
if len(relation.Name) = 0 then
relation.Name = orgRelation.Name
end if
end if
'compare name
if relation.Name <> orgRelation.Name then
exit do 'skip to next
end if
'compare source end
if not compareMergedConnectorEnd(relation.ClientEnd, orgRelation.ClientEnd) then
exit do 'skip to next
end if
'compare target end
if not compareMergedConnectorEnd(relation.SupplierEnd, orgRelation.SupplierEnd) then
exit do 'skip to next
end if 
'if we get here then we have a valid merged duplicate. Return connector and exit
set getMergedExistingRelation = orgRelation
exit function
Loop While False
next
end function

function compareMergedConnectorEnd (connectorEnd, orgConnectorEnd)
'initialize false
compareMergedConnectorEnd = false
'merge cardinality
if orgConnectorEnd.Cardinality <> connectorEnd.Cardinality then
if len(orgConnectorEnd.Cardinality) = 0 then
orgConnectorEnd.Cardinality = connectorEnd.Cardinality
end if
if len(connectorEnd.Cardinality) = 0 then
connectorEnd.Cardinality = orgConnectorEnd.Cardinality
end if
end if
'compare cardinality
if getUnifiedMultiplicity(orgConnectorEnd.Cardinality) <> getUnifiedMultiplicity(connectorEnd.Cardinality) then
exit function
end if
'compare aggregationKind
if orgConnectorEnd.Aggregation <> connectorEnd.Aggregation then
exit function
end if
'merge rolename
if orgConnectorEnd.Role <> connectorEnd.Role then
if len(orgConnectorEnd.Role) = 0 then
orgConnectorEnd.Role = connectorEnd.Role
end if
if len(connectorEnd.Role) = 0 then
connectorEnd.Role = orgConnectorEnd.Role
end if
end if
'compare roleName
if orgConnectorEnd.Role <> connectorEnd.Role then
exit function
end if
'if we end up here they are the same
compareMergedConnectorEnd = true
end function

function getUnifiedMultiplicity(multiplicity)
getUnifiedMultiplicity = Replace(multiplicity, "0..*", "*")
getUnifiedMultiplicity = Replace(getUnifiedMultiplicity, "1..1", "1")
end function


function getUserSelectedElement(duplicateElement)
'get best match for original element
dim candidateOriginal as EA.Element
set  candidateOriginal =  getBestCandidateForOriginal(duplicateElement)
'build construct picker string.
dim constructpickerString
constructpickerString = "IncludedTypes=" & duplicateElement.Type
if len(duplicateElement.Stereotype) > 0 then
constructpickerString = constructpickerString & ";StereoType=" & duplicateElement.Stereotype
end if
if not candidateOriginal is nothing then
constructpickerString = constructpickerString & ";Selection=" & candidateOriginal.ElementGUID
else
constructpickerString = constructpickerString & ";Selection=" & duplicateElement.ElementGUID
end if
'invoke the construct picker
dim userSelectedElementID
userSelectedElementID = Repository.InvokeConstructPicker(constructpickerString)
if userSelectedElementID > 0 then
set getUserSelectedElement = Repository.GetElementByID(userSelectedElementID)
else
set getUserSelectedElement = nothing
end if
end function

function getBestCandidateForOriginal(duplicateElement)
'initialize at null
set getBestCandidateForOriginal = nothing
dim sqlGetData
sqlGetData = "select top(1) o.Object_ID from t_object o                             " & vbNewLine & _
" left join                                                            " & vbNewLine & _
"  (select do.Object_ID, count(*) as NumberOfUsesOnDiagram from       " & vbNewLine & _
"   (select do.object_ID as Object_ID                              " & vbNewLine & _
"   from t_diagramobjects do                                       " & vbNewLine & _
"   union all                                                      " & vbNewLine & _
"   select oo.Classifier                                           " & vbNewLine & _
"   from t_diagramobjects do                                       " & vbNewLine & _
"   inner join t_object oo on oo.Object_ID = do.Object_ID          " & vbNewLine & _
"   ) do                                                           " & vbNewLine & _
"   group by do.Object_ID                                          " & vbNewLine & _
"  ) do2 on do2.Object_ID = o.Object_ID                               " & vbNewLine & _
" where o.Name = '" & duplicateElement.Name & "'                       " & vbNewLine & _
" and o.Object_ID <> " & duplicateElement.ElementID & "                " & vbNewLine & _
" and o.Object_Type = '" & duplicateElement.Type & "'                  " & vbNewLine & _
" and isnull(o.Stereotype, '') = '" & duplicateElement.Stereotype & "' " & vbNewLine & _
" order by isnull(do2.NumberOfUsesOnDiagram, 0) desc                   "
dim results
set results = getElementsFromQuery(sqlGetData)
if results.Count > 0 then
set getBestCandidateForOriginal = results(0)
end if
end function

'Quick and dirty via a database update
function fixDiagramsQuick(duplicateElement, originalElement)
dim sqlUpdateDiagrams
sqlUpdateDiagrams = "update t_diagramobjects set Object_ID = " & originalElement.ElementID & " where Object_ID = " & duplicateElement.ElementID
Repository.Execute sqlUpdateDiagrams
end function

function fixDiagrams(duplicateElement, originalElement)
'get diagrams where the duplicate element is shown
dim sqlGetDiagrams
sqlGetDiagrams = "select distinct do.Diagram_ID from t_diagramobjects do where do.Object_ID = " & duplicateElement.ElementID
dim diagrams
set diagrams = getDiagramsFromQuery(sqlGetDiagrams)
'loop diagrams
dim diagram as EA.Diagram
for each diagram in diagrams
'get diagramObject for the duplicate element
dim diagramObject as EA.DiagramObject
for each diagramObject in diagram.DiagramObjects
if diagramObject.ElementID = duplicateElement.ElementID then
diagramObject.ElementID = originalElement.ElementID
diagramObject.Update
'we could do an "exit for" here since in theory there should only be one diagramObject for a single element, but to be safe we don't.
end if
next
next
end function


Geert

3
Yes, definitely a bug.

Geert

4
AFAIK there is no setting in EA that influences this.

A complete guess is that this is related to high dpi screens.
I know that there have been other issues (very small font sizes) with those type of screens.

Geert

5
Automation Interface, Add-Ins and Tools / Re: Get WebEA link via API
« on: January 30, 2025, 11:51:15 pm »
select * from usys_system where property = 'webEAUrl'

Geert

6
Automation Interface, Add-Ins and Tools / Re: Extend a Menu
« on: January 30, 2025, 06:41:36 pm »
Yes, you can completely customize the menu entries (within Specialize|<YourAddin>) depending on the selected item and location (diagram, treeview, menu)

Geert

7
Bugs and Issues / Re: Document generation broken in v16.1
« on: January 27, 2025, 10:22:27 pm »
Hi Jens,

Make sure to contact sparx support with your issues (if you haven't already)

They eventually fixed all the issues I reported and we are now preparing for an upgrade to v17

Geert

8
Bugs and Issues / Re: Sparx EA to crash - v17 streamed from Citrix
« on: January 24, 2025, 06:07:19 pm »
a Citrix compatibility issue
We don't support running on Citrix, so I wouldn't be surprised if there were compatibility issues.
Hi Eve, this is the first I've heard of it. Is this documented on the website?

I have several clients running EA on Citrix for years without any issues.

Geert

9
Have you tried using Element.LoadLinkedDocument(string Filename)
I think that does the same as your code.

Geert

10
General Board / Re: RTF recipe how to print state.name and state.notes
« on: January 23, 2025, 01:20:02 am »
You are not supposed to put anything between the child element tags.
It will automatically apply the same template on the child elements.

If you search the forum there should be a couple of examples I posted for sql fragments.

Geert

11
General Board / Re: RTF recipe how to print state.name and state.notes
« on: January 22, 2025, 11:48:12 pm »
States are child elements under the state machine element.
If you check the box "child elements" it will automatically iterate over these elements.

I personally usually use a sql template fragment for things like this.

Geert

12
General Board / Re: RTF recipe how to print state.name and state.notes
« on: January 22, 2025, 11:35:24 pm »
I'm not sure what you mean by "in a recipe", but you can write a scrpt to loop the states.

Otherwise you can use report generation templates to generate a report as well.

Geert

13
Does anybody have experience using ChatGPT for these conversions?
I've done some experiments (mainly to translate vbscripts to javascript) and using an AI works mostly, but you'll still need some manual work.
The downside is that the code generated by such an AI always looks plausable, so it's hard to spot the errors.

I also tried https://www.codeporting.ai/ and I was very happy with the results, especially since you can include additional instructions (like leaving the "as EA.Element" and the likes)

Geert

14
General Board / Re: Converting the Model File to HTML Report
« on: January 20, 2025, 07:06:04 pm »
Might be related to model security.
If it works on a new local model, then it's probably that.

Geert

15
General Board / Re: Various questions about attributes and tags
« on: January 17, 2025, 12:14:52 am »
If it's metadata, it should go into tagged values.

If it's data then it should be modelled as attributes.

1. No, you can't export attributes with the CSV import/export feature
2. No, I don't think "inherited tags" are exported to CSV. There is also not really an "inherit" when it comes to tagged values. Each element has it's own set of tagged values. I know EA kinda makes you think that, but that is purely a visual GUI thing.
3. You can query the tags in a shapescript, but not the attributes. So you can do the color thing with tags, but not with attributes.

Geert

Pages: [1] 2 3 ... 884