将Drawing.Image插入WordprocessingDocument主体

时间:2014-06-25 14:56:00

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

我有一个代码,我用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]标签 - 这是一个非常简单的解决方案。

BUT。如果我可以避免保存不必要的文件并且不得不依赖链接(这不是图像消失的最稳定的话),我宁愿这样做。

但是为了减少追逐,这是我到目前为止使用的代码:

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,我更喜欢这样做而不使用html img link to url。

要更新此内容:

票据答案,基本上是MSDN链接,显示如何插入效果很好的图像。 然而它错过了一些部分,如:

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

  2. 我宁愿不用本地inoder保存我的Drawing.Image来使用'FileStream(fileName, FileMode.Open))',有没有办法让我直接使用Drawing.Image执行此操作而不先保存它? (不重要但更喜欢这个)

  3. 使用MSDN示例我的图像分辨率和宽高比发生了变化,原因是什么? (现在不是很重要,但可能会在将来)

2 个答案:

答案 0 :(得分:3)

单词doc只不过是一堆XML文件。获取现有的.docx文件,将其重命名为.zip,然后查看内部。您将看到图像的存储方式,主要文档,定义的样式以及各种其他好东西。要添加图像,您需要找到&#34; Part&#34;您要添加图像的文档的位置。一旦找到,就很容易添加图像&#34; part&#34;致父母&#34;部分&#34;。

以下是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)));
}

这里的关键部分是知道如何找到父母的身份&#34;部分&#34;您要插入图像的位置。

答案 1 :(得分:0)

您是否考虑使用图片内容控件而不是[IMAGE]文字?您可以将它放在Word文件中的任何位置,给它一个&#34;标记&#34;识别它然后在代码中访问它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图像的麻烦。只需将现有的Blip Embed属性替换为新添加的图片ID即可。