How to obtain the data returned by callCommand?

Document Server version:7.1.1
Hello, I’m using vue2 + onlyoffice to make plugins.
I would like to know how to return data in callCommand

  1. I tried callCommand(func, isClose, isCalc, callback) in the callback returns undefined,
  2. Also try to add the parameter to the callback function is undefined.
  3. I also tried to define an Asc.scope.cellKeyNameData = 1 in callCommand, change the value to 2 in the callCommand function and return Asc.scope.cellKeyNameData to callback, the result is read Asc.scope.cellKeyNameData = 1
  4. I also tried to use localStorage.setItem() in the callCommand and read it on the web page, but the storage address of localStorage.setItem() is the address of onlyofficeDocument, not the address of the page, so the data cannot be interconnected.
  5. I have also used Vuex but it doesn’t, for the same reason as 4
 window.Asc.plugin.callCommand(
        function () {
           
            let cellKeyNameData = [];

            let oDocument = Api.GetDocument();

            let oTable = oDocument.GetAllTablesOnPage(0)[0];
            console.log("oTable", oTable);

            let oTableRow = oTable.GetRow(0);
            console.log("oTableRows", oTableRow);

            let oTableCell = oTable.GetCell(1, 4).GetContent().GetRange().GetText();
            console.log("oTableCell", oTableCell);

            let oTableCellIamgeTag = oTable.GetCell(0, 6).GetContent().GetElement(0).GetTag();

            for (let i = 0; i < oTable.GetRowsCount(); i++) {

                for (let j = 0; j < oTable.GetRow(i).GetCellsCount(); j++) {
                    let curRow = oTable.GetRow(i)

                    let curCell = curRow.GetCell(j)
                    let curCellRange = curCell.GetContent().GetRange();
                    let curCellRangeText = curCellRange.GetText();
                    let curCellContent = curCell.GetContent();
                   
                    if (curCellRangeText != "" && curCellRangeText.trim() !== "") {
                        cellKeyNameData.push(curCellRangeText);
                    }
                

                }

            }
           
        })

Hello @yingyu

First of all, please note that you are using outdated version of Document Server. I’d recommend updating to recently released version 8.2.

In provided example you didn’t specify the callback as per description of the callCommand method. The last parameter callback is used to define function that is return after execution. For example:

window.Asc.plugin.callCommand(function () {
   <your code>       
}), false, false, (console.log("callback"));

In this case parameters isClose and isCalc are set to false, then callback is returned.

Thanks, I forgot to mention my needs.
I want callCommand to return cellKeyNameData
I have tried your method and the result is cellKeyNameData is not defined

I’m not sure if I understand your goal. In your example cellKeyNameData is an empty array. What are you trying to achieve? Do you want to get text values from each non-empty cell in the table?

I defined a function export function getTableData() in a JS file and used window in this function Asc.plugin.callCommand
Then in the window The Asc.plugin.callCommand defines let cellKeyNameData = ;
Then obtained the text content of all non empty cells and pushed it to cellKeyNameData
cellKeyNameData.push(curCellRangeText);
The results are as follows:

let cellKeyNameData = [Name ‘,’ Gender ‘,’ Date of Birth ‘,’ Current Position ‘,’ Rank (Position) Time ‘,’ Resume Information ‘,’ Family Members’, ‘Title’, ‘Name’, ‘Age’, ‘Work Unit’, ‘Barcode’]

I hope to return the data of cellKeyNameData to an external function

If you still don’t understand, please take a look at the example. I hope to return the change of Asc.scope.data in Call Command to the outside. That is to say, I hope to change Asc.scope.data to 2

export function getData(){
    
    let data = 1
    Asc.scope.data = data
    let testEvent = window.Asc.plugin.callCommand(function () {
        
        console.log("Asc.scope.data",Asc.scope.data);
        // Asc.scope.data = 1
        
        Asc.scope.data = 2;
        console.log("Asc.scope.data",Asc.scope.data);
        // Asc.scope.data = 2
        
        return Asc.scope.data
    },false,false,function(){
        console.log("Callback Asc.scope.data",Asc.scope.data);
        // Asc.scope.data = 1
      
        
    })
    
    console.log("Asc.scope.data",Asc.scope.data);
    // Asc.scope.data = 1

    return Asc.scope.data
    // return 1
    
}

