Importing from or exporting to Excel are important topics in this board and there are a number of scripts out there how to accomplish that. This article here is more about the question "how to make a script better", how to add the remaining 10% of convenience such that the end user accepts it more.
A repeated question especially when importing huge Excel sheets is progress reporting, some imports, especially those who create model elements may take a few minutes so we should think about the user who is waiting in front of the tool now knowing when this import will end, in a second? A few seonds? Minutes? So here are some basic recipes how to improve a script. Note: There are other articles about progress reporting in general and they also mention a few limitations that crep in recently. Also remember that the script is executed in a transaction, so at the end, all changes are comotted to the project which may take a few seconds as well and at that time the script has finished already!
First script: basic Excel importer which does everything (iterating over workbook, sheet and rows:
/** $EXPERIMENTAL$
*
* This script is meant to illustrate how to write better Excel scripts.
*/
load(".lib/excel.js");
var file = new java.io.File(__filedir + "/.data/sample.xlsx");
var document = ExcelDocument.open(file, true);
var wb = document.workbook;
var sheets = wb.worksheets;
// (1) Show nice progress when importing huge excel sheets
var ws = sheets[1];
console.log("Sheet {0} with dim {1} and {2} rows", ws.name, ws.dimension, ws.rows.length);
var rows = ws.rows;
progressMonitor.beginTask("Loading Excel rows...", rows.length);
for (var i=0; i<rows.length; i++) {
var row = rows[i];
console.log("Handle row {0}...", row.rowIndex);
java.lang.Thread.sleep(10); // wait 100ms to simulate work
progressMonitor.subTask("Loaded row " + i + " of " + rows.length);
// this should normally move the progress bar but since 2025 R2 there is an issue, see https://medini.freshdesk.com/support/discussions/topics/1000121455
progressMonitor.worked(1);
}
progressMonitor.done();
document.close();
progressMonitor.subTask("Committing changes (this may take a while)...");
java.lang.Thread.sleep(2000); // wait 2s to simulate transaction commit
Second scrip: does the same but this time for "callback" based workflow (import):
/** $EXPERIMENTAL$
*
* This script is meant to illustrate how to write better Excel scripts.
*/
load(".lib/excel.js");
var file = new java.io.File(__filedir + "/.data/sample.xlsx");
var callback = {
numrows : 0,
getFile() {
return file;
},
getSheet : function(wb) {
return wb.worksheets[1];
},
beforeHandle : function(sheet) {
this.numrows = sheet.rows.length;
progressMonitor.beginTask("Loading Excel rows...", this.numrows);
},
afterHandle : function(sheet) {
progressMonitor.done();
},
handleRow : function(index, row) {
console.log("Handle row {0}...", index);
java.lang.Thread.sleep(10); // wait 100ms to simulate work
progressMonitor.subTask("Loaded row " + index + " of " + this.numrows);
// this should normally move the progress bar but since 2025 R2 there is an issue, see https://medini.freshdesk.com/support/discussions/topics/1000121455
progressMonitor.worked(1);
}
};
var importer = new ExcelImporter(callback);
if (!importer.run()) {
console.log("Import was canceled");
undefined;
} else {
"Import completed";
}
Hope this helps to write better scripts!
Jan