Flexsheet: Two Worksheet Tabs With Cells Sharing Data

Posted by: curiosichi on 22 March 2018, 2:12 pm EST

    • Post Options:
    • Link

    Posted 22 March 2018, 2:12 pm EST

    I have an Angular 2 flexsheet use case where I need formulas and values to be shared across several tabs on a single workbook.


             Workbook Tab 1           |            Workbook Tab 2
                                                      |
                Col A | Col B                |                Col C | Col D
    

    Row 1 5 6 | 5 9

    |

    If I change Tab 1’s Col A from 5 → 7, I want Col C on Tab 2 to change from 5 → 7. That is easy enough by setting Col C to a function (=‘Worksheet Tab 1’ !A1).

    What I want, however, is to be able to open Tab 2, change the value of Col C on Tab 2 to 19, and then it would automatically update Tab 1’s Col A to 19. If the underlying value of one of these cells is a function, I lose the ability to have these (and maybe even more cells on other sheets) edit and update each other.

    Is there a way to accomplish this use case that can be stored in the cell data so that when persisting this workbook as JSON its relationship is not lost?

    To be clear: I have a databound flexsheet where the data source is persisted through JSON (to a DB) and a hard coded cell relationship manager on the client side is not ideal solution to this problem.

  • Posted 23 March 2018, 11:39 am EST

    Hi,

    If I understand correctly then you need to just set value of a cell in a workbook when value of another cell in another workbook changes, then handle the cellEditEnded event to sync the chances to the other Sheet.

    Refer to following example in which a cell value in sheet 2 changes according to changes made to cells in sheet 1 and vice versa.

    https://stackblitz.com/edit/angular-chzgbw

    In case this does not meet your requirements, then please feel free to elaborate .

  • Posted 23 March 2018, 9:39 pm EST

    That example is definitely getting on the right track. Let me see if I can come up with something a bit closer to what I want, and then you can suggest the better way to do it using Flexsheet.

    
    
    class CustomCell {
        constructor(public Sheet: number, public Row: number, public Col: number) { }
    }
    
    . . .
    
    flexSheetInit(flexSheet: wjcGridSheet.FlexSheet) {
     //stuff
    
            for (let i = 0; i < Object.keys(dataFromServer).length; i++) {
    
                // dynamically creating bound sheets for the flexsheet control (using JSON)
                this.ServerWorkbook.addBoundSheet(dataFromServer[i].SheetName, dataFromServer[i].IndividualTabdata);
            }
    
    // object for storing all out desired Cells to Mirror (Is there a better way to reference Cells that I could pull from my dataFromServer?)
                            const CellsToMirror = [];
                            CellsToMirror.push(new CustomCell(1,1,1));
                            CellsToMirror.push(new CustomCell(2,2,2));
                            CellsToMirror.push(new CustomCell(2,2,3));
    
                            // pass our array of 3 cells we want to mirror each other
                            this.addMirroredCells(CellsToMirror);
    
    . . .
    
    
        addMirroredCells(customCellArray : CustomCell []) {
    
            // we itterate over all the cells we want to mirror data to
            for (let i = 0; i < customCellArray.length; i++) {
    
                // add an event handler for each cell
                this.ServerWorkbook.cellEditEnded.addHandler((refFlexGrid, e) => {
    
                    // grab the value of this edited cell
                    const data = refFlexGrid.sheets[customCellArray[i].Sheet].grid.getCellData(customCellArray[i].Row,customCellArray[i].Col);
    
                    // This itterates over the whole list of cells, and as long as it isn't the current cell, it copies its value to the cell.
                    for (let j = 0; j < customCellArray.length; j++)
    
                        if (i !== j) {
                            refFlexGrid.sheets[customCellArray[j].Sheet].grid.setCellData(customCellArray[j].Row, customCellArray[j].Col, data, false, false);
                        }
                    
                  });
            }
    
                
        }
    
    
    

    Ok so that doesn’t quite work, but should show you my thinking. The addHandler I don’t fully understand, as it looks like the event is tied to the workbook/flexsheet and not to individual cells.

    I might want to add 100s of different groups of mirrored cells among dozens of different pages, and I need to somehow group them all using data from my json object from the server. A flexsheet binds to simple string data using addBoundSheet(), so I’d like to pull data from there to somehow get them all mirrored, on a worksheet that could add and remove rows potentially on the client before saving back. Another option is adding another object to my server data that has a list of all the cells that need to merge to each other, but getting to a solution is hard without understanding deeply how the cellEditEnded.addHandler works.

    The way I have it now doesn’t really bind on the event (e) since I don’t want every cell mirroring each other, just the ones I define.

    With this extra info, is my question more clear?

  • Posted 26 March 2018, 10:15 am EST

    Hi,

    Thank you for the details on your requirement. We are working on it. We shall update you soon.

  • Posted 27 March 2018, 3:49 am EST

    Hi,

    As we understand you want to sync data between two cells of different workbooks. But due to the circular dependency we cannot use =WorksheetTab!cell formula directly.

    What we can handle the cellEditEnded event(fired after a cell edit finishes) using the addHandler() method

    Here’s what we need to do

    1. Prepare a list of cells to mirror

    2. Inside cellEditEnded event handler:-

    Check if the current edited cell is in list for mirrorCells,.If yes, then update all other workbook cell to reflect changes as required.

    Also if the edited value is a formula then change the cell references to cross worksheet cell references and update the value in other worksheets with modified value

    Here is a working example for reference:- https://stackblitz.com/edit/angular-axt4f9

    **You may also want to handle deletedRow event if you would like the user to delete the row and remove the corresponding cell entries(if present) from the mirror cells list.

  • Posted 27 March 2018, 11:26 am EST

    Thank you for this example.

    I will review this with my team, try an integration, and get back to you if I have any issues.

    It looks great right now, though certainly more complex than I was hoping for; persisting these mirrors with my json data set looks like it will require some more thought on our “complete” worksheet data set.

  • Posted 27 March 2018, 7:45 pm EST

    I do have a question about this “flexSheet.cellEditEnded.addHandler”

    That gets called on every single cell edit. If we have a few 1000 cells that are mirrored/functioned are we going to get performance impacts? Granted a single worksheet might only have a few dozen visible changes, we do still need to update the data set for all the workbsheets and I am concerned changing/editing a cell might put a perceivable delay in visible worksheet updating.

    Any thoughts?

    Also, what is the best way to remove all event listeners for these mirrored cells. If I want to load another dataset, this.ServerWorkbook.removeEventListener() makes the grid unresponsive.

    this.ServerWorkbook.clear();

    this.ServerWorkbook.sheets.removeAt(0);

    this.ServerWorkbook.removeEventListener();

    Those three lines is what I was using to “reset” a flexsheet grid, but realistically I just want to remove all the cellEditEnded events, right?

    this.cellsToMirror = ; would just empty out the array so that works I suppose, but that isn’t removing the event listener.

    also:

    error TS2339: Property ‘row’ does not exist on type ‘EventArgs’.

    error TS2339: Property ‘col’ does not exist on type ‘EventArgs’.

    error TS2339: Property ‘row’ does not exist on type ‘EventArgs’.

    error TS2339: Property ‘col’ does not exist on type ‘EventArgs’.

  • Posted 28 March 2018, 11:14 am EST

    Hi,

    A few thousand cells shouldn’t affect performance, but after a certain number of cells you may notice some performance issues.

    At this time this solution seems to fit your use case & I can’t think of an alternate solution at this time.

    For removing event handlers you can use removeHandler()/removeAllHandlers().

    Refer to the updated example here:-https://stackblitz.com/edit/angular-axt4f9

    Also for more info about wijmo’s base Event class, you can refer to following document:-

    http://demos.wijmo.com/5/Angular/WijmoHelp/WijmoHelp/topic/wijmo.Event.Class.htm

    Could you please elaborate the use case scenario for replicating the error or even better if you could share a sample replicating the problem.

  • Posted 28 March 2018, 11:45 am EST

    To reproduce the error, I just copied the exact code from your example and got the errors.

    The newest version of wijmo available for download from https://www.grapecity.com/en/download/wijmo-enterprise is “Wijmo 5.20173.409 Eval”, but the one you have in your demo is referencing “Wijmo Evaluation Version (5.20181.436)”

    Perhaps there is a difference there? Where can I download a copy of the newest version to demo?

    Thanks for the other advice; hopefully this grid works for us and our use case; it is looking very promising and the help has been wonderful!

  • Posted 28 March 2018, 12:33 pm EST

    The Build in the sample uses pre-release build. I would suggest you to use the last stable release version i.e Wijmo 5.20173.409.

    I think there could be an issue with your application which may be resulting in those error messages. I will need a sample to investigate this as I can’t reproduce this at my end

  • Posted 28 March 2018, 2:56 pm EST

    adding the “: any” solved the compiler issue present in both webstorm and visual code.

    cellEditEnded.addHandler((s, e : any) => {

  • Posted 29 March 2018, 8:35 am EST

    That’s great to know that you we’re able to resolve this.

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels