Skip to content

Instantly share code, notes, and snippets.

@smileham
Last active April 24, 2024 16:44
Show Gist options
  • Save smileham/15c445b17a92bd6f5dc1508e573bcd8a to your computer and use it in GitHub Desktop.
Save smileham/15c445b17a92bd6f5dc1508e573bcd8a to your computer and use it in GitHub Desktop.
Export to CSV #jarchi
/*
* Export To CSV
*
* Requires jArchi - https://www.archimatetool.com/blog/2018/07/02/jarchi/
* Requires PapaParse - https://www.papaparse.com/
* Works with Import from CSV script - https://gist.github.com/smileham/1e57a5946235e780dee5a824f664aa3d
*
* Version 1: Export to CSV
* Version 1.1: Avoid duplicate concepts exported from diagram
* Version 1.2: Fix missing properties
* Version 2: Updated to export Relationships to additional CSV
* Version 2.1: Added error check for View.
* Version 2.2: Added support for Specialization
* Version 2.3: Added UTF-8 BOM to (hopefully) fix Excel export
* Version 2.4: Added support for relationship properties export (by @isalew)
*
* (c) 2018 Steven Mileham
*
*/
var debug = false;
// Show output in the console
console.show();
console.clear();
console.log("> Starting CSV Export");
const Papa = require(__DIR__ + "lib/papaparse.min.js");
var propertiesList = [];
var relationPropertiesList = [];
var conceptHashMap = [];
// Set up some conceptHeaders
var conceptHeaders = [
"Name",
"Documentation",
"UID",
"Type",
"Specialization"
];
var relationshipHeaders = [
"Relationship ID",
"From Name",
"From Type",
"Relationship Type",
"Specialization",
"To Name",
"To Type",
"Relationship Name",
"Relationship Documentation"
];
var typeMappings = {
"access-relationship":"Accesses",
"composition-relationship":"Comprises",
"flow-relationship":"Flows to",
"realization-relationship":"Realises",
"assignment-relationship":"Assigned to",
"serving-relationship":"Serves/Used By",
"association-relationship":"Associated to",
"aggregation-relationship":"Aggregates"
}
var current_row = 1;
var theData = new Array();
var theRelationshipData = new Array();
var theView = $(selection).filter("archimate-diagram-model").first();
debug? console.log(theView):true;
if (theView) {
// Loop through all elements and set cells to elememt info
$(theView).find().not("relationship").each(function(e) {
var theConcept = e.concept;
try {
if (e.name!="") {
if (!conceptHashMap[theConcept.id]) {
conceptHashMap[theConcept.id]=true;
var theProperties = theConcept.prop();
for (var i=0; i<theProperties.length; i++){
var found = false;
for (var j=0; j<propertiesList.length; j++) {
if (propertiesList[j]==theProperties[i]) {
found=true;
}
}
if (!found) {
propertiesList.push(theProperties[i]);
conceptHeaders.push(theProperties[i]);
}
}
var theObject = new Object;
theObject["Name"]=theConcept.name;
theObject["Documentation"]=theConcept.documentation;
theObject["UID"]=theConcept.id;
theObject["Type"]=theConcept.type;
theObject["Specialization"]=theConcept.specialization;
for (var i=0; i<propertiesList.length; i++){
if (theConcept.prop(propertiesList[i])) {
theObject[propertiesList[i]]=""+theConcept.prop(propertiesList[i]);
}
}
debug? console.log("> theObject"):true;
debug? console.log(theObject):true;
theData.push(theObject);
// Get Relationships
$(e).outRels().each(function (r) {
var theRelationshipRow = new Object;
theRelationshipRow["Relationship ID"]=r.id;
theRelationshipRow["From Name"]=r.source.name;
theRelationshipRow["From Type"]=r.source.type;
theRelationshipRow["Relationship Type"]=!typeMappings[r.type]?r.type:typeMappings[r.type];
theRelationshipRow["Specialization"]=r.specialization;
theRelationshipRow["To Name"]=r.target.name;
theRelationshipRow["To Type"]=r.target.type;
theRelationshipRow["Relationship Name"]=r.name;
theRelationshipRow["Relationship Documentation"]=r.documentation;
var theRelationshipProperties = r.prop();
for (var i=0; i<theRelationshipProperties.length; i++){
var found = false;
for (var j=0; j<relationPropertiesList.length; j++) {
if (relationPropertiesList[j]==theRelationshipProperties[i]) {
found=true;
}
}
if (!found) {
relationPropertiesList.push(theRelationshipProperties[i]);
relationshipHeaders.push(theRelationshipProperties[i]);
}
}
for (var i=0; i<relationPropertiesList.length; i++){
if (r.prop(relationPropertiesList[i])) {
theRelationshipRow[relationPropertiesList[i]]=""+r.prop(relationPropertiesList[i]);
}
}
debug? console.log("> theRelationshipRow"):true;
debug? console.log(theRelationshipRow):true;
theRelationshipData.push(theRelationshipRow);
});
current_row++;
}
else {
console.log("Duplicate Concept: ",theConcept.name);
}
}
}
catch (error) {
console.log("> Ignoring: "+e);
}
});
// Open a dialog to let the user choose where to save the generated file
var defaultFileName = model.name ? model.name + "-" + theView.name + ".csv" : "Exported Model.csv"; // Default file name
var exportFile = window.promptSaveFile({ title: "Export to CSV", filterExtensions: [ "*.csv" ], fileName: defaultFileName } );
debug? console.log("> conceptHeaders"+conceptHeaders):true;
debug? console.log("> TheData"+theData.length):true;
debug? console.log(theData):true;
debug? console.log(theRelationshipData):true;
var theCSV = Papa.unparse({fields:conceptHeaders, data:theData});
var theRelationshipsCSV = Papa.unparse({fields:relationshipHeaders, data:theRelationshipData});
if(exportFile != null) {
debug? console.log("> TheCSV"):true;
debug? console.log(theCSV):true;
$.fs.writeFile(exportFile, "\ufeff"+theCSV);
$.fs.writeFile(exportFile.substring(0,exportFile.length-4) +"-relationship.csv", "\ufeff"+theRelationshipsCSV);
console.log("> Export done");
}
else {
console.log("> Export cancelled");
}
}
else {
console.log("> Please Select a View");
}
@imbacracy
Copy link

It's Very helpful!
Could I ask a question about "$.fs.writeFile", I don't know how it works, which lib it is from.
I want to use "$.fs.readFile" and "$.fs.mkdir", But error.

@smileham
Copy link
Author

@isalew
Copy link

isalew commented Oct 13, 2023

@smileham I created a fork to add property support for relationships. Feel free to merge in, it's not a complex change: https://gist.github.com/isalew/67751369374e7ff8838659b323938a60

@smileham
Copy link
Author

Hey @isalew 'cor merging Gists is a pain, but thanks for the new feature, looks great! Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment