【问题标题】:Insert Drawing.Image into WordprocessingDocument body将 Drawing.Image 插入 WordprocessingDocument 正文
【发布时间】:2014-06-25 14:55:59
【问题描述】:

我有一个代码,我使用 System.IO 读取字节数组格式的 docx 文档。 后来我制作了一个 docx 字节数组的流,并使用 WordprocessingDocument 来编辑 docx 流。

我在 docx 流文本中编辑/替换使用硬括号和自定义插入文本的标签。

最后,我将编辑后的 ​​docx 流转换为新的字节数组,稍后我将其用于其他内容(例如使用字节数组创建 PDF),但之后发生的事情现在并不重要。

现在的问题是,就像我替换文本中的某些标签一样,我可以插入图像吗?最好使用 Drawing.Image,因为这就是我现在的图像格式。

澄清几点:

我知道我可以使用 Drawing.Image.Save() 保存图像,然后使用 <img href="our image url that we just saved down.png"> 编辑 [IMAGE] 标记 - 这是一个非常简单的解决方案。

但是。如果我可以避免保存不必要的文件并不得不依赖链接(如果图像消失,这不是最稳定的),我会更喜欢

但是为了避免追逐,这是我目前使用的代码:

Image image = myImage;
byte[] byteArray = System.IO.File.ReadAllBytes(fullFileNamePath); //Get our docx document as Byte Array
byte[] byteArrayAfterReading;
using (MemoryStream stream = new MemoryStream())
{
    stream.Write(byteArray, 0, (int)byteArray.Length); //Create a stream of the docx byte array document
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(stream, true))
    {
       Body body = wordDoc.MainDocumentPart.Document.Body;
       foreach (var text in body.Descendants<Text>())
       {
           if (text.Text.Contains("[TEST]"))
           {
               text.Text = text.Text.Replace("[TEST]", "Test text here!");
           }
           if (text.Text.Contains("[IMAGE]"))
           {
               text.Text = text.Text.Replace("[IMAGE]", "Image here!"); 
               //Here I should somehowly insert my Drawing.Image
               //I could do this here but would prefer to not 
               //text.Text = text.Text.Replace("[IMAGE]", "<img href='imgurl.png'>"); 
           }
       }
    }
byteArrayAfterReading = stream.ToArray();
}
//After here I do my convert byte array to PDF and save it

这一切都很好。我只是想找出一种在其中插入图像的好方法。

tl;博士。

我有一个 Drawing.Image,我想以某个字符串插入到我的 wordprocessingDocument.Document.Body 中,我希望不使用指向 url 的 html img 链接来执行此操作。

要更新此内容:

Bills answer,基本上是一个 MSDN 链接,显示如何插入效果很好的图像。 但是它遗漏了一些部分,例如:

  1. 如何将图像放置在某个位置,在本例中是我的 [IMAGE] 标签? (最重要的)

  2. 我宁愿不必在本地保存我的 Drawing.Image 以使用 'FileStream(fileName, FileMode.Open))' 即有没有办法让我直接使用我的 Drawing.Image 而不先保存它? (不重要但更喜欢这个)

  3. 在 MSDN 示例中,我的图像分辨率和纵横比发生了变化,有什么原因吗? (现在不那么重要,但将来可能会)

【问题讨论】:

  • 应该有办法的。让我看看图片是如何存储在 docx 中的
  • @henrikp - 你是如何实现这一行的? //在这里我将字节数组转换为PDF并保存

标签: c# .net openxml system.drawing memorystream


【解决方案1】:

word doc 只不过是一堆放在一起的 XML 文件。获取现有的 .docx 文件,将其重命名为 .zip,然后查看内部。您将看到图像是如何存储的、主文档、定义的样式以及各种其他好东西。要添加图像,您需要找到要添加图像的文档的“部分”。找到后,很容易将图像“part”添加到父“part”。

这是来自 MSDN 的快速操作方法: http://msdn.microsoft.com/en-us/library/office/bb497430(v=office.15).aspx

MainDocumentPart mainPart = wordprocessingDocument.MainDocumentPart;
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    imagePart.FeedData(stream);
}
AddImageToBody(wordprocessingDocument, mainPart.GetIdOfPart(imagePart));

AddImageToBody 看起来像这样:

private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId)
{
    // Define the reference of the image.
    var element =
         new Drawing(
             new DW.Inline(
                 new DW.Extent() { Cx = 990000L, Cy = 792000L },
                 new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, 
                     RightEdge = 0L, BottomEdge = 0L },
                 new DW.DocProperties() { Id = (UInt32Value)1U, 
                     Name = "Picture 1" },
                 new DW.NonVisualGraphicFrameDrawingProperties(
                     new A.GraphicFrameLocks() { NoChangeAspect = true }),
                 new A.Graphic(
                     new A.GraphicData(
                         new PIC.Picture(
                             new PIC.NonVisualPictureProperties(
                                 new PIC.NonVisualDrawingProperties() 
                                    { Id = (UInt32Value)0U, 
                                        Name = "New Bitmap Image.jpg" },
                                 new PIC.NonVisualPictureDrawingProperties()),
                             new PIC.BlipFill(
                                 new A.Blip(
                                     new A.BlipExtensionList(
                                         new A.BlipExtension() 
                                            { Uri = 
                                                "{28A0092B-C50C-407E-A947-70E740481C1C}" })
                                 ) 
                                 { Embed = relationshipId, 
                                     CompressionState = 
                                     A.BlipCompressionValues.Print },
                                 new A.Stretch(
                                     new A.FillRectangle())),
                             new PIC.ShapeProperties(
                                 new A.Transform2D(
                                     new A.Offset() { X = 0L, Y = 0L },
                                     new A.Extents() { Cx = 990000L, Cy = 792000L }),
                                 new A.PresetGeometry(
                                     new A.AdjustValueList()
                                 ) { Preset = A.ShapeTypeValues.Rectangle }))
                     ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
             ) { DistanceFromTop = (UInt32Value)0U, 
                 DistanceFromBottom = (UInt32Value)0U, 
                 DistanceFromLeft = (UInt32Value)0U, 
                 DistanceFromRight = (UInt32Value)0U, EditId = "50D07946" });

   // Append the reference to body, the element should be in a Run.
   wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph(new Run(element)));
}

这里的关键部分是知道如何找到要插入图像的父“部分”的 ID。

【讨论】:

  • 我没有下载图片,只是一个 Drawing.Image,它如何替换标签?
  • 如果我使用提供的代码下载的图像,它会破坏图像的高度/宽度和纵横比。
  • 将该图像转换为内存流,并将其输入示例中的 .FeedData 方法。
【解决方案2】:

您是否考虑过使用图片内容控件而不是 [IMAGE] 文本?您可以将它放在 Word 文件中的任何位置,给它一个“标签”来识别它,然后在代码中访问它的 SdtContent 并根据需要进行操作。

您仍然需要使用以下方法将新的替换图像添加到 Word 文档中:

MainDocumentPart mainPart = wordprocessingDocument.MainDocumentPart;
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    imagePart.FeedData(stream);
}

就像比尔的回答一样,但您不需要经历创建 Drawing.Image 图像的麻烦。只需将现有的BlipEmbed 属性替换为新添加的图像的id。

【讨论】:

    猜你喜欢
    • 2017-03-03
    • 2011-09-29
    • 1970-01-01
    • 2011-03-29
    • 2023-03-25
    • 2012-04-22
    • 2012-02-07
    • 2013-06-24
    • 1970-01-01
    相关资源
    最近更新 更多