Exceljs : 'An issue has been identified with certain content in the document named "file.xlsx"(...)'

I have encountered an issue with an xlsx file generated using Exceljs. While I have been creating csv files in my project without any problems, creating an xlsx file now poses an error. The xlsx file opens clean on Ubuntu/LibreOffice Calc, but there is an error when opening it on Excel (Windows and IOS).

The file is named "export-yyyy-mm-dd.xlsx" and consists of two sheets titled "Total" and "Details". Both sheets have a "fake" title line above the column headers. The second sheet contains 13 columns of string or number data for all the users, while the first sheet aggregates this data into 6 number columns with just one line under the headers.

The missing data when opening the file with Excel seems to be the one line of data in the first sheet.

I have tried several solutions so far:

  • Converting plain numeric values from string to number format
  • Converting the percentage cell from string to number format
  • Updating the Exceljs package (from 3.9 to 4.4)
  • Removing the sheets setup on creation
  • Removing the "fake" titles from both sheets
  • Removing the first sheet
  • Removing the second sheet

I am currently out of ideas, so what could be causing this issue?

Below is a simplified version of the code used to generate the first sheet:

const file = new Workbook();

function createFirstSheetHeaders(): Partial<Column>[] {
  return [
    {
      key: "usersCount",
      width: 50,
    },
    {
      key: "ratio",
      width: 40,
    },
    {
      key: "firstCount",
      width: 40,
    },
    {
      key: "total",
      width: 40,
    },
    {
      key: "secondCount",
      width: 40,
    },
    {
      key: "saved",
      width: 50,
    },
  ];
}

function firstSheetHeadersContent(): {
  usersCount: string;
  ratio: string;
  firstCount: string;
  total: string;
  secondCount: string;
  saved: string;
} {
  return {
    usersCount: "Users count",
    ratio: "Ratio",
    firstCount: "First count",
    total: "Total",
    secondCount: "Second count",
    saved: "Saved",
  };
}

  const header = "Export from 04-03-2024 for the period from 01-01-2024 to 04-07-2024";

  const firstSheet = file.addWorksheet("Total", {
    pageSetup: { orientation: "landscape" },
  });
  firstSheet.columns = createFirstSheetHeaders();
  firstSheet.mergeCells("A1:F1");
  firstSheet.getCell("A1").value = header;
  firstSheet.addRow(firstSheetHeadersContent(t));

function formatTotalDataForRow(
  usersCountInput: number,
  ratioInput: number,
  dailyTotal: number,
  firstCount: number,
  secondCount: number
): {
  usersCount: number;
  ratio: number;
  firstCount: number;
  total: number;
  secondCount: number;
  saved: number;
} {
  const parsedTransportEmissionRatio = Number(ratioInput.toFixed(4));

  const total = dailyTotal * firstCount;
  const saved = dailyTotal * secondCount;

  return {
    usersCount: usersCountInput,
    ratio: parsedTransportEmissionRatio,
    firstCount: firstCount,
    total: total,
    secondCount: secondCount,
    saved: saved,
  };

const totalData = formatTotalDataForRow(
    usersCount,
    ratioInput,
    dailyTotal,
    firstCount,
    secondCount
  );

  firstSheet.addRow(totalData);
  firstSheet.getCell("B3").numFmt = "0.00%";
}

Edit: Including only one of the two sheets works fine, whether it's the first or the second sheet. Therefore, the issue may not be related to the way this sheet is created or its content.

Due to the nature of the data and its potential large size, I generate my file in the following manner:

  • Create the file/workbook
  • Create both sheets with their titles and column headers
  • Loop through chunked data to fill the SECOND sheet, 200 users at a time, increasing totals used for the first sheet. Write in the file buffer during this process.
  • Use the previously generated totals to fill the FIRST sheet. Write in the file buffer.
  • End the passthrough.

Here's what I do when the first sheet is filled:

  const firstSheetBuffer = await firstSheet.workbook.xlsx.writeBuffer();
  if (Buffer.isBuffer(firstSheetBuffer)) {
    passThrough.write(firstSheetBuffer);
  } else {
    const err = new Error("ExcelJs does not return a Buffer");
    passThrough.destroy(err);
    throw err;
  }
  passThrough.end();
  return file;

Answer №1

After some investigation, I discovered that the issue was related to s3, not ExcelJs. To resolve the problem, I realized that I needed to commit() each row, each sheet, and the entire document once they were completed. I also found that I had to initialize my file as a WorkbookWriter (rather than a simple Workbook) and provide it with my stream upon creation, as shown below:

  const file = new stream.xlsx.WorkbookWriter({
    stream: passThrough,
  });

Any other method I tried seemed to cause some data corruption that Excel struggled with, but LibreOffice didn't seem to have any issues with.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unlocking the power of bitwise operations in VueJS with Javascript

Forgive me if this sounds like a silly question. I'm currently using vue-moment within my Vue.js application and I have the following code snippet: <!-- date = '2020-03-23 01:01:01' --> <span>{{ date | moment('from', & ...

