Passing data from the callCommand "sandbox" to the main plugin code

(I use automatic translation from Russian, the text may look clumsy, sorry)

onlyoffice desktop edition, 8.2.2.

how to pass a message from window.Asc.plugin.callCommand function to the main plugin code ?

I have this code:

(function(window, undefined) {

window.Asc.plugin.init = function() {
    document.getElementById("inputIDstatus").value = "step 1";
    document.getElementById("buttonIDtest").onclick = function() {
        document.getElementById("inputIDstatus").value = "step 2";
        window.Asc.plugin.callCommand(
            function () {
                for (let i = 0; i < 100; i++)
                    {
// here is a long action. we need to pass the "i" value to the plugin to show in the "input" field.
                    }
                return "done";
            }, false, false, function (res1) { document.getElementById("inputIDstatus").value = res1 }
        );
    };
};

})(window, undefined);

how to change it so that in the process of the function inside callCommand - the result goes to the “input” field not only after the function is completed, but also in the process (for example, let only the value of the variable “i” get there), how to implement it ?

This is to pass “progress” when running a long loop (processing a document that can take a few minutes) - I want to do a “feedback” so that the plugin window shows the percentage of progress and the user doesn’t think it’s stuck.

Hello @iteh

Return data from callCommand is possible in several ways, all of them are mentioned here:

Please take a look at this topic.

I might have expressed myself wrong (or misunderstood your answer) - I need to get intermediate data from callCommand, that is, to get intermediate results from callCommand in the main (outside of callCommand) plugin code.

As I understand it, callCommand runs synchronously and until the function launched through callCommand finishes, I won’t see the result.

How can I get intermediate values (in my example - like the value of the variable “i”) while the function inside callCommand is running?

Is there some kind of “postMessage” function to call from inside callCommand (passing the value of “i” for my example), and catch it from the main plugin code without waiting for the block inside callCommand to finish?

My function (inside callCommand) runs for a few minutes and I want to get not just the final value, but also see all the intermediate “i” in real time (i.e., see which iteration of the loop is currently running while callCommand hasn’t finished yet).

Is that possible?

I believe the easiest solution is to put callCommand into a for cycle, it will return values for each step if your condition. Of course it depends on what kind of operation you are performing in callCommand, but it should work.

I am checking the rows of a .docx file in a loop (approximately 2-3 thousand rows with 15 columns each), and depending on the content of the cells, either some cells of each row are merged or the formatting (font, indents, etc.) is changed.

I checked - the difference between a single call to callCommand (inside the function - 3000 iterations of the loop in which a simple action is done, only measure the total time of all iterations) and 100 times to call callCommand (each call has 30 iterations of the loop) - the difference is 10 times (in the first case it took 1ms, in the second - 10ms), but in absolute time - acceptable, I can use multiple callCommand calls, As you said above. Thanks for this idea :slight_smile:

And one more question: could you please advise if there is any way (API function of the text editor) to display information from a loop running inside callCommand, but already in the editor’s interface?

Is there any API function to display information in the text editor’s interface?

For example, in VBA in MS Office (WinWord), we can use the following code:

Application.DisplayStatusBar = True
Application.StatusBar = "Processing " & i & ", completed Percentage: " & pct_complete

and display any information during the macro execution.

Are there any similar methods (to display the text string in the editor interface while executing the function code inside callCommand) in OnlyOffice desktop editors ?

maybe I’m doing something wrong (with a “multiple” callCommand call), but I’m getting weird results. the following code:

    document.getElementById("buttonIDtest2").onclick = function() {
        Asc.scope.i = 0;
        while (Asc.scope.i < 5)
        {
            Asc.scope.i++;
            console.log('[',Date.now(),'] Asc.scope.i (while) = ',Asc.scope.i);
            window.Asc.plugin.callCommand(
                function () {
                    Asc.scope.i++;
                    console.log('[',Date.now(),'] iRetCode(int) = Asc.scope.i (int) = ',Asc.scope.i);
                    return { iRetCode : Asc.scope.i };
                }, false, false);
            window.Asc.plugin.onCommandCallback = function (res1) {
                console.log('[',Date.now(),'] iRetCode(ext) = ',res1.iRetCode) 
                Asc.scope.i++
                console.log('[',Date.now(),'] Asc.scope.i (onCommandCallback) = ',Asc.scope.i);
            };
        }
    };

I was hoping it would run (and added the time in milliseconds to check) like this:

Asc.scope.i (while) =  1
iRetCode(int) = Asc.scope.i (int) =  2
iRetCode(ext) =  2
Asc.scope.i (onCommandCallback) =  3
Asc.scope.i (while) =  4
iRetCode(int) = Asc.scope.i (int) =  5
iRetCode(ext) =  5
Asc.scope.i (onCommandCallback) =  6
...

But in fact, I see this:

[ 1738663271433 ] Asc.scope.i (while) =  1
[ 1738663271434 ] Asc.scope.i (while) =  2
[ 1738663271434 ] Asc.scope.i (while) =  3
[ 1738663271434 ] Asc.scope.i (while) =  4
[ 1738663271434 ] Asc.scope.i (while) =  5
[ 1738663271437 ] iRetCode(int) = Asc.scope.i (int) =  2
[ 1738663271443 ] iRetCode(int) = Asc.scope.i (int) =  3
[ 1738663271449 ] iRetCode(int) = Asc.scope.i (int) =  4
[ 1738663271453 ] iRetCode(int) = Asc.scope.i (int) =  5
[ 1738663271456 ] iRetCode(int) = Asc.scope.i (int) =  6
[ 1738663271459 ] iRetCode(ext) =  2
[ 1738663271459 ] Asc.scope.i (onCommandCallback) =  6
[ 1738663271459 ] iRetCode(ext) =  3
[ 1738663271459 ] Asc.scope.i (onCommandCallback) =  7
[ 1738663271459 ] iRetCode(ext) =  4
[ 1738663271459 ] Asc.scope.i (onCommandCallback) =  8
[ 1738663271460 ] iRetCode(ext) =  5
[ 1738663271460 ] Asc.scope.i (onCommandCallback) =  9
[ 1738663271460 ] iRetCode(ext) =  6
[ 1738663271460 ] Asc.scope.i (onCommandCallback) =  10

why does this happen ? :frowning:

If the Onlyoffce engine algorithm works only like this (all the steps of the “external” loop of while are executed first, then all callCommand functions at once, then all onCommandCallback functions at once), then how do I implement such an algorithm:

  1. Use callCommand to get the number of rows from the document table
  2. if the number of rows is greater than zero, then use the while loop, where the condition is that the current row (the number of which is returned from onCommandCallback on each iteration of the while loop, and within callCommand to process 20-30 rows at a time) is less than the number of rows in the table, or that the previous callCommand was with an error (problems with row processing), and inside while there will be a callCommand , But after each call, analyze onCommandCallback to see if we need to exit while.

How to implement this if, when executing the test code (see above), we get the “wrong” order of command execution ? :frowning:

I could assume that the code works very fast, and the onCommandCallback functions work in a separate thread and because of this the callCommand functions and onCommandCallback are “mixed”, but I ran it 5 times in a row - and the order is always strictly like this (both the order in the log and the chronology by timestamps)… :frowning: