c# - OpenXml 强制图像适合父容器

标签 c# ms-word openxml openxml-sdk

我正在使用以下代码将一段 hmtl 解析为 word 文档

//Need the following packages
//<package id="DocumentFormat.OpenXml" version="2.7.2" targetFramework="net471" />
//<package id = "HtmlToOpenXml.dll" version="2.0.1" targetFramework="net471" />

using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Wordprocessing;
using HtmlToOpenXml;

namespace ConsoleAppHtmlParse
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileName = @"C:\temp\myDoc.docx";

            using (WordprocessingDocument document = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
            {
                document.AddMainDocumentPart();
                document.MainDocumentPart.Document = new Document(new Body());
                HtmlConverter conveter = new HtmlConverter(document.MainDocumentPart);

                var compositeElements = conveter.Parse(Html);

                Paragraph p = compositeElements[0] as Paragraph;
                p.ParagraphProperties = new ParagraphProperties();
                p.ParagraphProperties.FrameProperties = new FrameProperties();
                p.ParagraphProperties.FrameProperties.Width = new StringValue("3200");

                document.MainDocumentPart.Document.Body.Append(compositeElements);
            }
        }

        const string Html = "<p>SomeText<img  src=\"data:image/png;base64,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\" alt=\"Screenshot_3\" />moretext</p>";
    }
}

上面的代码示例产生如下内容:
enter image description here
我想将图像“缩小”成这样:
enter image description here

如果我知道“父”容器大小,我可以这样做吗?

谢谢

最佳答案

了解 OpenXml 的修改:

w:drawing 元素有两个部分来管理图像大小

  1. wp:extent 节点,wp:inline 的子节点,它确定将包含图像的文档区域的范围。这对我们没有帮助。

注意:Libre Office 必备

extent

  1. spPr 节点用于定义包含 xfrm 节点的形状属性,该节点将变换应用于对象。它定义偏移量和范围。

注意:OpenXml - Google Documents等必备

inline extent

我在下面编写了一个程序,对您的代码进行了两处修改。

  1. 定义页面宽度:设置PageSizePageMargin:定义我们需要用图像填充的可用区域。在我们的例子中,可用区域可以定义如下:

    Available Page Width = PageSize.Width - PageMargin.Left - PageMargin.Right

    // Define Constants for Page Width and Page Margin
    private const int PageWidth = 17000;
    private const int PageHeight = 10000;
    private const int PageMarginLeft = 1000;
    private const int PageMarginRight = 1000;
    private const int PageMarginTop = 1000;
    private const int PageMarginBottom = 1000;
    private const double DocumentSizePerPixel = 15;
    private const double EmuPerPixel = 9525;
    
    // Set Page Size and Page Margin so that we can place the image as desired.
    // Available Width = PageWidth - PageMarginLeft - PageMarginRight (= 17000 - 1000 - 1000 = 15000 for default values)
    var sectionProperties = new SectionProperties();
    sectionProperties.AppendChild(new PageSize { Width = PageWidth, Height = PageHeight });
    sectionProperties.AppendChild(new PageMargin { Left = PageMarginLeft, Bottom = PageMarginBottom, Top = PageMarginTop, Right = PageMarginRight });
    document.MainDocumentPart.Document.Body.AppendChild(sectionProperties);
    
  2. 更新图像宽度:使用更新后的图像宽度和高度值更新Extents

    1. 计算纵横比,有助于更新图像的高度。

    2. 使用下面的方法计算Emu中单词理解的新宽度

      15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel

      Avalable page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu

    3. 在 Google Documents 和 Libre Office 等两个不同的地方使用 Extents 更新页面的宽度和高度。

               // Search for Extents used by the word present in Drawing > Inline > Extent
              var inlineEnumerable = p.ChildElements.Where(e => e is DocumentFormat.OpenXml.Wordprocessing.Run)
                  .Where(r => r.GetFirstChild<Drawing>() != null).Select(r => r.GetFirstChild<Drawing>())
                  .Where(r => r.GetFirstChild<Inline>() != null).Select(r => r.GetFirstChild<Inline>());
      
              // Update Visible Extent
              var inlineChildren = inlineEnumerable as Inline[] ?? inlineEnumerable.ToArray();
              foreach (var inlineChild in inlineChildren)
              {
                  var inlineElement = inlineChild.Extent;
                  UpdateExtent(inlineElement);
              }
      
              // Search for Extents used by the word present in Drawing > Inline > Graphic > GraphicData > Picture > ShapeProperties > Transform2D > Extents
              var extentsEnumerable = inlineChildren
                  .Where(r => r.GetFirstChild<Graphic>() != null).Select(d => d.GetFirstChild<Graphic>())
                  .Where(r => r.GetFirstChild<GraphicData>() != null).Select(r => r.GetFirstChild<GraphicData>())
                  .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>() != null)
                  .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>())
                  .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>() != null)
                  .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>())
                  .Where(r => r.GetFirstChild<Transform2D>() != null).Select(r => r.GetFirstChild<Transform2D>())
                  .Where(r => r.GetFirstChild<Extents>() != null).Select(r => r.GetFirstChild<Extents>());
      
              // Modify all images in Extents to the desired size here, to be stretched out on available page width
              foreach (var extents in extentsEnumerable)
              {
                  // Set Image Size: We calculate Aspect Ratio of the image and then calculate the width and update the height as per aspect ratio
                  var inlineElement = extents;
      
                  UpdateExtent(inlineElement);
              }
      

