【问题标题】:Formula to convert .NET pixels to Excel width in OpenXML format将 .NET 像素转换为 OpenXML 格式的 Excel 宽度的公式
【发布时间】:2011-12-04 16:33:26
【问题描述】:

我花了很多时间试图确定一个公式,以使用 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;
    }

有什么想法吗?

【问题讨论】:

  • 如果它是一个自动调整大小的列,为什么不使用链接的 MSDN 中指定的最合适的属性?
  • 我已经试过了。如果将 BestFit 设置为 True,然后打开电子表格,则列的大小不合适。
  • 像素到动车组是(像素 * 12700)。我根本不希望列宽以像素为单位。试试动车组。

标签: c# openxml


【解决方案1】:

升级 MikeTeeVee 给出的答案,因为我在 3rd dp 看到了差异。

根据文档说明从 OpenXml 文件宽度计算点宽度

列宽测量为以正常样式字体呈现的数字 0、1、2、...、9 的最大数字宽度的字符数。有 4 个像素的边距填充(每边两个),外加 1 个像素的网格线填充。

width = Truncate([{字符数} * {最大数字宽度} + {5 像素填充}]/{最大数字宽度}*256)/256

这导致我在黑暗实验中进行了一个主要的尝试,并提出了从像素到宽度的转换:

double width = Math.Truncate(px / 7 * 256) / 256

这将返回与 OpenXml 文档中的值完全相同的值。

【讨论】:

    【解决方案2】:

    我想出的将像素宽度转换为 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;
        }
    

    【讨论】:

    • 到目前为止这对我有用,但是你从哪里得到这些公式?只是想知道?
    • 我想出了它们,然后我测试+调整直到我满意。反复试验。
    【解决方案3】:

    首先我们需要确定 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 宽度;其中 Width 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 个大写字母 M。您将看到自动调整分别为您提供 41 像素和 129 像素。 ms 提供的公式没有考虑单个字符的宽度。换一种说法;他们派你去追逐野鹅。

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

    此致
    普通人


    编辑 - 2011 年 10 月 26 日:

    因为我感觉很慷慨,这里有一个示例,说明如何为您的列获取 近似 宽度。我宁愿避免对列中的所有行执行此操作,所以让我们将宽度(默认情况下)基于标题单元格中的值。下面是如何使用我之前链接到的示例来执行此操作。注意:这些是近似值,但足够接近。

    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 的“使用”并完全限定“字体”和“字体样式” " 作为 System.Drawing.Font 和 System.Drawing.FontStyle。否则您的编译器可能会将这些类误认为属于 DocumentFormat.OpenXml.Spreadsheet 。

    【讨论】:

    • 我发现你建议的第一个公式是最准确的,但还不够准确。正如您所说,我必须对其进行一些修改以做出“最佳猜测”。
    • 你看到我在底部我的编辑下发布的代码了吗?我使用它,它非常适合我的需求(给或取几个像素,但不足以显示磅符号或剪辑文本)。我可能会修改我的代码以扫描标题和前 20 行的最大宽度(因为这是用户第一次打开文档时首先看到的内容)。至于第一个公式,它在将像素计算为 OpenXML-Width 时非常准确,这将在打开 Excel 文档时产生相同的确切像素数(请记住设置相同的字体名称、粗体和大小)。感谢您的积分!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2022-07-06
    • 2015-07-18
    相关资源
    最近更新 更多