I see. Callback for callCommand supports all JS types, so, for instance, you can transfer result like:

window.Asc.plugin.callCommand(
        function() {
            let cellKeyNameData = [];
            let oDocument = Api.GetDocument();
            let oTable = oDocument.GetAllTablesOnPage(0)[0];
            let oTableRow = oTable.GetRow(0);
            let oTableCell = oTable.GetCell(1, 4).GetContent().GetRange().GetText();
            // let oTableCellIamgeTag = oTable.GetCell(0, 6).GetContent().GetElement(0).GetTag();
            // This one returns an error,  you should revise it. 
            for (let i = 0; i < oTable.GetRowsCount(); i++) {
                for (let j = 0; j < oTable.GetRow(i).GetCellsCount(); j++) {
                    let curRow = oTable.GetRow(i)
                    let curCell = curRow.GetCell(j)
                    let curCellRange = curCell.GetContent().GetRange();
                    let curCellRangeText = curCellRange.GetText();
                    let curCellContent = curCell.GetContent();
                    if (curCellRangeText != "" && curCellRangeText.trim() !== "") {
                        cellKeyNameData.push(curCellRangeText);
                    }
                }
            }
            return { data: cellKeyNameData };
        },
        function(result) {
            console.log('Received result:', result.data);
        })

That way your filled array is transferred into second function. It is up to you how to manage the data further.

After trying to copy your code, I found that console.log ('Received result: ', result. data) was not executed. The console also did not report any errors

I wrote an example according to the code you provided.
The code in the callback has not been executed

export function getData(){
    
    let data = 1;
    Asc.scope.data = data;
    window.Asc.plugin.callCommand(function () {
        
        console.log("Asc.scope.data",Asc.scope.data);
        // Asc.scope.data = 1
        
        Asc.scope.data = 2;
        console.log("Asc.scope.data",Asc.scope.data);
        // Asc.scope.data = 2
        
        return { data:Asc.scope.data }
    },function(res){
        console.log("start callback");
        // Not executed, console not displaying
        
        console.log("Callback Asc.scope.data",res.data);
        // Not executed, console not displaying

        Asc.scope.data = res.data;
        console.log(Asc.scope.data);
        // Not executed, console not displaying

        // data = res.data;
        // window.Asc.plugin.callCommand is not a function
        
    })
    
    console.log(Asc.scope.data);
    // Asc.scope.data = 1

}

I think it might be easier to add onCommandCallback block for the returned callback if you want to perform any actions with it.

For example, with previously shared code it can used like:

    window.Asc.plugin.init = function() {
        window.Asc.plugin.callCommand(function() {
            let cellKeyNameData = [];
            let oDocument = Api.GetDocument();
            let oTable = oDocument.GetAllTablesOnPage(0)[0];
            let oTableRow = oTable.GetRow(0);
            let oTableCell = oTable.GetCell(1, 4).GetContent().GetRange().GetText();
            for (let i = 0; i < oTable.GetRowsCount(); i++) {
                for (let j = 0; j < oTable.GetRow(i).GetCellsCount(); j++) {
                    let curRow = oTable.GetRow(i)
                    let curCell = curRow.GetCell(j)
                    let curCellRange = curCell.GetContent().GetRange();
                    let curCellRangeText = curCellRange.GetText();
                    let curCellContent = curCell.GetContent();
                    if (curCellRangeText != "" && curCellRangeText.trim() !== "") {
                        cellKeyNameData.push(curCellRangeText);
                    }
                }
            }
            return { data: cellKeyNameData };
        });
        window.Asc.plugin.onCommandCallback = function(result) {
            console.log('Received result:', result.data);
        };
    };

I tried both callback and onCommandCallback , Not getting the console in both ways

Hello @Jagan

It may depend on the logic of code that you are executing. Can you share an example?

Thanks for the response.

I am using 8.0.1. We need to get current visible page of the office viewer document and send it to the parent window.