Update Extent 方法更新范围值:

    private static void UpdateExtent(dynamic inlineElement)
    {
        // Read Default Cx and Cy Values provided in Emu
        var extentCx = inlineElement.Cx;
        var extentCy = inlineElement.Cy;

        // Aspect ratio used to set image height after calculation of width
        double aspectRatioOfImage = (double)extentCy / extentCx;

        // We know 15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel, and we convert document size to pixel and then to EMU
        // For Default Values Available page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu
        double newExtentCx = EmuPerPixel * ((PageWidth - PageMarginLeft - PageMarginRight) / DocumentSizePerPixel);
        // Maintain the Aspect Ratio for height
        double newExtentCy = aspectRatioOfImage * newExtentCx;

        // Update the values
        inlineElement.Cx = (long)Math.Round(newExtentCx);
        inlineElement.Cy = (long)Math.Round(newExtentCy);
    } 

完整程序:

namespace Solutions
{
    using System;
    using System.Linq;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Drawing;
    using DocumentFormat.OpenXml.Drawing.Wordprocessing;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using HtmlToOpenXml;

    using Paragraph = DocumentFormat.OpenXml.Wordprocessing.Paragraph;

    public class WordProcessorClass
    {
        const string Html = "<p>SomeText<img src=\"data:image/png;base64,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\" alt=\"Screenshot_3\" />moretext</p>";

        // Define Constants for Page Width and Page Margin
        private const int PageWidth = 17000;
        private const int PageHeight = 10000;
        private const int PageMarginLeft = 1000;
        private const int PageMarginRight = 1000;
        private const int PageMarginTop = 1000;
        private const int PageMarginBottom = 1000;
        private const double DocumentSizePerPixel = 15;
        private const double EmuPerPixel = 9525;

