我终于找到了一个使用图形引擎 GDI+ 来准确执行此操作的解决方案。avg. char width * number of chars
从来没有削减它。
这里有一个警告,如果您的目标平台是 linux,您将需要几个库 - 一个用于 GDI+ 互操作,另一个用于添加开放的 microsoft web 字体。
它使用像素的基本单位,考虑到 excel 字体pt
和列宽英寸!(哈哈)
这是方法。它需要一个 JSchema 来映射到列,但你明白了要点。
private static Columns CreateColumnDefs(JSchema jsonSchema)
{
const double cellPadding = .4;
const double minCellWidth = 10;
var columnDefs = new Columns();
var columnIndex = 0U;
// set up graphics for calculating column width based on heading text width
var bmp = new Bitmap(1, 1);
// todo: ensure linux host has gdi and "Microsoft core fonts" libs installed
using var graphics = Graphics.FromImage(bmp);
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.PageUnit = GraphicsUnit.Pixel;
// excel fonts are in points - Arial 10pt matches the excel default of Calibri 11pt pretty well...
using var font = new Font("Arial", 10F, FontStyle.Bold, GraphicsUnit.Point);
// currently only handles 1 level (no nested objects)
foreach (var (_, value) in jsonSchema.Properties)
{
var pixelWidth = graphics.MeasureString(value.Title, font).Width;
// see: https://stackoverflow.com/questions/7716078/formula-to-convert-net-pixels-to-excel-width-in-openxml-format/7902415
var openXmlWidth = (pixelWidth - 12 + 5) / 7d + 1; // from pixels to inches.
columnIndex++;
var column = new Column
{
BestFit = true,
CustomWidth = true,
Width = Math.Max(openXmlWidth + cellPadding, minCellWidth),
Min = columnIndex,
Max = columnIndex
};
columnDefs.Append(column);
}
return columnDefs;
}
编辑
要在 linux 安装上运行,例如:
RUN apt update && apt-get install -y libgdiplus
(我不需要任何额外的字体库,所以也许系统字体有效)