0

“一个单位的列宽等于 Normal 样式中一个字符的宽度。对于比例字体,使用字符 0(零)的宽度。”

因此ColumnWidth,在 Excel 中,以适合一列的“0”字符数来衡量。如何将此值转换为像素,反之亦然?

图片来自 https://bettersolutions.com/excel/rows-columns/column-widths.htm

4

1 回答 1

2

如前所述ColumnWidth,Excel 中的值取决于工作簿的默认字体,可以通过Workbook.Styles("Normal").Font. 它还取决于当前屏幕 DPI。

在 Excel 2013 中对不同字体和大小进行了一些研究后,我发现我们有 2 个线性函数(Arial 无法看到,因为它与 Tahoma 重叠。):

在此处输入图像描述

从图中可以看出,该功能ColumnWidth < 1与折线图的主要部分不同。它被计算为一列中的像素数/在一列中适合一个“0”字符所需的像素数。

现在让我们看看典型的单元格宽度是由什么组成的。

在此处输入图像描述

  • A- 普通样式中的“0”字符宽度
  • B- 左右填充
  • C- 1px 右边距

A可以用GetTextExtentPoint32 Windows API 函数计算,但字体大小要大一点。通过实验,我选择了 +0.3pt,它适用于基本大小为 8-48pt 的不同字体。使用"round half up"B(A + 1) / 4入为整数。这里还需要屏幕 DPI(请参阅下面的 Python 3 实现)

以下是字符像素转换的方程式及其在 Python 3 中的实现:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

import win32print, win32gui
from math import floor

def get_screen_dpi():
    dc = win32gui.GetDC(0)
    LOGPIXELSX, LOGPIXELSY = 88, 90
    dpi = [win32print.GetDeviceCaps(dc, i) for i in (LOGPIXELSX,
                                                        LOGPIXELSY)]
    win32gui.ReleaseDC(0, dc)
    return dpi

def get_text_metrics(fontname, fontsize):
    "Measures '0' char size for the specified font name and size in pt"
    dc = win32gui.GetDC(0)
    font = win32gui.LOGFONT()
    font.lfFaceName = fontname
    font.lfHeight = -fontsize * dpi[1] / 72
    hfont = win32gui.CreateFontIndirect(font)
    win32gui.SelectObject(dc, hfont)
    metrics = win32gui.GetTextExtentPoint32(dc, "0")
    win32gui.ReleaseDC(0, dc)
    return metrics

def ch_px(v, unit="ch"):
    """
    Convert between Excel character width and pixel width.
    `unit` - unit to convert from: 'ch' (default) or 'px'
    """
    rd = lambda x: floor(x + 0.5)  # round half up
    # pad = left cell padding + right cell padding + cell border(1)
    pad = rd((z + 1) / 4) * 2 + 1
    z_p = z + pad  # space (px) for "0" character with padding
    if unit == "ch":
        return v * z_p if v < 1 else v * z + pad
    else:
        return v / z_p if v < z_p else (v - pad) / z

font = "Calibri", 11
dpi = get_screen_dpi()
z = get_text_metrics(font[0], font[1] + 0.3)[0]  # "0" char width in px
px = ch_px(30, "ch")
ch = ch_px(px, "px")
print("Characters:", ch, "Pixels:", px, "for", font)
于 2020-04-05T11:28:07.483 回答