以OpenXML格式将.NET像素转换为Excel宽度的公式

Jef*_*ock 12 c# openxml

我花了很多时间尝试使用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;
    }
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Mik*_*Vee 20

首先,我们需要确定Excel如何进行转换(因为我们手动更改Excel应用程序中的大小):

//Use 7d to promote to double, otherwise int will truncate.
ExcelWidth = (Pixels - 12) / 7d +  1;//From pixels to inches.
Run Code Online (Sandbox Code Playgroud)

警告:公式不适用于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.
Run Code Online (Sandbox Code Playgroud)

这回答了你的问题的标题:
" 以OpenXML格式将.NET像素转换为Excel宽度的公式 "

如果您想知道如何根据单个单元格的内容(和字体)计算列宽的近似值来自动拟合列,那么这是一个完全不同的问题.您提供的Microsoft链接提供的公式将不起作用.在一个单元格中键入10个句点,在另一个列中键入10个大写字母.您将看到自动调整分别为您提供41像素和129像素.ms提供的公式不考虑单个字符的宽度.换一种说法; 他们派你去疯狂追逐.

自动调整列的唯一方法是扫描列中的每一行,并根据使用的字符和字体计算文本的宽度.你会使用我在这里找到的东西.然后取5的最大值并用5填充.我会在Web环境中处理电子表格时避免这种方法,因为你可能导出数十万行数十列 - 你明白了.最好的方法是为列设置最佳猜测宽度,并培训用户如何从excel自动调整.

此致,
" The Common Man "


编辑 - 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.
Run Code Online (Sandbox Code Playgroud)

警告:如果您在使用OpenXml的同一个地方使用此代码,则可能需要删除System.Drawing的"using"并将"Font"和"FontStyle"完全限定为System.Drawing.Font和System. Drawing.FontStyle.否则,您的编译器可能会将这些类误认为属于DocumentFormat.OpenXml.Spreadsheet.