Auto Column Width #2535
Replies: 31 comments
-
+1 |
Beta Was this translation helpful? Give feedback.
-
look #36 |
Beta Was this translation helpful? Give feedback.
-
Hopfully this because something built into ExcelJS down the road, but in the meantime this is how I solved the issue:
This allows you to have a minimum width (12) or base the column width off the number of characters in the header string. Sadly, unless you're using a mono typeface this isn't going to be exactly accurate, but it'll get you a lot closer. If you need to base it off of contents instead of header length, you can always loop through the rows to find the longest string length and base the width off of that. |
Beta Was this translation helpful? Give feedback.
-
there is an array with values if I add the row all well, all values are exported to excel, but I can not build the column ((( who can do?? |
Beta Was this translation helpful? Give feedback.
-
I've had some luck with the still rough but maybe more accurate approach below in TypeScript: /** Determined this value based upon experimentation */
export const PIXELS_PER_EXCEL_WIDTH_UNIT = 7.5
export function autoSize(sheet: excel.Worksheet, fromRow: number) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (!ctx) {
return
}
const maxColumnLengths: Array<number> = []
sheet.eachRow((row, rowNum) => {
if (rowNum < fromRow) {
return
}
row.eachCell((cell, num) => {
if (typeof cell.value === 'string') {
if (maxColumnLengths[num] === undefined) {
maxColumnLengths[num] = 0
}
const fontSize = cell.font && cell.font.size ? cell.font.size : 11
ctx.font = `${fontSize}pt Arial`
const metrics = ctx.measureText(cell.value)
const cellWidth = metrics.width
maxColumnLengths[num] = Math.max(maxColumnLengths[num], cellWidth)
}
})
})
for (let i = 1; i <= sheet.columnCount; i++) {
const col = sheet.getColumn(i)
const width = maxColumnLengths[i]
if (width) {
col.width = width / PIXELS_PER_EXCEL_WIDTH_UNIT + 1
}
}
} |
Beta Was this translation helpful? Give feedback.
-
This worked well for me : `// Auto width column
|
Beta Was this translation helpful? Give feedback.
-
Very nice explanation, but when I tried this has a performance issue, my worksheet has lots of rows /columns running into thousands. Any help on optimising my response time. |
Beta Was this translation helpful? Give feedback.
-
A bit different solution and in TypeScript:
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
although the cells can be expanded normally, this calculation method seems to be inaccurate. |
Beta Was this translation helpful? Give feedback.
-
A little bit diff way to make it reusable for all worksheets. `class Exporter{
export(){ |
Beta Was this translation helpful? Give feedback.
-
Feel free to use my solution /**
* Autofit columns by width
*
* @param worksheet {ExcelJS.Worksheet}
* @param minimalWidth
*/
const autoWidth = (worksheet, minimalWidth = 10) => {
worksheet.columns.forEach((column) => {
let maxColumnLength = 0;
column.eachCell({ includeEmpty: true }, (cell) => {
maxColumnLength = Math.max(
maxColumnLength,
minimalWidth,
cell.value ? cell.value.toString().length : 0
);
});
column.width = maxColumnLength + 2;
});
}; |
Beta Was this translation helpful? Give feedback.
-
Inspired by @MeisQuietude solution for const autoHeight = (worksheet) => {
const lineHeight = 12 // height per line is roughly 12
worksheet.eachRow((row) => {
let maxLine = 1
row.eachCell((cell) => {
maxLine = Math.max(cell.value.split('\n').length - 1, maxLine)
})
row.height = lineHeight * maxLine
})
} Caveat: Performance will be slow due to the iteration of between rows and cells! |
Beta Was this translation helpful? Give feedback.
-
I Use this logic for resizing the height & should also work with merged cells. |
Beta Was this translation helpful? Give feedback.
-
Here is the answer I was looking for, hope it would be helpful for someone. For height you can see https://learn.microsoft.com/en-us/javascript/api/excel/excel.rangeformat?view=excel-js-preview#excel-excel-rangeformat-autofitrows-member(1) |
Beta Was this translation helpful? Give feedback.
-
Unfortunately, that is the Office Add-ins JavaScript API, which will only work inside an instance of Excel. Autofitting columns is an internal API to Excel program itself, and people have been trying to figure out how to gracefully implement it within the Office Open XML spec for years ( what everyone besides Microsoft has to grapple with to create XLSX files ). The best solution to do this (still kindof a hack) has been around for a long time, but It only works when the spreadsheet is opened by excel, and only sometimes... you have to set these attributes on the columns of a worksheet : {BestFit : true, CustomWidth : true} There are caveats to this since this is kindof a backwards way of achieving autofit. See: |
Beta Was this translation helpful? Give feedback.
-
@MeisQuietude I'm using Angular, so I adapted your solution to use it in service like a method:
|
Beta Was this translation helpful? Give feedback.
-
When there's a import { format } from 'ssf';
// Convert Date object to Microsoft serial date aka ms date aka 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 = 6;
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);
});
column.width = maxLength + 2;
}; |
Beta Was this translation helpful? Give feedback.
-
This works really great! case ValueType.RichText:
const richTextValue = (cell.value as CellRichTextValue).richText.map(prop('text')).join('');
columnLength = richTextValue.length;
break;
case ValueType.Formula:
break;
|
Beta Was this translation helpful? Give feedback.
-
This works for me! /**
* Calculate columns width.
*/
const columnWidths = columns.map(
(column, columnIndex) => {
/**
* Max width for each column.
*/
const maxContentWidth = rows.reduce((maxWidth, row) => {
const cellValue = row[columnIndex]
const cellWidth = cellValue ? String(cellValue).length : 0
return Math.max(maxWidth, cellWidth)
}, column.name.length)
/**
* Add a extra space.
*/
return maxContentWidth + 2
}
)
/**
* Apply width.
*/
columnWidths.forEach((width, columnIndex) => {
worksheet.getColumn(columnIndex + 1).width = width
}) |
Beta Was this translation helpful? Give feedback.
-
Is there a way to set column width based on cell's content length ?
thank you
Beta Was this translation helpful? Give feedback.
All reactions