        public static void Main1()
        {
            string fileName = @"f:\myDoc.docx";

            using (WordprocessingDocument document = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
            {
                document.AddMainDocumentPart();
                document.MainDocumentPart.Document = new Document(new Body());

                HtmlConverter converter = new HtmlConverter(document.MainDocumentPart);
                var compositeElements = converter.Parse(Html);
                var p = compositeElements[0] as Paragraph;


                // Set Page Size and Page Margin so that we can place the image as desired.
                // Available Width = PageWidth - PageMarginLeft - PageMarginRight (= 17000 - 1000 - 1000 = 15000 for default values)
                var sectionProperties = new SectionProperties();
                sectionProperties.AppendChild(new PageSize { Width = PageWidth, Height = PageHeight });
                sectionProperties.AppendChild(new PageMargin { Left = PageMarginLeft, Bottom = PageMarginBottom, Top = PageMarginTop, Right = PageMarginRight });
                document.MainDocumentPart.Document.Body.AppendChild(sectionProperties);

                if (p != null)
                {
                    // Search for Extents used by the word present in Drawing > Inline > Extent
                    var inlineEnumerable = p.ChildElements.Where(e => e is DocumentFormat.OpenXml.Wordprocessing.Run)
                        .Where(r => r.GetFirstChild<Drawing>() != null).Select(r => r.GetFirstChild<Drawing>())
                        .Where(r => r.GetFirstChild<Inline>() != null).Select(r => r.GetFirstChild<Inline>());

                    // Update Visible Extent
                    var inlineChildren = inlineEnumerable as Inline[] ?? inlineEnumerable.ToArray();
                    foreach (var inlineChild in inlineChildren)
                    {
                        var inlineElement = inlineChild.Extent;
                        UpdateExtent(inlineElement);
                    }

                    // Search for Extents used by the word present in Drawing > Inline > Graphic > GraphicData > Picture > ShapeProperties > Transform2D > Extents
                    var extentsEnumerable = inlineChildren
                        .Where(r => r.GetFirstChild<Graphic>() != null).Select(d => d.GetFirstChild<Graphic>())
                        .Where(r => r.GetFirstChild<GraphicData>() != null).Select(r => r.GetFirstChild<GraphicData>())
                        .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>() != null)
                        .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.Picture>())
                        .Where(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>() != null)
                        .Select(r => r.GetFirstChild<DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties>())
                        .Where(r => r.GetFirstChild<Transform2D>() != null).Select(r => r.GetFirstChild<Transform2D>())
                        .Where(r => r.GetFirstChild<Extents>() != null).Select(r => r.GetFirstChild<Extents>());

                    // Modify all images in Extents to the desired size here, to be stretched out on available page width
                    foreach (var extents in extentsEnumerable)
                    {
                        // Set Image Size: We calculate Aspect Ratio of the image and then calculate the width and update the height as per aspect ratio
                        var inlineElement = extents;

                        UpdateExtent(inlineElement);
                    }
                }

                document.MainDocumentPart.Document.Body.Append(compositeElements);
            }
        }

        private static void UpdateExtent(dynamic inlineElement)
        {
            // Read Default Cx and Cy Values provided in Emu
            var extentCx = inlineElement.Cx;
            var extentCy = inlineElement.Cy;

            // Aspect ratio used to set image height after calculation of width
            double aspectRatioOfImage = (double)extentCy / extentCx;

            // We know 15 width of Page = 1 width of image in pixel = 9525 EMUs per pixel, and we convert document size to pixel and then to EMU
            // For Default Values Available page width = 15000 page width = 15000/ 15 pixels = 1000 pixels = 1000 * 9525 Emu = 9525000 Emu
            double newExtentCx = EmuPerPixel * ((PageWidth - PageMarginLeft - PageMarginRight) / DocumentSizePerPixel);
            // Maintain the Aspect Ratio for height
            double newExtentCy = aspectRatioOfImage * newExtentCx;

            // Update the values
            inlineElement.Cx = (long)Math.Round(newExtentCx);
            inlineElement.Cy = (long)Math.Round(newExtentCy);
        }
    }
}

输出:

自由办公室

Libre Office Document

谷歌文档

Google Document

引用:Output Document

关于c# - OpenXml 强制图像适合父容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50645759/

相关文章:

c# - ASPNET : Make sure that the class defined in this code file matches the 'inherits' attribute

c# - 计算/将 Excel 列宽转换为 Word 表列宽的公式/算法

database - 可以从数据库中获取信息的 Word/Excel 模板

.net - 使用.NET自动更新Word文档的目录部分?

c# - 删除 Excel 图表

c# - IQueryable 和 Queryable 之间的区别

c# - MVC 4.5.2 Response.WriteFile 大于 2gb

Word 2016 中的正则表达式

c# - 使用 OpenXML 合并 PowerPoint 幻灯片

c# - OpenXML 从 Word 中删除项目符号或数字