Get individual cell formats in Excel using office.js?
Asked Answered
O

1

8

I'm just starting to look at the new office js API with regard to converting existing Excel add-ins to use this new tech.

I can easily get an array of values from an entire range by queuing a single load on the context, but there doesn't seem to be an equivalent way to get cell formatting. Unless all cells in the range are formatted identically, the value returned for the range is 'undefined'.

The solution I've come up with is to queue a load operation on each individual cell in the range. For example, this function gets the fill color for each cell in a range:

function readFormats() {
    Excel.run(function (ctx) {
        var cells = [];

        //First get the size of the range for use in the loop below
        var myRange = ctx.workbook.getSelectedRange().load(["rowCount", "columnCount"]);

        return ctx.sync()
        .then(function () {
            //Loop though every cell and queue a load on the context for fill colour
            for (var r = 0; r < myRange.rowCount; ++r)
                for (var c = 0; c < myRange.columnCount; ++c)
                    cells.push(myRange.getCell(r, c).load("format/fill"));
        })
        .then(ctx.sync)
        .then(function () {
            //Do something useful with the fill color of cells in array here
        })
    })
    .then(function () {
        console.log("Formats done");
    })
    .catch(function (error) {
        console.log("Error: " + error);
        if (error instanceof OfficeExtension.Error) {
            console.log("Debug info: " + JSON.stringify(error.debugInfo));
        }
    });
}

This code works as expected, but is extremely slow. For example, a 10,000 cell range takes approximately 12 seconds and a 20k cell range somewhere around 45 seconds to run. When I tried it on a range containing 50k cells, my async callback was never called at all.

Is there a better and more efficient way to do this?

Octahedrite answered 26/2, 2016 at 9:21 Comment(0)
J
4

There currently isn't a better way, but we do have it on our backlog to expose cell-level properties. I will be sure to share your question with the team.

Jawbone answered 26/2, 2016 at 17:29 Comment(3)
Thanks for the answer, although it's not the one I was hoping for. I guess I'll have to wait for cell level properties. Could you also ask the team why the above function does not run with linear complexity? Fyi, I did get it to run with 50k cells and it took somewhere near 5 minutes.Octahedrite
@JamieDuncan, re. time complexity, it might be one of two things. It could be that using Excel.run is getting in your way here -- try just creating a request context using new Excel.RequestContext, and seeing if that works. But fundamentally, it might well be the fact that you're creating a whole bunch of Range objects, all of which need to be internally tracked to ensure that the Range moves when stuff around it shifts (much like a named range). And it might just be that at 50k that becomes quite a task.Jawbone
@MichealZlatkovsky Thanks for the advice - getting rid of Excel.Run reduced run time significantly (to approx 40% in the simple examples above). This begs the question of what Excel.Run is doing for me for the huge overhead, but that's a question for another post. I take your point re 50k range objects - it's not really a practical solution, merely a work around until cell level properties are available (and I could be tracking hundreds of large ranges in each workbook). It's a shame, as data bindings in office.js are performing very well for me with this size/number of ranges.Octahedrite

© 2022 - 2024 — McMap. All rights reserved.