Tips for adjusting the width of columns automatically in exceljs

One of my challenges is to automatically adjust column width using exceljs. I want the Excel sheet to be dynamic, saving only the columns specified by the user in the request. Here is the code snippet that accomplishes this:

workSheet.getRow(1).values = dto.columns;

This code saves the column names provided in dto.columns on the first row.

However, I also need to set the width for each column. I attempted the following approach:

for(let i=0; i <= dto.columns.length-1; i++) {
            workSheet.columns = [
                {key: dto.columns[i], width: Object.keys(dto.columns[i]).length}
            ]
        }

Unfortunately, this approach does not adjust the column widths as intended.

If anyone knows how to create an autosize function for this problem, I would greatly appreciate your help.

Thank you in advance for any assistance.

Answer №1

Loop through the cells and calculate the longest length of each cell

worksheet.columns.forEach(function (column, index) {
    let maxLen = 0;
    column["eachCell"]({ includeEmpty: true }, function (cell) {
        var cellLen = cell.value ? cell.value.toString().length : 10;
        if (cellLen > maxLen ) {
            maxLen = cellLen;
        }
    });
    column.width = maxLen < 10 ? 10 : maxLen;
});

Answer №2

This approach has been successful for me in the past. Here is an example of how you can implement it:

function ResizeColumns(sheet) {
  sheet.columns.forEach(col => {
    const valuesLengths = col.values.map(val => val.toString().length);
    const maxValLength = Math.max(...valuesLengths.filter(val => typeof val === 'number'));
    col.width = maxValLength;
  });
}

Answer №3

In case you encounter issues with other solutions not working properly when dealing with numFmt, especially for Date values, here is a unique approach that combines previously suggested concepts and utilizes the SSF library to format cell values with numFmt before calculating the length.

import { format } from 'ssf';

// Function to convert Date object to Microsoft serial date (ms date / OA date)
const dateToSerial = (date: Date): number => {
  const timezoneOffset = date.getTimezoneOffset() / (60 * 24);
  const msDate = date.getTime() / 86400000 + (25569 - timezoneOffset);
  return msDate;
};

const autoFitColumn = (column: ExcelJS.Column) => {
  const numFmt = column.numFmt;
  let maxLength = 8; // Set initial max length
  column.eachCell({ includeEmpty: true }, (cell: ExcelJS.Cell) => {
    let columnLength: number;
    if (numFmt && cell.value != undefined) {
      switch (cell.type) {
        case ExcelJS.ValueType.Date:
          const serialDate = dateToSerial(cell.value as Date);
          const formattedDate = format(numFmt, serialDate);
          columnLength = formattedDate.length;
          break;
        case ExcelJS.ValueType.Number:
          const formattedNumber = format(numFmt, cell.value as Number);
          columnLength = formattedNumber.length;
          break;
        default:
          const formatted = format(numFmt, cell.value);
          columnLength = formatted.length;
          break;
      }
    } else {
      columnLength = cell.text.length;
    }
    maxLength = Math.max(maxLength, columnLength); // Update max length if needed
  });
  column.width = maxLength + 4; // Adjust column width
};

Answer №4

Ashish's solution is effective. Much appreciated!

If you need to skip the serial number in the first cell:

Check out this code snippet:

worksheet.columns.forEach(function (column, idx) {
    if(idx!==0)
    {
        var maxLen = 0;
        column["eachCell"]({ includeEmpty: true }, function (cell) {
            var colLen = cell.value ? cell.value.toString().length : 10;
            if (colLen > maxLen ) {
                maxLen = colLen;
            }
        });
        column.width = maxLen < 10 ? 10 : maxLen;
    }
});

Answer №5

Although my response may be a bit delayed, I believe it will still be valuable to you. The examples provided above are functioning properly. With a small adjustment, everything should work seamlessly. In order to avoid conflicting column widths, here is a solution that has worked well for me:

worksheet.columns.forEach(function (column) {
    var dataMax = 0;
    column.eachCell({ includeEmpty: true }, function (cell) { 
        dataMax = cell.value ? cell.value.toString().length : 0;
        if (dataMax <= (column.header.length + 2)) {
            if (column.width > dataMax) {
                // retain the default width
            } else {
                column.width = column.header.length + 3;
            }
        } else {
            column.width = dataMax + 3;
            column.header.length = dataMax + 3;
        }
        dataMax = 0;
    })
});

Answer №6

Here is the solution that worked perfectly for me:

worksheet.columns.forEach((col) => {
    let maxLen = 0;
    col["eachCell"]({ includeEmpty: true }, (cell) => {
        const colLength = cell.value ? cell.value.toString().length + 4 : 12;
        if (cell.type === ExcelJS.ValueType.Number) {
            maxLen = 25;
        }
        else if (colLength > maxLen) {
            maxLen = colLength + 4;
        }
    });
    col.width = maxLen < 12 ? 12 : maxLen;
});

Answer №7

If we want to automatically adjust the width of a column in an excel sheet based on the length of its values, there is a simple approach that can be taken. After some experimentation, I have come up with the following solution:

Firstly, we loop through each column in the worksheet:

worksheetName.columns.forEach(col => {});
//Note: col => {} is just a shorthand for function(col) {}

Next, we need to determine the value with the longest length in each column. This information is stored in the 'values' property. Since there may be multiple values per key in a column, we look for the value with the highest length (e.g., the longest name):

// Loop through all columns in the worksheet
worksheetName.columns.forEach(col => {
    // Find the value with the longest length
    const maxLength = col.values.reduce((maxWidth, value) => {
        if (value && value.length > maxWidth) {
            return value.length;
        }
        return maxWidth;
    }, 0);
    // Set the column width to accommodate the longest value
    col.width = maxLength;
});

In cases where the header might be wider than the values in a column, we can update the code accordingly:

worksheetName.columns.forEach(col => {
    // Access the header length
    const headerLength = col.header.length;
    // Determine the longest value in the column
    const maxLength = col.values.reduce((maxWidth, value) => {
        if (value && value.length > maxWidth) {
            return value.length;
        }
        return maxWidth;
    }, 0);
    // Adjust column width based on the header and values
    col.width = Math.max(headerLength, maxLength);
});

To add additional spacing to the cells, a number can be included in the calculation. The final code would look something like this:

worksheetName.columns.forEach(col => {
    // Get the header length
    const headerLength = col.header.length;
    // Determine the longest value length in the column
    const maxLength = col.values.reduce((maxWidth, value) => {
        if (value && value.length > maxWidth) {
            return value.length;
        }
        return maxWidth;
    }, 0);
    // Adjust column width with added padding
    col.width = Math.max(headerLength, maxLength) + 2;
});

Answer №8

[2].forEach(ind => billsTbl.columns.getAt(ind).getBodyDataRange().edit.format.sizeToFit());

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

Get rid of numerous div elements in a React.js application with the help of a Remove button

I need help figuring out how to efficiently remove the multiple div's that are generated using the add button. I am struggling to grasp how to pass the parent div's id into the delete method from the child div. Additionally, I'm wondering if ...

Converting axios response containing an array of arrays into a TypeScript interface

