exceljs/exceljs

Sheet Order

crash83k opened this issue · 5 comments

I'm not sure why, but if I open a book with multiple sheets, and then immediately save it to a new file, the sheets are out of order.

Is there a way to ensure that the sheets are saved in the same order?

BTW, this is a fantastic library. Seems very complete (especially for our needs).

Also, another note:

Looking at the workbook model, I see an object key called sheets that has the worksheets in their proper order. I'm digging a little deeper to see if this is the only place where the order of the sheets is set, and if that order is being used when writing the book to a new file.

edit For clarity, I'm talking about the model.sheets array created at Line: 139 in lib/xlsx/xlsx.js

Update:

I haven't been able to get the sheets to read in the correct order, but I've been able to get them to write in the correct order. I'm sure this isn't the best way to go about this, but maybe it will give you some clue as to what would be the best way to do this.

What I'm doing is saving the sheet order from the default case in the createInputStream method as self.orderedSheets like so:

          promise = self.parseWorksheet(entry)
              .then(function (worksheet) {
                worksheet.sheetNo = sheetNo;
                model.worksheetHash[entry.path] = worksheet;
                model.worksheets.push(worksheet);
              })
              .then(()=>{
                if(model.worksheets.length === model.sheets.length) {
                  self.orderedSheets = model.sheets;
                }
              });

Then in the write method, I'm popping off the sheets from the model.worksheets array. (Sorting didn't seem to work.) And then I push them back to the model.worksheets array in the order they appear in the self.orderedSheets array. I also do a quick check to see if there's any more sheets in the tmpSheets object just in case they were programmatically added, and push them if they were.

Like so:

    var tmpSheets = {};
    while (model.worksheets.length > 0) {
      let sheet = model.worksheets.pop();
      tmpSheets[ sheet.name ] = sheet;
    }

    this.orderedSheets.forEach(orderedSheet => {
      model.worksheets.push(tmpSheets[ orderedSheet.name ]);
      delete tmpSheets[ orderedSheet.name ]
    });

    const keys = Object.keys(tmpSheets);
    if (keys.length > 0) {
      keys.forEach(key => {
        model.worksheets.push(tmpSheets[ key ]);
      });
    }

However, I haven't tested the additional sheets part. I won't be adding sheets in my usage. Only modifying sheets as they go out.

I can create a PR for this. Just let me know...
https://github.com/crash83k/exceljs

Same issue here. eachSheet was expected to trigger callback in the sheet order, but it was not.

Thanks to Robbi for his fix. I'll close this now.