Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: Modesto Vega on July 03, 2024, 02:38:52 am
-
With announcement that VBScript support will be deprecated in the future, we have decided to try and write some new scripts using JavaScript and hit some problems. In JavaScript the following 2 lines of code result on the following message: "Object doesn't support this property or method".
selectedObject.Type = "Class";
selectedObject.StereotypeEx = "ArchiMate3::ArchiMate_Requirement";
Similar VBScript code works fine. What are we missing?
-
A complete stab in the dark. It is because of the Type property that is a preserved word or something?
Geert
-
I've noticed something similar when writing JavaScript.
According to the specifications, a variable should be declared using "let" or "const". The "var" seems to be something from the past.
However, I have succesfully used the "var" keyword to declare a variable of a certain object type, e.g.:
function setElementName( theElement /* : EA.Element */ ) /* : void */
{
var curElement as EA.Element;
curElement = theElement;
curElement.Name = "Name";
}
Still not very clear to me what the difference is between the use of "var" and "let" as "let as ..." generates compiler errors.
HTH
-
I posted some javascript code a while back on this forum that changes type and stereo type of elements. Do a search you might find it.
-
I posted some javascript code a while back on this forum that changes type and stereo type of elements. Do a search you might find it.
Thank you, much appreciated. I found several of your posts with JavaScript examples, the best one is perhaps https://sparxsystems.com/forums/smf/index.php/topic,48139.msg279730.html#msg279730, but nothing that changes the type and stereotype.
Furthermore, the script you shared on the message linked above very helpfully points to the Element API, but it is an older version and the link to go to the latest version is broken.
The biggest issue we have is that without any examples and/or documentation, none of us has time to figure out how how this should work in JavaScript. Since, it works in VBScript we may just have to bite the following when the functionality is removed.
-
The biggest issue we have is that without any examples and/or documentation, none of us has time to figure out how how this should work in JavaScript. Since, it works in VBScript we may just have to bite the following when the functionality is removed.
There are several sample scripts included in the installation. See you script library Local Scripts
The API documentation is the same for all languages.
Can you maybe post the rest of the script?
Your selectedObject object might not be of the right type. (e.g. EA.Diagram instead of EA.Element)
Geert
-
Current rough script looks like
!INC Local Scripts.EAConstants-JScript
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
Session.Output("Started");
if ( currentDiagram != null )
{
Session.Output(currentDiagram.Name);
// Get a reference to any selected connector/objects
var selectedConnector as EA.Connector;
var selectedElements as EA.Collection;
selectedElements = currentDiagram.SelectedObjects;
Session.Output(selectedElements.Count());
//selectedConnector = currentDiagram.SelectedConnector;
if ( selectedConnector != null )
{
// A connector is selected
}
else if (selectedElements.Count > 0 )
{
var objectCount = 0;
while (objectCount < selectedElements.Count())
{
Session.Output("Enumerating");
var currentElement as EA.Element;
currentElement = selectedElements.GetAt(objectCount);
Session.Output(currentElement.Type);
Session.Output(currentElement.Name);
currentElement.Type = "Class"; //Change the type - it fails
currentElement.Stereotype = ""; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
currentElement.Update();
currentElement.Stereotype = "ArchiMate_Requirement"; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
currentElement.Update();
//currentElement.StereotypeEx = "ArchiMate3::ArchiMate_Requirement"; //This also fails
objectCount = objectCount + 1;
}
}
else
{
// Nothing is selected
}
}
else
{
Session.Prompt( "This script requires a diagram to be visible.", promptOK)
}
}
OnDiagramScript();
All of this fails to execute
Session.Output(currentElement.Type);
Session.Output(currentElement.Name);
currentElement.Type = "Class"; //Change the type - it fails
currentElement.Stereotype = ""; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
...
currentElement.Stereotype = "ArchiMate_Requirement"; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
-
I don't even get that far
---------------------------
Error
---------------------------
Diagram Group.TestJavaScript
selectedElements.Count is not a function, Line:45
---------------------------
OK
---------------------------
After fixing the syntax errors I got an error on trying to display the element.Type
Session.Output(currentElement.Type);
That is because currentElement is an EA.DiagramObject, not an EA.Element
You would get exactly the same type of error in VBScript.
This works:
var currentDiagramObject as EA.DiagramObject;
currentDiagramObject = selectedElements.GetAt(objectCount);
var currentElement = Repository.GetElementByID(currentDiagramObject.ElementID);
Session.Output(currentElement.Type);
Session.Output(currentElement.Name);
Geert
-
Thanks Geert, much appreciated. Out of curiosity, what version are you using? We should we getting the same error you are getting with selectedElements.Count but we are not.
This works and have not changed selectedElements.Count.
!INC Local Scripts.EAConstants-JScript
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
Session.Output("Started");
if ( currentDiagram != null )
{
Session.Output(currentDiagram.Name);
// Get a reference to any selected connector/objects
var selectedConnector as EA.Connector;
var selectedElements as EA.Collection;
selectedElements = currentDiagram.SelectedObjects;
Session.Output(selectedElements.Count());
//selectedConnector = currentDiagram.SelectedConnector;
if ( selectedConnector != null )
{
// A connector is selected
}
else if (selectedElements.Count > 0 )
{
var objectCount = 0;
while (objectCount < selectedElements.Count())
{
Session.Output("Enumerating");
var currentDiagElement as EA.DiagramObject;
currentDiagElement = selectedElements.GetAt(objectCount);
var currentElement = Repository.GetElementByID(currentDiagElement.ElementID);
Session.Output(currentElement.Type);
Session.Output(currentElement.Name);
currentElement.Type = "Class"; //Change the type - it fails
currentElement.Stereotype = ""; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
currentElement.Update();
currentElement.Stereotype = "ArchiMate_Requirement"; //Clear the Current Stereotype - it fails with both Stereotype and StereotypeEx
currentElement.Update();
//currentElement.StereotypeEx = "ArchiMate3::ArchiMate_Requirement"; //This also fails
objectCount = objectCount + 1;
}
}
else
{
// Nothing is selected
}
}
else
{
Session.Prompt( "This script requires a diagram to be visible.", promptOK)
}
}
OnDiagramScript();
-
I've tested this with version 16.1 as a javascript script (not Jscript)
Geert
-
Same version. What I cannot check right now is how we ended with JScript when I thought we created a JavaScript script.
Also, I am sure I want to ask this after an online search but what is the difference and why do they look so horribly and confusedly similar?
-
Jscript is Microsofts copy of Javascript.
The main difference is that it's being interpreted and executed by a different application.
There are a few differences in syntax. One of them is the way to create objects from other libraries.
Geert
-
Please find below a working JavaScript for reference, oddly selectedObjects.Count() does not error and have not time to research what is the difference.
!INC Local Scripts.EAConstants-JavaScript
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
if ( currentDiagram != null )
{
// Get a reference to any selected connector/objects
var selectedConnector as EA.Connector;
var selectedObjects as EA.Collection;
selectedConnector = currentDiagram.SelectedConnector;
selectedObjects = currentDiagram.SelectedObjects;
if ( selectedConnector != null )
{
// A connector is selected
}
else if ( selectedObjects.Count > 0 )
{
// One or more diagram objects are selected
var objectCount = 0;
while (objectCount < selectedObjects.Count())
{
Session.Output("Enumerating");
var currentDiagElement as EA.DiagramObject;
currentDiagElement = selectedObjects.GetAt(objectCount);
var currentElement = Repository.GetElementByID(currentDiagElement.ElementID);
Session.Output(currentElement.Type);
Session.Output(currentElement.Name);
currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
currentElement.Stereotype = "ArchiMate_Requirement";
currentElement.Update();
objectCount = objectCount + 1;
}
}
else
{
// Nothing is selected
}
}
else
{
Session.Prompt( "This script requires a diagram to be visible.", promptOK)
}
}
OnDiagramScript();
-
Why use both "selectedObjects.Count()" and "selectedObjects.Count"?
Count is a property and should not be used as a method?
Further do you get the desired ArchiMate type?
When I use something similar in my scripts, I end up with stereotype "ArchiMate::ArchiMate_Requirement" which is an ArchiMate2 reference instead of ArchiMate3.
-
Yeah, you should really only use the fully qualified stereotype. Otherwise EA will be guessing which profile you want it from and use the first one it finds.
so something like
element.SteretoypEx = "ArchiMate3::ArchiMate_Requirement"
PS. Check for uppercase/lowercase because that matters in these cases
Geert
-
I created a JavaScript Library MDG a while back with a script that does that. You can find it along with the Sparx Model that created it on git hub. https://github.com/EASunshine/Sparx-EA/tree/master (https://github.com/EASunshine/Sparx-EA/tree/master)
-
Well, this is now officially confusing.
Based on this comment
Why use both "selectedObjects.Count()" and "selectedObjects.Count"?
Count is a property and should not be used as a method?
Further do you get the desired ArchiMate type?
When I use something similar in my scripts, I end up with stereotype "ArchiMate::ArchiMate_Requirement" which is an ArchiMate2 reference instead of ArchiMate3.
Upon changing the script to use selectedObjects.Count on the while loop. The end result is a bit puzzling:
1) The code changing the type of element no longer works - i.e., this code currentElement.Type = "Class";
now does not do anything. But currentElement.Stereotype = "ArchiMate_Requirement
changes the stereotype.
2) Even worse using using currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
currentElement.SteretoypEx = "ArchiMate3::ArchiMate_Requirement";
does nothing, it does not change the type or the stereotype
3) and, just to put the cherry on the cake, reverting back to selectedObjects.Count() now results on the error I would expect after reading the post above.
In short, the JavaScript scripting engine appears to be exhibiting inconsistent behaviour without nay Sparx EA upgrade.
-
Sorry, but I think you are mixing Stereotype and StereotypeEx (apart from the typo):
currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
currentElement.SteretoypEx = "ArchiMate3::ArchiMate_Requirement";
I think it should be:
currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
currentElement.Stereotype = "ArchiMate3::ArchiMate_Requirement";
currentElement.Update();
According to the documentation StereotypeEx is a list of Stereotypes (see https://www.sparxsystems.com/enterprise_architect_user_guide/16.1/add-ins___scripting/element2.html (https://www.sparxsystems.com/enterprise_architect_user_guide/16.1/add-ins___scripting/element2.html)).
-
Thank you DeBAAT, but I am still officially confused, perhaps because it has been a long week and I am no longer used to writing code.
This script is doing some seriously strange things.
!INC Local Scripts.EAConstants-JavaScript
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
if ( currentDiagram != null )
{
// Get a reference to any selected connector/objects
var selectedConnector as EA.Connector;
var selectedObjects as EA.Collection;
selectedConnector = currentDiagram.SelectedConnector;
selectedObjects = currentDiagram.SelectedObjects;
if ( selectedConnector != null )
{
// A connector is selected
}
else if ( selectedObjects.Count > 0 )
{
// One or more diagram objects are selected
var objectCount = 0;
while (objectCount < selectedObjects.Count)
//while (objectCount < selectedObjects.Count())
{
Session.Output("Enumerating");
var currentDiagElement as EA.DiagramObject;
currentDiagElement = selectedObjects.GetAt(objectCount);
var currentElement = Repository.GetElementByID(currentDiagElement.ElementID);
Session.Prompt(currentElement.Type, promptOK); //[1]
Session.Prompt(currentElement.Name, promptOK); //[2]
//Session.Prompt(currentElement.Steretoype, promptOK); //[3]
currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
//currentElement.Steretoype = "ArchiMate_Requirement"; //[5]
currentElement.Steretoype = "ArchiMate3::ArchiMate_Requirement"; //[6]
currentElement.Update();
Session.Prompt(currentElement.Type, promptOK); //[7]
Session.Prompt(currentElement.Name, promptOK); //[8]
Session.Prompt(currentElement.Steretoype, promptOK); //[9]
objectCount = objectCount + 1;
}
}
else
{
// Nothing is selected
}
}
else
{
Session.Prompt( "This script requires a diagram to be visible.", promptOK)
}
Repository.ReloadDiagram(currentDiagram.DiagramID);
}
OnDiagramScript();
1) Lines 47 & 48, marked [1] & [2], return the correct values.
2) Line 49, marked [3], always errors, if not commented out, but it is an exact copy of line 58. The error is "Parameter 1 type mismatch". I am attributing this to the stereotype being blank, but if that is the case, it must be a bug, see below.
3) Lines 53 and 54, marked [7] & [8], both work. We are settling with line 54.
4) Line 56, marked [7], returns the correct type, as per the change from line 50.
5) Line 58, marked [9], returns the stereotype as per the change from line 54.
6) Nothing else visibly errors.
7) Line 72 reloads a diagram with all elements changed as per line 50 - i.e., to a class, but a blank/empty stereotype - i.e., the change applied by lines 54, mark as [7] and 55, and correctly displayed by line 58, marked as [9], disappear.
8) Just to help matters, sarcasm intended, line 58, marked [9], does not error, despite now having a blank/empty stereotype, but line 49, mark as [3], always errors when not commented out.
-
//Session.Prompt(currentElement.Steretoype, promptOK); //[3]
2) Line 49, marked [3], always errors, if not commented out, but it is an exact copy of line 58. The error is "Parameter 1 type mismatch". I am attributing this to the stereotype being blank, but if that is the case, it must be a bug, see below.
Please look carefully how you have spelled Stereotype in your code above, as in line [9] and [6]
Geert
-
As Geert said, check your spelling.
In line [3], you are using a non-defined property "Steretoype".
In line [6], you are assigning this non-defined property a value, thus making it defined.
In line [9], this does not generate an error because you defined the property in line [6].
Sometimes it is nice to have weak type-checking, sometimes it is not...
-
If you are seeing weird results when testing scripts, it might be due to caching.
In some circumstances (I don't know exactly when) EA caches scripts when executing.
So you think you are executing version B, but in fact you are still executing a cached version A.
If you suspect that is happening you might want to exit and restart EA.
Geert
-
As Geert said, check your spelling.
In line [3], you are using a non-defined property "Steretoype".
In line [6], you are assigning this non-defined property a value, thus making it defined.
In line [9], this does not generate an error because you defined the property in line [6].
Sometimes it is nice to have weak type-checking, sometimes it is not...
Sorry but IMHO this is a bug. Stereotype is a property of the Element object, if it is mistyped - e.g., Steretoype - I am expecting Sparx EA to throw and error instead of going through it as if it were a supported property. I find very odd that methods are strongly typed but properties are not, essentially this means that I can try to fabricate any for any object which is very questionable.
If you are seeing weird results when testing scripts, it might be due to caching.
In some circumstances (I don't know exactly when) EA caches scripts when executing.
So you think you are executing version B, but in fact you are still executing a cached version A.
If you suspect that is happening you might want to exit and restart EA.
Geert
Since the prompts always appear in the right sequence, this may not be due to caching.
Anyway, a working version of the script is below, a key change (other than the spelling corrections) was the addition of the following line "var currentElement as EA.Element;"
!INC Local Scripts.EAConstants-JavaScript
/*
* This code has been included from the default Diagram Script template.
* If you wish to modify this template, it is located in the Config\Script Templates
* directory of your EA install path.
*
* Script Name:
* Author:
* Purpose:
* Date:
*/
/*
* Diagram Script main function
*/
function OnDiagramScript()
{
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
if ( currentDiagram != null )
{
// Get a reference to any selected connector/objects
var selectedConnector as EA.Connector;
var selectedObjects as EA.Collection;
selectedConnector = currentDiagram.SelectedConnector;
selectedObjects = currentDiagram.SelectedObjects;
if ( selectedConnector != null )
{
// A connector is selected
}
else if ( selectedObjects.Count > 0 )
{
// One or more diagram objects are selected
var objectCount = 0;
while (objectCount < selectedObjects.Count)
//while (objectCount < selectedObjects.Count())
{
Session.Output("Enumerating");
var currentDiagElement as EA.DiagramObject;
var currentElement as EA.Element;
currentDiagElement = selectedObjects.GetAt(objectCount);
currentElement = Repository.GetElementByID(currentDiagElement.ElementID);
//Session.Prompt(currentElement.Type, promptOK); //[1]
//Session.Prompt(currentElement.Name, promptOK); //[2]
//Session.Prompt(currentElement.Stereotype, promptOK); //[3]
currentElement.Type = "Class";
currentElement.Stereotype = "";
currentElement.Update();
//currentElement.Stereotype = "ArchiMate_Requirement"; //[5]
currentElement.Stereotype = "ArchiMate3::ArchiMate_Requirement"; //[6]
currentElement.Update();
//Session.Prompt(currentElement.Type, promptOK); //[7]
//Session.Prompt(currentElement.Name, promptOK); //[8]
//Session.Prompt(currentElement.Stereotype, promptOK); //[9]
objectCount = objectCount + 1;
}
}
else
{
// Nothing is selected
}
}
else
{
Session.Prompt( "This script requires a diagram to be visible.", promptOK)
}
Repository.ReloadDiagram(currentDiagram.DiagramID);
}
OnDiagramScript();
My conclusion is that writing JavaScripts is a very cumbersome time consuming process which is better to avoid unless there is an abundance of spare time.
-
My conclusion is that writing JavaScripts is a very cumbersome time consuming process which is better to avoid unless there is an abundance of spare time.
I agree that there is a steep learning curve, but once you have mastered the skill, it is pretty fast and very powerful.
Geert
-
I am not worried about the learning curve. I am more worried about having weakly typed properties and strongly typed methods; presumably the former is the reason why 1) the script editor does not show the properties in a different font colour, and 2) Sparx EA does not throw any errors.
Agreed scripts are very powerful but life will be easier if they were not required certain operations.
-
I am not worried about the learning curve. I am more worried about having weakly typed properties and strongly typed methods; presumably the former is the reason why 1) the script editor does not show the properties in a different font colour, and 2) Sparx EA does not throw any errors.
Agreed scripts are very powerful but life will be easier if they were not required certain operations.
I have been using VBScript in EA for ages, now, so I was a bit surprised that indeed Javascript doesn't automatically raises an exception if you try to access a property that doesn't exist.
According to this post on stackoverflow https://stackoverflow.com/a/32214394/2018133 (https://stackoverflow.com/a/32214394/2018133) that is a feature that might be turned on, but I wouldn't know if or how that could work in EA.
Maybe there are some more experienced Javascript coders here that know how to avoid typo's like that?
Geert
-
I do not know how to turn that feature on.
I do know that the internal JavaScript editor within EA is capable of autocompleting both methods and properties.
So I usually try to either copy/paste code or add the property by the autofill of the editor.
-
It does auto-complete methods but, in our installation base, it does not auto-complete properties, and we don't know how to turn that on.
Getting to auto-complete properties will definitely make a big difference.
-
Strange, can't recall changing any settings regarding JavaScripting.
In my configuration, after setting the '.' (dot), the editor shows a pop-up with both methods and properties.
All in one single list, sorted alphabetically.
There is a difference in the color though.
-
Strange, can't recall changing any settings regarding JavaScripting.
In my configuration, after setting the '.' (dot), the editor shows a pop-up with both methods and properties.
All in one single list, sorted alphabetically.
There is a difference in the color though.
After a full system reboot I get both methods and properties on a list after entering the '.' (dot) for everything in the script.
Somehow I got in my head that a) I have seem a similar behaviour with VBScript, and b) it has something to do with how the scripts are written, specially if they are weakly typed by accident or design.
Regarding the later point, I have not tried this yet but I am wondering if the following explains the issue with the script editor listing the methods and properties of an object; an earlier version of the script
1) was missing the following line var currentElement as EA.Element;
2) only had the following line - i.e., currentElement was, as you pointed out, weakly typed currentElement = Repository.GetElementByID(currentDiagElement.ElementID);
3) as a result, typing currentElement followed by '.' (dot) did not result on a list of methods and methods for this particular object because it was weakly typed;
4) when we introduced the line of code on point 1, it continued not listing methods and properties for that object because of caching;
5) a full system reboot cleared the caches and everything started working as expected.
-
Autocomplete and strong typing are two different things.
var currentElement as EA.Element;
Doesn't make your currentElement strong typed. It only enables the autocomplete in the code editor.
(at least for VBScript. I'm not 100% sure that applies to Javascript as well)
Geert
-
Thank you Geert, I'll rather not start a strongly vs weakly type thread here.
From your reply, I am concluding that you are confirming that without
var currentElement as EA.Element;
the code editor will not be able to auto-complete. Is that correct?
-
Thank you Geert, I'll rather not start a strongly vs weakly type thread here.
From your reply, I am concluding that you are confirming that without
var currentElement as EA.Element;
the code editor will not be able to auto-complete. Is that correct?
Yes, that's what I meant.
Geert
-
https://sparxsystems.com/forums/smf/index.php/topic,39510.msg243782/topicseen.html#msg243782 (https://sparxsystems.com/forums/smf/index.php/topic,39510.msg243782/topicseen.html#msg243782)