When working with an API, I encountered a response in the following format: [ [ 1636765200000, 254.46, 248.07, 254.78, 248.05, 2074.9316693 ], [ 1636761600000, 251.14, 254.29, 255.73, 251.14, 5965.53873045 ], [ 1636758000000, 251.25, 251.15, 252.97, ...

The Vue component fails to refresh after modifications to the state in the Pinia store

I'm currently immersed in my inaugural vue application, focusing on constructing the login functionalities. To handle State management, I've implemented pinia. I've set up a Pinia Store to globally manage the "isLoggedIn" state. import { def ...

"Make sure to specify Safari input field as an email and mark

I am experiencing an issue with a contact form in my HTML/PHP code. Everything seems to be working fine, but when using the SAFARI browser, the form fails to validate if I try to submit without filling out all input fields. For example, my form includes: ...

Tips for developing a dynamic game that adjusts to different screen sizes using Phaser 3

Recently, I've been on the hunt for a way to ensure my game adapts seamlessly to various screen resolutions when using Phaser 3. In the past, I achieved this with ease in Construct 2. However, I'm now curious to explore how best to implement thi ...

Using Selenium webdriver to assign a JSON object to a paragraph element

What is the correct way to insert a JSON object into a p tag inside an iframe? I attempted the following approach but it displayed the text "[object Object]" rather than the actual content of the object... This is my implemented code: var arrJSON = [ ...

The next column featuring a dropdown menu

My goal is to make this sketch operational. The red elements in the sketch need to be programmed. Currently, I am using angularJS and bootstrap with the following code: <div class="col-md-6"> <div class="form-group"> <label&g ...

Updating chart.js data seems to be presenting some challenges

Need help fetching data with an AJAX request to update chart.js. The AJAX request is working fine, but the response doesn't update the chart. This is how I fetch the data: <script type="text/javascript"> $(document).ready(function(){ $("#da ...

Using JQuery to enable checkbox if another is selected

I have a single checkbox that reveals a hidden div when checked. Inside this div, there are two additional checkboxes. My goal is to disable the initial checkbox if either of these two checkboxes is checked. Here's the HTML code snippet: <p> ...

TypeScript combined with Vue 3: Uncaught ReferenceError - variable has not been declared

At the start of my <script>, I define a variable with type any. Later on, within the same script, I reference this variable in one of my methods. Strangely, although my IDE does not raise any complaints, a runtime error occurs in my console: Referenc ...

Aligning validation schema with file type for synchronization

Below is the code snippet in question: type FormValues = { files: File[]; notify: string[]; }; const validationSchema = yup.object({ files: yup .array<File[]>() .of( yup .mixed<File>() .required() .t ...

What is the method for adding a tag within a specific div ID in ExtJS?

I am looking to insert a new tag within existing tags using extjs, based on the div id 'task123', and also trigger an alert message accordingly. Below is the HTML code snippet: <div id="task123"> <div class="msg" id="sample"> ...

Passing a map from the SpringBoot backend to the Angular view and storing it in LocalStorage

I'm facing a challenge with this task. I am trying to transfer a Map from my Spring Boot backend to an Angular application. Controller @GetMapping("/dict") public Map<String, String> getAll(){ return dictionaryService.getAll(); } @ ...

granting authorization to modify content post channel establishment in discord using discord.js

I am encountering an issue with granting the message.author and staff permission to view the channel right after its creation. The problem arises when the channel's parent (category) is changed, causing it to synchronize with the permissions of the pa ...

Ways to transmit information from a React application to a Node server

As a Nodejs beginner, I am using the rtsp-relay library for live streaming. Currently, it is working in the frontend when the URL is included in the server proxy object like this: rtsp://.....@..../Stream/Channel/10. However, I want users to be able to inp ...

What is causing the lack of updated data on the components when navigating to a different page? (Vue.JS 2)

I am working with 2 components The first component looks like this : http://pastebin.com/M8Q3au0B Due to the long code, I have used pastebin for it The first component calls the second component The second component is as follows: <template> ...

jQuery ajax doesn't function properly on the server, it only works locally

When I send a jQuery Ajax request from my front-end to the back-end to retrieve values for calculations, it works perfectly on my local web server. However, when I try it online, all I get is a result of 0 in my calculations, indicating that the Ajax respo ...

A method using JQuery and Javascript to retrieve Highcharts data in JSON format, properly structured, by leveraging Selenium with C# programming

I am currently working on extracting the JSON equivalent of a highchart graph using Selenium and C# but have encountered a few obstacles along the way. To retrieve the JSON data for a specific highchart, follow these steps: Visit the URL Log in using th ...

Achieving a draggable object to land on a designated target

Before you jump to conclusions based on the title, let me clarify that I am not referring to jQuery UI draggable. Instead, I am discussing a plugin that I am currently developing for the community. The goal of my plugin is to create a designated target fea ...

Understanding special characters within a URL

Here is a URL example: postgres://someuser:pas#%w#@rd-some-db.cgosdsd8op.us-east-1.rds.amazonaws.com:5432 This URL is being parsed using the following code snippet: const url = require('url'); const { hostname: host, port, auth, path } = url.par ...