window.Asc.plugin.callCommand(
                function () {
                    var currentPage = Asc.scope.editorType === 'cell'
                        ? Api.GetActiveSheet().GetIndex()
                        : Api.GetCurrentVisiblePage();
console.log('Current Page",  currentPage );  // I am getting currentPage value here

                    return { data: currentPage };
                                        
                },
                function(result) {
                    console.log('Retrieved Result', result);  // Not executed
                    var currentPage = result.data;  
                    console.log('Retrieved Current page'); // Not executed
                    updateTimeSpentOnPage(currentPage? currentPage : 0, 1);
                }
            );

            window.Asc.plugin.onCommandCallback = function(result) {
                console.log('Received onCommandCallback result:', result.data);   //  Uncaught TypeError: Cannot read properties of undefined (reading 'data')
            };

Thanks. In my tests on this exact code version 8.2 returns result in onCommandCallback method, please see:
Screenshot 2024-10-28 at 15.26.02

None of code has been modified besides the typo with double bracket in this line:

console.log("Current Page",  currentPage );  

Please update your editor and check the situation once again.

Thanks @Constantine , Could you please let us know why it is not working in 8.0.1. Or is there any other way we can pass the data out of callCommand.

Probably there was a bug that is fixed now. I can’t help you with older version so recommendation is to update and check the situation again.

As for me, it takes a long time to understand the way to get data from document to plugin.
So, there are 4 arguments of callCommand method: func, isClosed, isCalc and Callback.

  1. func - the function, executed at the document context. You should send data to this function by using the Asc.scope object. And if you want to get data from this function, you have to RETURN data! This is important! And you may return only the Number, String or Array. If You want to return the Object, you should use JSON.stringify(…)!
  2. Callback - the function, executing after returning process control from document back to plugin. And this callback can get argument, tht is your data, returned from document!
    Example (for worksheet):
function getData () {
    let data = 1;
    Asc.scope.data = data;

    window.Asc.plugin.callCommand( function () {
        const sh = Api.GetActivesheet();
        const rng = sh.GetRange("A2");
        rng.SetValue(Asc.scope.data);
	
        const resRng = sh.GetRange("B4");
        const result = resRng.GetValue();
	
        //return your data!!
        return JSON.stringify({data: result});
    },
    
    //isClose:
    false,
    
    //isCalc
    true,

    //Callback function:
    function (res) {
        //argument res is returned data!
        console.log(`result from worksheet: ${JSON.parse(res)}`);
    });
}
1 Like

Hi @Constantine

We have upgraded to “8.2.1.38”. Still we are getting the same error. We need to get the current page and pass the value outside callCommand.

window.Asc.plugin.callCommand(
                function () {
                    var currentPage = Asc.scope.editorType === 'cell'
                        ? Api.GetActiveSheet().GetIndex()
                        : Api.GetCurrentVisiblePage();

                        console.log('current page Audit page',currentPage); // getting currentPage value

                       return currentPage;
                                        
                },
                false,
                true,
                function (res) {
                                     console.log('result from callback: ',res);    // getting undefined
                     }
            );

 window.Asc.plugin.onCommandCallback = function(result) {
            console.log('Received onCommandCallback audit result:', result);  //not executed
        };

Is there any other way we can get current page outside call command

Hello @Jagan

I am not quite following the design. Are you trying to get a page in the spreadsheet editor? In general, you code returns Api.GetCurrentVisiblePage is not a function - can you share a link to this method for the reference? Also, used GetIndex method returns index of the sheet in the file.

Hello @Constantine ,

Using the above code in the variable “currentPage” I am able to get the current sheet number for Excel and current viewing page for other documents and presentations.

The problem I am facing is, I am unable to use the “currentPage” value outside callCommand function.

Regards,
Jagan

First of all, you can use only one option to return a callback. I recommend using onCommandCallback method. For example, this returns the value:

    window.Asc.plugin.callCommand(
      function () {
        var currentPage = Asc.scope.editorType === 'cell'
          ? Api.GetActiveSheet().GetIndex()
          : Api.GetCurrentVisiblePage();
        console.log('current page Audit page', currentPage); // getting currentPage value
        return currentPage;
      });
    window.Asc.plugin.onCommandCallback = function (currentPage) {
      console.log('Received onCommandCallback audit result:', currentPage);  // returns the same value
    };

You can further execute your code in onCommandCallback.

Second, as I mentioned, GetIndex returns index of the sheet, instead of something like a page number. Not sure if there is a workaround to this as canvas in the spreadsheet editor is basically one.