Skip to main content Skip to footer

Potential issues when adding worksheets across workbooks: Understanding storage differences between SpreadJS and Excel

In this article we will talk about a common scenario: You want to generate a single PDF by combining multiple .sjs files where each file contains just one worksheet. A typical approach might be to load each .sjs file into a SpreadJS instance, then add each sheet to another Spread instance that’s used to export the final PDF. 

At first glance, this might seem like a reasonable solution, but it actually introduces a serious issue. 

async function prepareReportData(blob) {
    try {
        let exportWorkbook = new GC.Spread.Sheets.Workbook(); // Create a new workbook for exporting
        exportWorkbook.removeSheet(0);

        let importWorkbook = new GC.Spread.Sheets.Workbook(); // Temporary workbook for opening the file

        await new Promise((resolve, reject) => {
            importWorkbook.open(blob, () => { // Open the file in the temporary workbook
                var activeSheet = importWorkbook.getActiveSheet();
                
                exportWorkbook.addSheet(0, activeSheet); // Adding the active sheet directly 

                resolve();
            }, (error) => {
                console.error(error);
                reject(error);
            });
        });

        return exportWorkbook; // Return the prepared workbook for PDF export
    } catch (err) {
        console.error("Failed to generate export data:", err);
        throw err;
    }
}

Here’s the problem: Adding a worksheet instance directly from one workbook to another is incorrect usage in SpreadJS. This causes internal reference confusion between the two Spread instances, leading to unexpected behavior and errors. It's not a matter of DOM or UI, it's about how the underlying data and references are managed. 

To make this clearer, let’s consider an example using two files: 

  • One created with SpreadJS Designer. 

  • One created with Excel, then imported into the Designer and saved as .sjs. 

If you import both into your application and try to combine their sheets, you might notice that the second file loses its styling such as alignment, colors, etc. That’s not a bug but it’s the result of how styles are stored differently in Excel versus SpreadJS. 

Here’s what’s happening under the hood: 

  • In SpreadJS, styles are stored at the worksheet level unless you explicitly create spread-level named styles and apply them to cells. So, when you move a sheet from one workbook to another, all the style information goes with it, and things work as expected. 

  • In Excel, styles are stored at the workbook level, and each worksheet just references those styles. When you import an Excel file into SpreadJS and save it as .sjs, this reference structure is preserved. So, if you then take that sheet and try to move it into another Spread instance, the cell values may appear but the styles won’t, because they’re still tied to the original workbook. 

So what’s the right approach? 

If you want to combine sheets into a single workbook, don’t reuse worksheet instances from one SpreadJS instance in another. Instead, make sure each sheet you’re combining is completely independent, with its own local styles and not styles that are shared or referenced from a different workbook. 

Kristina Ismail

Technical Engagement Engineer