我花了很多时间尝试使用OpenXML格式确定将.NET像素转换为Excel列宽的公式。我正在使用EPPlus生成xmls文档。我正在尝试确定要自动调整大小的列的宽度。我通过测量字符串然后尝试将其转换为OpenXML的列宽来获取像素数,这是用我认为的字符来衡量的。
我已经阅读了微软关于如何转换它的文档,并尝试了他们建议的公式,但它甚至不准确:
http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx
这是我的代码使用他们的公式:
public double GetCharacterWidth(string Text, Font f, Graphics g)
{
float MaxDigitWidth = g.MeasureString("0", f).Width;
float Pixels = g.MeasureString(Text, f).Width;
return ((Pixels - 5) / MaxDigitWidth * 100 + 0.5) / 100;
}
有什么想法吗?
答案 0 :(得分:19)
首先,我们需要确定Excel如何进行转换(因为我们手动更改Excel应用程序中的大小):
//Use 7d to promote to double, otherwise int will truncate.
ExcelWidth = (Pixels - 12) / 7d + 1;//From pixels to inches.
警告:公式不适用于0(零)宽度或像素。
对于这些情况,使用“if”语句检查是否为零并返回零。
它也把我扔了一圈。我没有试图找出每个宽度的像素,而是查看每个宽度整数之间的像素差异,发现它始终为7.异常为0到1宽度;宽度为1.00的12个像素。从那里我能够拿出上面的公式,轻松自如。
现在这些数字在Excel世界中占据了一席之地,但如果您直接在OpenXml文档中设置列宽,那么这个故事就会略有不同。原因如下:在您链接的文档中,这是关于5像素的说明:
边距填充有4个像素(每边两个),加上网格线的1个像素填充。
现在所有这些意味着Excel假设您已将这5个像素考虑到您提供的宽度中。当您在Excel中打开文档并调整列的大小时,您将看到宽度比您设置的宽度小5个像素。
要调整此项,您可以按如下方式更新公式:
//Use 7d to promote to double, otherwise int will truncate.
OpenXmlWidth = (Pixels - 12 + 5) / 7d + 1;//From pixels to inches.
这回答了你的问题的标题:
“将.NET像素转换为OpenXML格式的Excel宽度的公式”
如果您想知道如何根据单个单元格的内容(和字体)计算列宽的近似值来自动拟合列,那么这是一个完全不同的问题。您提供的Microsoft链接提供的公式将不起作用。在一个单元格中键入10个句点,在另一个列中键入10个大写字母。您将看到自动调整分别为您提供41像素和129像素。 ms提供的公式不考虑单个字符的宽度。换一种说法;他们派你去疯狂追逐。
自动调整列的唯一方法是扫描列中的每一行,并根据使用的字符和字体计算文本的宽度。你会使用我发现的here之类的东西。然后取5的最大值并用5填充。我会在Web环境中处理电子表格时避免这种方法,因为你可能导出数十万行数十列 - 你明白了。最好的方法是为列设置最佳猜测宽度,并培训用户如何从excel自动适应。
此致
“普通人”
修改 - 10/26/2011:
因为我感觉很慷慨,所以这里有一个如何为你的列获得近似宽度的例子。我宁愿避免对列中的所有行执行此操作,因此我们只需将宽度(默认情况下)基于标题单元格中的值。以下是使用我之前链接的示例执行此操作的方法。注意:这些是近似值,但足够接近。
using System.Drawing;
using System.Windows.Forms;//Add Reference. Test on webserver first.
Font font = new Font("Calibri", 11.0f, FontStyle.Regular);
string header = "Hello There World!";
int pxBaseline = TextRenderer.MeasureText("__", font).Width;
int pxHeader = TextRenderer.MeasureText("_" + header + "_"), font).Width;
int pxColumnWidth = pxHeader - pxBaseline + 5;//Pad with 5 for Excel.
警告:如果您在使用OpenXml的同一个地方使用此代码,则可能需要删除System.Drawing的“using”并完全限定“Font”和“FontStyle” “作为System.Drawing.Font和System.Drawing.FontStyle。否则,您的编译器可能会将这些类误认为属于DocumentFormat.OpenXml.Spreadsheet。
答案 1 :(得分:1)
由于我在第3 dp出现差异,因此对MikeTeeVee给出的答案进行了升级。
在根据OpenXml文件宽度计算点宽时,文档说明
列宽,以正常样式的字体中呈现的数字0、1、2,...,9的最大数字宽度的字符数来衡量。边缘填充有4个像素(每侧两个),网格线有1个像素填充。
width =截断([{字符数} * {最大数字宽度} + {5像素填充}] / {最大数字宽度} * 256)/ 256
这使我在黑暗实验中几乎陷入了僵局,并提出了从像素到宽度的转换:
double width = Math.Truncate(px / 7 * 256) / 256
这将返回与OpenXml文档中完全相同的值。
答案 2 :(得分:0)
我想出的将像素宽度转换为Excel宽度的公式是
private double PixelWidthToExcel(int pixels)
{
var tempWidth = pixels * 0.14099;
var correction = (tempWidth / 100) * -1.30;
return tempWidth - correction;
}
对我来说,它总是可以进行精确的值转换。
还有高度公式
private double PixelHeightToExcel(int pixels)
{
return pixels * 0.75;
}