【问题标题】:Calculate the size (Extents) of a text (TextBody) in OpenXML (PresentationML) PowerPoint (PPTX)在 OpenXML (PresentationML) PowerPoint (PPTX) 中计算文本 (TextBody) 的大小 (Extents)
【发布时间】:2015-09-19 13:03:15
【问题描述】:

我想用来自数据库的数据创建一个演示文稿。我设法获得在 PowerPoint 中打开的有效演示文稿(SDK 2.5 的Open XML Productivity Tool 对执行此操作有很大帮助)。但是,如何计算文本框形状的大小?我知道将值放在哪里,但new Extents() 默认宽度和高度为零。当我从现有演示文稿中获取Shape 的一些值时,我可能会得到正确的高度(至少对于一行或固定行数的文本),但文本会溢出到右侧或底部(取决于自动换行设置)。

TextBodyBodyProperties 中插入NormalAutoFit 也无济于事 - 在 OpenXML 中不会计算 FontScaleLineSpaceReduction 的必要值。

那么,将ShapeExtents 设置为TextBody 的最佳做法是什么?

是否有内置方法来计算给定TextBodyShapeExtents? (使用内置方法的一些经验法则总比没有好)

我知道 PowerPoint 将在进行任何更改后重新计算 NormalAutoFit 的值(至少对于更改前后的一堆幻灯片),但是当演示文稿在更改之前开始时这无济于事制作(或者如果它是使用 PowerPoint 查看器启动的)。

【问题讨论】:

  • 我有同样的问题,并且通过从 TextRenderer.MeasureText() 返回的范围缩放到包含的文本框取得了一些进展。但是它的文本大小并不像 Powerpoint 重新计算的缩放那样紧密围绕文本。通过从高度中减去前导和从宽度中减去管道字符宽度,我得到了更进一步的结果。欢迎提供更多想法。

标签: c# powerpoint openxml openxml-sdk presentationml


【解决方案1】:

来自Eric White's Forum

这是一项不平凡(但可行)的任务。

经过多次实验,我发现 System.Windows.Forms.TextRenderer 中的文本度量方法给了我最好的结果。这是 WmlToHtmlConverter 使用的文本度量功能。您可以查看 WmlToHtmlConverter 中的代码作为 TextRenderer 的使用示例。

这是我根据 Eric White 的 WmlToHtmlConverter、this postthis 为我的目的提出的代码。我用它来计算文本水印的 TextBox 尺寸和 Word 文档的 OpenXml 图像水印的尺寸。

    private static D.Size pixelsToEmus(int widthPx, int heightPx, double resDpiX, double resDpiY, int zoomX, int zoomY)
    {
        const int emusPerInch = 914400;
        const int emusPerCm = 360000;
        const decimal maxWidthCm = 16.51m;
        var widthEmus = (int)(widthPx / resDpiX * emusPerInch) * zoomX / 100;
        var heightEmus = (int)(heightPx / resDpiY * emusPerInch) * zoomY / 100;
        var maxWidthEmus = (int)(maxWidthCm * emusPerCm);
        if (widthEmus > maxWidthEmus)
        {
            var ratio = ((decimal)heightEmus / (decimal)widthEmus);
            widthEmus = maxWidthEmus;
            heightEmus = (int)(widthEmus * ratio);
        }
        return new D.Size(widthEmus, heightEmus);
    }

    public static D.Size GetTextSize(this CWatermarkItemBase watermark, string runText)
    {
        var fs = watermark.GetFontStyle();
        var sz = watermark.FontSize;
        var proposedSize = new D.Size(int.MaxValue, int.MaxValue);
        D.Size sf;

        using (var ff = new D.FontFamily(watermark.FontFamily))
        {
            try
            {
                using (var f = new D.Font(ff, (float)sz, fs))
                {
                    const TextFormatFlags tff = TextFormatFlags.NoPadding;
                    sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                }
            }
            catch (ArgumentException)
            {
                try
                {
                    const D.FontStyle fs2 = D.FontStyle.Regular;
                    using (D.Font f = new D.Font(ff, (float)sz, fs2))
                    {
                        const TextFormatFlags tff = TextFormatFlags.NoPadding;
                        sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                    }
                }
                catch (ArgumentException)
                {
                    const D.FontStyle fs2 = D.FontStyle.Bold;
                    try
                    {
                        using (var f = new D.Font(ff, (float)sz, fs2))
                        {
                            const TextFormatFlags tff = TextFormatFlags.NoPadding;
                            sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // if both regular and bold fail, then get metrics for Times New Roman
                        // use the original FontStyle (in fs)
                        using (var ff2 = new D.FontFamily("Times New Roman"))
                        using (var f = new D.Font(ff2, (float)sz, fs))
                        {
                            const TextFormatFlags tff = TextFormatFlags.NoPadding;
                            sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                        }
                    }
                }
            }
        }
        D.Size s2 = pixelsToEmus(sf.Width, sf.Height, 96, 96, 100, 100);
        return s2;
    }
    public static D.Size GetImageSize(this CWatermarkItemImage watermarkItem)
    {
        var img = new BitmapImage(new Uri(watermarkItem.FilePath, UriKind.RelativeOrAbsolute));
        return pixelsToEmus(img.PixelWidth, img.PixelHeight, img.DpiX, img.DpiY, watermarkItem.ZoomWidth, watermarkItem.ZoomHeight);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多