Python 2.7 在MS Excel中,GetTextExtentPoint32W返回的单元格中文本的文本宽度大于实际宽度

Python 2.7 在MS Excel中,GetTextExtentPoint32W返回的单元格中文本的文本宽度大于实际宽度,python-2.7,excel,ctypes,vba,Python 2.7,Excel,Ctypes,Vba,我正在使用GetTextExtentPoint32W获取MS Excel 2010中单元格中文本的宽度。使用ActiveCell.width获取单元格宽度。然后比较这两种宽度,以确定文本是适合单元格还是延伸出单元格。 从视觉上看,即使文本完全适合单元格,该方法返回的文本宽度也大于单元格宽度。此外,当我增加字体大小时,实际文本宽度与方法返回的文本宽度之间的差异也会增加。 下面是用于实现结果的部分源代码。请帮我解决这个错误 hDC=ctypes.windell.user32.GetDC(self.w

我正在使用
GetTextExtentPoint32W
获取MS Excel 2010中单元格中文本的宽度。使用
ActiveCell.width
获取单元格宽度。然后比较这两种宽度,以确定文本是适合单元格还是延伸出单元格。 从视觉上看,即使文本完全适合单元格,该方法返回的文本宽度也大于单元格宽度。此外,当我增加字体大小时,实际文本宽度与方法返回的文本宽度之间的差异也会增加。 下面是用于实现结果的部分源代码。请帮我解决这个错误

hDC=ctypes.windell.user32.GetDC(self.windowHandle)
tempBMP=ctypes.windell.gdi32.CreateCompatibleBitmap(hDC,1,1)
hBMP=ctypes.windell.gdi32.SelectObject(hDC、tempBMP)
iFontSize=self.excelCellObject.Font.Size
deviceCaps=ctypes.windell.gdi32.GetDeviceCaps(hDC,90)
iFontSize=int(iFontSize)
iFontSize=ctypes.c_int(iFontSize)
iFontSize=ctypes.windell.kernel32.MulDiv(iFontSize,deviceCaps,72)
iFontSize=iFontSize*-1
如果self.excelObject.Font.Bold else 400,则iFontWeight=700
sFontName=self.excelCellObject.Font.Name
sFontItalic=self.excelcolbject.Font.Italic
sFontUnderline=如果self.excelCellObject.Font.Underline else为False,则为True
sfontstreethrough=self.excelcolbject.Font.streethrough
#创建具有正确大小、重量和样式的字体对象
hFont=ctypes.windell.gdi32.CreateFontW(iFontSize,
0, 0, 0, 
如果体重增加,
斯芬塔利克,
斯芬特强调,
斯芬特斯克勒,
假,假,假,,
假,假,,
(姓名)
#将字体加载到设备上下文中,存储原始字体对象
hOldFont=ctypes.windell.gdi32.SelectObject(hDC、hFont)
sText=self.excelObject.Text
log.io(“\nText\t”+sText+“\n”)
text长度=len(sText)
类structText(ctypes.Structure):
_字段=[(“宽度”,ctypes.c_int),
(“高度”,ctypes.c_int)]
StructText=StructText()
getTextExtentPoint=ctypes.windell.gdi32.GetTextExtentPoint32W
getTextExtentPoint.argtypes=[ctypes.c\u void\u p,
ctypes.c_char_p,
ctypes.c_int,
ctypes.POINTER(结构文本)]
getTextExtentPoint.restype=ctypes.c_int
#获取文本尺寸
a=ctypes.windell.gdi32.GetTextExtentPoint32W(hDC,
sText,
文本长度,
ctypes.byref(结构文本))
#删除我们创建的字体对象
a=ctypes.windell.gdi32.DeleteObject(hFont)
a=ctypes.windell.gdi32.DeleteObject(tempBMP)
#释放设备上下文
a=ctypes.windell.user32.ReleaseDC(self.windowHandle,hDC)
textWidth=StructText.width
cellWidth=self.excelCellObject.Width

谢谢。

我不使用Python或Excel 2010,因此无法对您当前的方法发表评论。然而,我也遇到了类似的问题。我希望以下几点会有所帮助


背景

如果将鼠标悬停在Excel列的右边界上并按住鼠标左键,则会显示以下格式:“宽度:n.nn(mm像素)”

ColumnWidth属性的帮助说明:

一个列宽单位等于一行中一个字符的宽度 正常风格。对于比例字体,字符的宽度为0 使用(零)

使用Width属性以点为单位返回列的宽度

据我所知,“普通样式”是指创建工作簿时的标准字体名称和大小。更改现有工作簿的标准字体名称和大小似乎没有任何效果。更改工作表的字体名称和大小无效

标准宽度列的两个示例显示为:

For Arial 10         Width: 8.43 (64 pixels)
For Tahoma 10.5      Width: 8.38 (72 pixels)
我创建了一个零字符串,并试图根据列的宽度测量有多少个是可见的。我发现我能看到的零的数量与显示的值相当匹配,比如主观测量

使用VBA时,列或单元格的ColumnWidth属性以字符为单位设置或返回宽度

使用VBA,列或单元格的只读宽度属性返回.75*像素宽度

上述信息的意义在于,从Excel获得的宽度值不一定适合所使用的字体


我的问题和我发现的解决方案

我遇到的问题是,我正在合并单元格并用文本填充它们。尽管Excel会调整行的高度,以便未合并单元格中的文本可见,但对于合并单元格,它不会这样做。我尝试了很多技术,包括微软的.Net,文本渲染程序,但都没有成功。我尝试过的任何东西都不能可靠地模仿Excel确定文本宽度的系统

我最终成功使用的技术是在所有使用过的细胞的右边和下面挑选一个细胞进行实验。我调整了实验单元格列的宽度,使其与合并单元格的组合宽度相匹配,并从我想要的单元格高度复制了格式化值。由于实验单元未合并,Excel将根据需要调整高度。然后,我确保源行至少有这个高度