_initAsync(data, opts) {
        opts = opts || {};

        this._maxSheetId = 0;
        this._sheets = [];

        return externals.Promise.resolve()
            .then(() => {
                // Make sure the input is a Buffer
                return this._convertInputToBufferAsync(data, opts.base64)
                    .then(buffer => {
                        data = buffer;
                    });
            })
            .then(() => {
                if (!opts.password) return;
                return encryptor.decryptAsync(data, opts.password)
                    .then(decrypted => {
                        data = decrypted;
                    });
            })
            .then(() => JSZip.loadAsync(data))
            .then(zip => {
                this._zip = zip;
                return this._parseNodesAsync([
                    "[Content_Types].xml",
                    "docProps/app.xml",
                    "docProps/core.xml",
                    "xl/_rels/workbook.xml.rels",
                    "xl/sharedStrings.xml",
                    "xl/styles.xml",
                    "xl/workbook.xml"
                ]);
            })
            .then(nodes => {
                const contentTypesNode = nodes[0];
                const appPropertiesNode = nodes[1];
                const corePropertiesNode = nodes[2];
                const relationshipsNode = nodes[3];
                const sharedStringsNode = nodes[4];
                const styleSheetNode = nodes[5];
                const workbookNode = nodes[6];

                // Load the various components.
                this._contentTypes = new ContentTypes(contentTypesNode);
                this._appProperties = new AppProperties(appPropertiesNode);
                this._coreProperties = new CoreProperties(corePropertiesNode);
                this._relationships = new Relationships(relationshipsNode);
                this._sharedStrings = new SharedStrings(sharedStringsNode);
                this._styleSheet = new StyleSheet(styleSheetNode);
                this._node = workbookNode;

                // Add the shared strings relationship if it doesn't exist.
                if (!this._relationships.findByType("sharedStrings")) {
                    this._relationships.add("sharedStrings", "sharedStrings.xml");
                }

                // Add the shared string content type if it doesn't exist.
                if (!this._contentTypes.findByPartName("/xl/sharedStrings.xml")) {
                    this._contentTypes.add("/xl/sharedStrings.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml");
                }

                // Kill the calc chain. It's not required and the workbook will corrupt unless we keep it up to date.
                this._zip.remove("xl/calcChain.xml");

                // Load each sheet.
                this._sheetsNode = xmlq.findChild(this._node, "sheets");
                return externals.Promise.all(_.map(this._sheetsNode.children, (sheetIdNode, i) => {
                    if (sheetIdNode.attributes.sheetId > this._maxSheetId) this._maxSheetId = sheetIdNode.attributes.sheetId;

                    return this._parseNodesAsync([`xl/worksheets/sheet${i + 1}.xml`, `xl/worksheets/_rels/sheet${i + 1}.xml.rels`])
                        .then(nodes => {
                            const sheetNode = nodes[0];
                            const sheetRelationshipsNode = nodes[1];

                            // Insert at position i as the promises will resolve at different times.
                            this._sheets[i] = new Sheet(this, sheetIdNode, sheetNode, sheetRelationshipsNode);
                        });
                }));
            })
            .then(() => this._parseSheetRefs())
            .then(() => this);
    }
Initialize the workbook. (This is separated from the constructor to ease testing.)
@param {string|ArrayBuffer|Uint8Array|Buffer|Blob} data - The data to load.
@param {{}} [opts] - Options
@param {boolean} [opts.base64=false] - No used unless input is a string. True if the input string is base64 encoded, false for binary.
@returns {Promise.<Workbook>} The workbook.
@private