Creating connections between variables and elements in nested ngRepeats in Angular

I've been facing a challenge with my app where I need to update the comments section whenever a comment is added, edited, or deleted without having to refresh the page. I am using ngResource to handle queries for both articles and comments (e.g. $scop ...

Why does variable passing use 'object Text' instead of passing values?

In my for loop, I am dynamically creating a table with radio buttons and trying to create labels dynamically as well. However, when I pass the variable to the label text node, it prints out 'object Text' on the page instead of the expected value. ...

Ensuring all fetch requests are completed successfully before dispatching an action in React-Redux

I'm currently developing a React application and utilizing Redux to manage the state. Here is a snippet of the code: category-arrows.component.jsx: import React, { Component } from 'react'; import { connect } from 'react-redux'; i ...

Master the art of navigating the Windows Sound Recorder with the power of JavaScript

I am creating a project that involves controlling the Windows sound recorder for tasks such as starting, stopping, and saving recordings. Is there a way to do this without displaying the recorder window? I would appreciate any assistance in solving this. ...

Dealing with Unreliable Data in Scatter Plots using React and HighCharts

Initially, I utilized line charts for my data visualization needs. However, I now require multiple data points on the same X-Axis with tooltips, which has led me to discover HighCharts behavior: "In a line chart, by default, Highcharts will display t ...

Ensure to update the npm package version before making any Git commit

My project is built with Ember using NPM and I utilize Git for version control. I am looking for a way to update or bump the package.json version before or during a Git commit. Is there a method to accomplish this? Should I be implementing Git hooks? ...

The script functions perfectly in jsfiddle, yet encounters issues when used in an HTML

I stumbled upon a seemingly peculiar issue with my script in jsfiddle: https://jsfiddle.net/oxw4e5yh/ Interestingly, the same script does not seem to work when embedded in an HTML document: <!DOCTYPE html> <html lang="en"> <head> & ...

Tips on retrieving enum values in typescript

Having trouble retrieving values from an enum? Check out this snippet of code: export const enum ComplianceType { ENGINEER_ASSESMENT = 'ENGINEER_ASSESMENT', CONSTRUCTION_COMPLIANCE = 'CONSTRUCTION_COMPLIANCE', ARCHITECTURE_ASSIGN ...

THREE.JS ensures that the face normal is perpendicular to the face and facing outward

When using THREE.JS to generate a custom geometry, I define vertices and faces. However, when creating a face without specifying the normal direction like new THREE.Face3(a,b,c), some faces end up pointing inward instead of outward. Is there a way to ens ...

Exploring the filter method in arrays to selectively print specific values of an object

const array = [ { value: "Value one", label: "Value at one" }, { value: "Value 2", label: "Value at 2" }, { value: "" , label: "Value at 3" } ...

Create a global variable by importing an external module in TypeScript

I am currently developing a TypeScript npm module called https://www.npmjs.com/package/html2commonmark. This module is versatile and can be utilized in nodejs (via require) as well as in the browser (by loading node_modules/html2commonmark/dist/client/bund ...

What is the process for constructing an object to resemble another object?

After collecting input data, I have created an object based on those values. Here is an example of the generated object: var generate_fields = { name: "Mike", email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4d9dddf ...

Retrieving data from a parent object within an iframe on a different origin

In order to incorporate a feature on various websites, I am looking to embed an iframe with JavaScript. This iframe should have the ability to interact with the parent object and display or hide certain elements on the webpage. The main HTML file includes ...

What is the best way to incorporate animation using Tailwind CSS within my Next.js project?

I have a challenge with placing three images in a circular path one after the other using Tailwind CSS for styling. I've identified the circular path and keyframe style for the images. How do I configure this style in my Tailwind config file and imple ...

How can I call a global function in Angular 8?

Currently implementing Angular 8, my objective is to utilize downloaded SVG icons through a .js library. To achieve this, I have made the necessary additions to my .angular.json file: "scripts": [ "node_modules/csspatternlibrary3/js/site ...

Executing a function with a click, then undoing it with a second click

My goal is to trigger an animation that involves text sliding off the screen only when the burger icon is clicked, rather than loading immediately upon refreshing the page. The desired behavior includes activating the function on the initial click and then ...

The initial loading of jQuery DataTables shows duplicate entries

Expanding on my query from the previous day: jQuery AJAX call function on timeout Following the guidance provided in the response from yesterday's post, the table successfully reloads without requiring a full page refresh every 30 seconds. However, ...

Can the distinction between a page refresh and closure be identified using the method below?

My idea is to trigger a popup window when the page is closed, not when it is refreshed. The plan is as follows: Client Send an ajax request to the server every x seconds. Server var timeout=0 var sec=0 while (sec>timeout) { open popup win ...

Selenium and JavaScript integration for opening new browser tabs

Hello there, I am looking to open new tests ('it' method) in new tabs and currently trying this approach: driver = new Builder().forBrowser('chrome').build(); beforeEach(() => { // driver.manage().window().open('url') ...