I am hoping that someone can assist with this issue. I am using OpenXMl to search and replace for text in the header, body and footer of a word document using Open XML. The text is working fine. But the image is not replacing as I would expect it to. The image (#"C:\temp\pic\Logo.gif") does exist at the source. But never shows up in the word document correctly. You can see in the region below (#region "Modify Header Logo")
Can anyone assist? Thank you!
Word Error
public void SearchAndReplace(string templateFileNameTemplate, string targetFileName, ProjectModel project)
{
//copy template file
if (File.Exists(targetFileName) == true)
{
File.Delete(targetFileName);
}
File.Copy(templateFileNameTemplate, targetFileName);
string searchText = "", replaceText = "", headerLogo = "", headerText = "";
bool replace = false;
//open file
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(targetFileName, true))
{
//Gets all the headers
foreach (var headerPart in wordDoc.MainDocumentPart.HeaderParts)
{
//Gets the text in headers
foreach (var currentText in headerPart.RootElement.Descendants<Text>())
{
replace = false;
switch (currentText.Text)
{
case "<COMPANY NAME>":
replace = true;
replaceText = project.ClientName;
searchText = currentText.Text;
break;
**case "<INSERT YOUR LOGO HERE>":
headerLogo = #"C:\temp\pic\Logo.gif";//project.ClientLogo;**
headerText = currentText.Text;
break;
case "<ISSUE DATE>":
replace = true;
replaceText = project.AssignedDate.ToShortDateString();
searchText = currentText.Text;
break;
case "<REVIEW DATE>":
replace = true;
replaceText = project.ClientDueDate.ToShortDateString();
searchText = currentText.Text;
break;
default:
break;
}
if(searchText.Length>0 && replace==true)
currentText.Text = currentText.Text.Replace(searchText, replaceText);
}
}
//Gets all the footers
foreach (var footerPart in wordDoc.MainDocumentPart.FooterParts)
{
//Gets the text in headers
foreach (var currentText in footerPart.RootElement.Descendants<Text>())
{
replace = false;
switch (currentText.Text)
{
case "<COMPANY NAME>":
replace = true;
replaceText = project.ClientName;
searchText = currentText.Text;
break;
default:
break;
}
if (searchText.Length > 0 && replace == true)
currentText.Text = currentText.Text.Replace(searchText, replaceText);
}
}
#region "Modify Header Logo"
if(headerLogo != string.Empty)
{
ImagePart imagePart = wordDoc.MainDocumentPart.AddImagePart(ImagePartType.Png);
using (FileStream stream = new FileStream(headerLogo, FileMode.Open))
{
imagePart.FeedData(stream);
}
searchText = headerText;
Text textPlaceHolder = null;
// Insert image (the image created with your function) after text place holder.
// Search for text holder
//Gets all the headers
foreach (var headerPart in wordDoc.MainDocumentPart.HeaderParts)
{
//Gets the text in headers
foreach (var currentText in headerPart.RootElement.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>())
{
textPlaceHolder = headerPart.RootElement.Descendants<Text>()
.Where((x) => x.Text == searchText).First();
}
}
if (textPlaceHolder != null)
{
var parent = textPlaceHolder.Parent;
if (parent is Run) // Parent should be a run element.
{
//add image
Drawing imageElement = GetImageElement(
wordDoc.MainDocumentPart.GetIdOfPart(imagePart),
headerLogo,
"my image",
475,
245);
// Insert image (the image created with your function) after text place holder.
textPlaceHolder.Parent.InsertAfter<Drawing>(imageElement, textPlaceHolder);
// Remove text place holder.
textPlaceHolder.Remove();
}
}
}
#endregion
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("<COMPANY NAME>");
docText = regexText.Replace(docText, project.ClientName);
//regexText = new Regex("<COMPANY NAME>");
//docText = regexText.Replace(docText, project.ClientName);
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
//wordDoc.SaveAs(targetFileName).Close();
}
}
private static Drawing GetImageElement(
string imagePartId,
string fileName,
string pictureName,
double width,
double height)
{
double englishMetricUnitsPerInch = 914400;
double pixelsPerInch = 96;
//calculate size in emu
double emuWidth = width * englishMetricUnitsPerInch / pixelsPerInch;
double emuHeight = height * englishMetricUnitsPerInch / pixelsPerInch;
var element = new Drawing(
new A.Wordprocessing.Inline(
new A.Wordprocessing.Extent { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight },
new A.Wordprocessing.EffectExtent { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
new A.Wordprocessing.DocProperties { Id = (UInt32Value)1U, Name = pictureName },
new A.Wordprocessing.NonVisualGraphicFrameDrawingProperties(
new A.GraphicFrameLocks { NoChangeAspect = true }),
new A.Graphic(
new A.GraphicData(
new A.Pictures.Picture(
new A.Pictures.NonVisualPictureProperties(
new A.Pictures.NonVisualDrawingProperties { Id = (UInt32Value)0U, Name = fileName },
new A.Pictures.NonVisualPictureDrawingProperties()),
new A.Pictures.BlipFill(
new A.Blip(
new A.BlipExtensionList(
new A.BlipExtension { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" }))
{
Embed = imagePartId,
CompressionState = A.BlipCompressionValues.Print
},
new A.Stretch(new A.FillRectangle())),
new A.Pictures.ShapeProperties(
new A.Transform2D(
new A.Offset { X = 0L, Y = 0L },
new A.Extents { Cx = (Int64Value)emuWidth, Cy = (Int64Value)emuHeight }),
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"
});
return element;
}
Firstly, here's the markup for an image (Picture.png) that I manually inserted in a Word document. Did you check the markup created by your code against markup created by Microsoft Word when inserting the same image manually? This often helps spot errors in the markup (not always, though, because there are multiple "ways to Rome" and the same thing can often be expressed in multiple ways). You could use the Open XML Productivity Tool to compare the two documents, for example, and look at the differences in markup and the code required to create the correct markup.
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0" wp14:anchorId="787F9556" wp14:editId="6F9F029A">
<wp:extent cx="4026107" cy="4019757"/>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr id="2" name="Picture 2" descr="A close up of a sign
Description automatically generated"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="2" name="Picture.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId1">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="4026107" cy="4019757"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
Secondly, the following code does not make a lot of sense, because you don't need the foreach loop. That loop takes all w:t descendants of w:hdr but never uses currentText in the body of the loop.
foreach (var currentText in headerPart.RootElement.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>())
{
textPlaceHolder = headerPart.RootElement.Descendants<Text>()
.Where((x) => x.Text == searchText).First();
}
The body of the loop is sufficient. I'd just use FirstOrDefault and check for null, unless you are 100% sure that the text will exist in all (!) headers.
Related
I have a method that replaces the tags in the document specific text. How do I replace the label picture?
Here is a piece of code that looks for a cell with the text 'PersonMainPhoto' inside a table. The tabel-cell is cleared, and an image is inserted. Hopefully this can guide you in the right direction.
Inserting an image is a two part process:
Add image part to the document
Insert a reference to the image inside the body text - with all kinds of details regarding scaling, positioning etc.
The code for inserting the reference is taken from the brilliant OpenXML SDK documentation: https://msdn.microsoft.com/en-us/library/office/bb497430.aspx
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
string file = #"c:\temp\mydoc.docx";
string imageFile = #"c:\temp\myimage.jpg";
string labelText = "PersonMainPhoto";
using (var document = WordprocessingDocument.Open(file, isEditable: true))
{
var mainPart = document.MainDocumentPart;
var table = mainPart.Document.Body.Descendants<Table>().First();
var pictureCell = table.Descendants<TableCell>().First(c => c.InnerText == labelText);
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(imageFile, FileMode.Open))
{
imagePart.FeedData(stream);
}
pictureCell.RemoveAllChildren();
AddImageToCell(pictureCell, mainPart.GetIdOfPart(imagePart));
mainPart.Document.Save();
}
}
private static void AddImageToCell(TableCell cell, string relationshipId)
{
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
});
cell.Append(new Paragraph(new Run(element)));
}
}
}
how do the picture fit, just into tablecell!??
not to fix it .
Cx = 990000L, Cy = 792000L
like this?
TableCellProperties tableCellProperties1 = VARIABLE.GetFirstChild<TableCellProperties>();
TableCellWidth tableCellWidth1 = tableCellProperties1.GetFirstChild<TableCellWidth>();
int _width = Int32.Parse(tableCellWidth1.Width);
TableRowProperties tableRowProperties1 =
VARIABLE.Parent.GetFirstChild<TableRowProperties>();
TableRowHeight tableRowHeight1 =
tableRowProperties1.GetFirstChild<TableRowHeight>();
int _height = Int32.Parse(tableRowHeight1.Val);
document.MainDocumentPart.Document.Save();
I am using Office Open XML and I have to add images at a specific points. On the document I have a 'tag' so I can locate it just fine. However, when I add more than one image, it corrupts the file.
Here's my code: (Modified from https://msdn.microsoft.com/en-us/library/office/bb497430.aspx)
Using:
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
My Main:
private const string Loc = #"D:\Documents\2-Mass Output.docx";
static void Main(string[] args)
{
var images = new[]
{
#"D:\Documents\NPL.bmp",
#"D:\Documents\NVT.bmp",
#"D:\Documents\MPL.bmp",
#"D:\Documents\MVT.bmp"
};
var tags = new[]
{
"NormalGraph1",
"NormalGraph2",
"MisGraph1",
"MisGraph2"
};
InsertPicture(Loc, images, tags);
}
Here are the methods:
/// <summary>
/// Inserts a picture in a paragraph with a specific text
/// </summary>
/// <param name="document">Where the file is located</param>
/// <param name="fileName">Name of the image file</param>
/// <param name="tag">Insert Image in the first paragraph that contains this text</param>
public static void InsertPicture(string document, string[] fileName, string[] tag)
{
using (var wordprocessingDocument = WordprocessingDocument.Open(document, true))
{
var mainPart = wordprocessingDocument.MainDocumentPart;
for (var i = 0; i < fileName.Length; i++)
{
var imagePart = mainPart.AddImagePart(ImagePartType.Bmp);
using (var stream = new FileStream(fileName[i], FileMode.Open))
{
imagePart.FeedData(stream);
}
AddImageToBody(wordprocessingDocument, mainPart.GetIdOfPart(imagePart), tag[i]);
}
}
}
private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId, string tag)
{
// Define the reference of the image.
var element =
new Drawing(
new DW.Inline(
new DW.Extent { Cx = 5d.Inches(), Cy = 2.66.Inches() }, // Width and Height of the image in inches. 1" = 1000000L
new DW.EffectExtent
{
LeftEdge = 0L,
TopEdge = 0L,
RightEdge = 0L,
BottomEdge = 0L
},
new DW.DocProperties
{
Id = 1U,
Name = tag // Make sure all of the images have a different name
},
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 = $"{tag}.bmp" // Make sure all of the images have a different name
},
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 = 5d.Inches(), Cy = 2.66.Inches() }), // Width and Height of the image in inches. 1" = 1000000L
new A.PresetGeometry(
new A.AdjustValueList()
)
{ Preset = A.ShapeTypeValues.Rectangle }))
)
{ Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
)
{
DistanceFromTop = 0U,
DistanceFromBottom = 0U,
DistanceFromLeft = 0U,
DistanceFromRight = 0U,
EditId = "50D07946"
});
// Append the reference to the specific paragraph that contains the 'tag'.
wordDoc.MainDocumentPart.Document.Body.Elements<Paragraph>().FirstOrDefault(f => f.InnerText.Contains(tag))?.AppendChild(new Paragraph(new Run(element)));
}
Function for converting an inch into an inch according to Word:
private static long Inches(this double size)
{
return (long) (size*1000000);
}
EDIT: Here are the contents of the header1.xml. They are the same before and after adding the images.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:hdr xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14"><w:p w:rsidR="007D4EA8" w:rsidRPr="00E6041C" w:rsidRDefault="00292B4C" w:rsidP="00292B4C"><w:pPr><w:spacing w:after="0" w:line="240" w:lineRule="auto"/><w:rPr><w:sz w:val="24"/></w:rPr></w:pPr><w:r w:rsidRPr="00E6041C"><w:rPr><w:noProof/><w:sz w:val="28"/></w:rPr><w:drawing><wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251658240" behindDoc="1" locked="0" layoutInCell="1" allowOverlap="1" wp14:anchorId="2F59D91E" wp14:editId="24EB15EA"><wp:simplePos x="0" y="0"/><wp:positionH relativeFrom="page"><wp:align>right</wp:align></wp:positionH><wp:positionV relativeFrom="paragraph"><wp:posOffset>-157972</wp:posOffset></wp:positionV><wp:extent cx="7792085" cy="661254"/><wp:effectExtent l="0" t="0" r="0" b="5715"/><wp:wrapNone/><wp:docPr id="1" name="Picture 1"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/></wp:cNvGraphicFramePr><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="0" name="Picture 1" descr="T:\Reich USA Commercial\Logo\Logos - US\Reich USA Letterhead.png"/><pic:cNvPicPr><a:picLocks noChangeAspect="1" noChangeArrowheads="1"/></pic:cNvPicPr></pic:nvPicPr><pic:blipFill><a:blip r:embed="rId1" cstate="print"><a:extLst><a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"><a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/></a:ext></a:extLst></a:blip><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr bwMode="auto"><a:xfrm><a:off x="0" y="0"/><a:ext cx="7792085" cy="661254"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom><a:noFill/><a:ln><a:noFill/></a:ln><a:effectLst/><a:extLst><a:ext uri="{53640926-AAD7-44D8-BBD7-CCE9431645EC}"><a14:shadowObscured xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"/></a:ext></a:extLst></pic:spPr></pic:pic></a:graphicData></a:graphic><wp14:sizeRelH relativeFrom="margin"><wp14:pctWidth>0</wp14:pctWidth></wp14:sizeRelH><wp14:sizeRelV relativeFrom="margin"><wp14:pctHeight>0</wp14:pctHeight></wp14:sizeRelV></wp:anchor></w:drawing></w:r>
<w:r w:rsidRPr="00E6041C"><w:rPr><w:sz w:val="28"/></w:rPr><w:t>TV</w:t></w:r>
<w:r w:rsidR="007843C2"><w:rPr><w:sz w:val="28"/></w:rPr><w:t>A</w:t></w:r>
<w:r w:rsidRPr="00E6041C"><w:rPr><w:sz w:val="28"/></w:rPr><w:t xml:space="preserve"> Number: </w:t></w:r>
<w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="28"/></w:rPr><w:t><</w:t></w:r>
<w:proofErr w:type="spellStart"/><w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="28"/></w:rPr><w:t>TVCNum</w:t></w:r>
<w:proofErr w:type="spellEnd"/><w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="28"/></w:rPr><w:t>></w:t></w:r>
</w:p><w:p w:rsidR="00940058" w:rsidRDefault="00940058"><w:pPr><w:pStyle w:val="Header"/><w:rPr><w:sz w:val="16"/></w:rPr></w:pPr></w:p><w:p w:rsidR="00BB3259" w:rsidRPr="00940058" w:rsidRDefault="00292B4C"><w:pPr><w:pStyle w:val="Header"/><w:rPr><w:sz w:val="16"/></w:rPr></w:pPr><w:r w:rsidRPr="00926942"><w:rPr><w:sz w:val="16"/></w:rPr><w:t xml:space="preserve">Torsional Vibration </w:t></w:r>
<w:r w:rsidR="007843C2"><w:rPr><w:sz w:val="16"/></w:rPr><w:t>Analysis</w:t></w:r>
</w:p><w:p w:rsidR="00BB3259" w:rsidRPr="0037430D" w:rsidRDefault="00BB3259" w:rsidP="00F909DF"><w:pPr><w:tabs><w:tab w:val="center" w:pos="4680"/><w:tab w:val="right" w:pos="9360"/></w:tabs><w:spacing w:after="0" w:line="240" w:lineRule="auto"/><w:rPr><w:sz w:val="28"/></w:rPr></w:pPr><w:r w:rsidRPr="00292B4C"><w:rPr><w:sz w:val="28"/></w:rPr><w:t xml:space="preserve">Customer: </w:t></w:r>
<w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="28"/></w:rPr><w:t><Customer></w:t></w:r>
<w:r w:rsidR="00F909DF"><w:rPr><w:sz w:val="28"/></w:rPr><w:tab/></w:r>
<w:r w:rsidR="00F909DF"><w:rPr><w:sz w:val="28"/></w:rPr><w:tab/></w:r>
<w:r w:rsidR="00F909DF" w:rsidRPr="0037430D"><w:rPr><w:sz w:val="20"/></w:rPr><w:t xml:space="preserve">Performed </w:t></w:r>
<w:proofErr w:type="gramStart"/><w:r w:rsidR="00F909DF" w:rsidRPr="0037430D"><w:rPr><w:sz w:val="20"/></w:rPr><w:t>By</w:t></w:r>
<w:proofErr w:type="gramEnd"/><w:r w:rsidR="00F909DF" w:rsidRPr="0037430D"><w:rPr><w:sz w:val="20"/></w:rPr><w:t xml:space="preserve">: </w:t></w:r>
<w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="20"/></w:rPr><w:t><User></w:t></w:r>
</w:p><w:p w:rsidR="00AF585E" w:rsidRPr="00BB3259" w:rsidRDefault="00645FF6" w:rsidP="00F909DF"><w:pPr><w:tabs><w:tab w:val="right" w:pos="9360"/></w:tabs><w:spacing w:after="0" w:line="240" w:lineRule="auto"/></w:pPr><w:r><w:rPr><w:noProof/><w:sz w:val="28"/></w:rPr><mc:AlternateContent><mc:Choice Requires="wps"><w:drawing><wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251660288" behindDoc="0" locked="0" layoutInCell="1" allowOverlap="1" wp14:anchorId="26F2E2C8" wp14:editId="4EF2E467"><wp:simplePos x="0" y="0"/><wp:positionH relativeFrom="page"><wp:posOffset>-74874</wp:posOffset></wp:positionH><wp:positionV relativeFrom="paragraph"><wp:posOffset>173822</wp:posOffset></wp:positionV><wp:extent cx="7950241" cy="0"/><wp:effectExtent l="38100" t="19050" r="69850" b="114300"/><wp:wrapNone/><wp:docPr id="3" name="Straight Connector 3"/><wp:cNvGraphicFramePr/><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"><wps:wsp><wps:cNvCnPr/><wps:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="7950241" cy="0"/></a:xfrm><a:prstGeom prst="line"><a:avLst/></a:prstGeom><a:ln w="12700"><a:solidFill><a:srgbClr val="335BA3"/></a:solidFill></a:ln><a:effectLst><a:outerShdw blurRad="50800" dist="38100" dir="5400000" algn="t" rotWithShape="0"><a:prstClr val="black"><a:alpha val="40000"/></a:prstClr></a:outerShdw></a:effectLst></wps:spPr><wps:style><a:lnRef idx="3"><a:schemeClr val="accent5"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent5"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent5"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></wps:style><wps:bodyPr/></wps:wsp></a:graphicData></a:graphic><wp14:sizeRelH relativeFrom="margin"><wp14:pctWidth>0</wp14:pctWidth></wp14:sizeRelH><wp14:sizeRelV relativeFrom="margin"><wp14:pctHeight>0</wp14:pctHeight></wp14:sizeRelV></wp:anchor></w:drawing></mc:Choice><mc:Fallback><w:pict><v:line w14:anchorId="04485610" id="Straight Connector 3" o:spid="_x0000_s1026" style="position:absolute;z-index:251660288;visibility:visible;mso-wrap-style:square;mso-width-percent:0;mso-height-percent:0;mso-wrap-distance-left:9pt;mso-wrap-distance-top:0;mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;mso-position-horizontal-relative:page;mso-position-vertical:absolute;mso-position-vertical-relative:text;mso-width-percent:0;mso-height-percent:0;mso-width-relative:margin;mso-height-relative:margin" from="-5.9pt,13.7pt" to="620.1pt,13.7pt" o:gfxdata="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
" strokecolor="#335ba3" strokeweight="1pt"><v:stroke joinstyle="miter"/><v:shadow on="t" color="black" opacity="26214f" origin=",-.5" offset="0,3pt"/><w10:wrap anchorx="page"/></v:line></w:pict></mc:Fallback></mc:AlternateContent></w:r>
<w:r w:rsidR="008453E8"><w:t xml:space="preserve">Customer Ref. – No. </w:t></w:r>
<w:r w:rsidR="00BB3259"><w:t xml:space="preserve"> </w:t></w:r>
<w:r w:rsidR="00F972A0" w:rsidRPr="00BB1CB1"><w:rPr><w:i/></w:rPr><w:t><</w:t></w:r>
<w:proofErr w:type="spellStart"/><w:r w:rsidR="00F972A0" w:rsidRPr="00BB1CB1"><w:rPr><w:i/></w:rPr><w:t>CustRef</w:t></w:r>
<w:proofErr w:type="spellEnd"/><w:r w:rsidR="00F972A0" w:rsidRPr="00BB1CB1"><w:rPr><w:i/></w:rPr><w:t>></w:t></w:r>
<w:r w:rsidR="00F909DF"><w:tab/></w:r>
<w:r w:rsidR="00DE1633"><w:rPr><w:sz w:val="16"/></w:rPr><w:t>Mahwah</w:t></w:r>
<w:r w:rsidR="0029773E"><w:rPr><w:sz w:val="16"/></w:rPr><w:t>,</w:t></w:r>
<w:r w:rsidR="00DE1633"><w:rPr><w:sz w:val="16"/></w:rPr><w:t xml:space="preserve"> NJ</w:t></w:r>
<w:r w:rsidR="00EE3F20" w:rsidRPr="00EE3F20"><w:rPr><w:sz w:val="16"/></w:rPr><w:t xml:space="preserve"> </w:t></w:r>
<w:r w:rsidR="0029773E"><w:rPr><w:sz w:val="16"/></w:rPr><w:t>-</w:t></w:r>
<w:r w:rsidR="00EE3F20" w:rsidRPr="00EE3F20"><w:rPr><w:sz w:val="16"/></w:rPr><w:t xml:space="preserve"> </w:t></w:r>
<w:r w:rsidR="00F972A0"><w:rPr><w:sz w:val="16"/></w:rPr><w:t><Date></w:t></w:r>
<w:r w:rsidR="0037430D" w:rsidRPr="00EE3F20"><w:rPr><w:b/><w:sz w:val="10"/></w:rPr><w:t xml:space="preserve"> </w:t></w:r>
</w:p></w:hdr>
I can see 3 issues with the code you've posted but I'm not sure why you would only see an error if you output more than one image.
The first issue is the Id of the DocProperties. The Id property should be unique amongst all of the DocProperties in the document.
new DW.DocProperties
{
Id = 1U, //this should be unique amongst ALL DocProperties within the document
Name = tag // Make sure all of the images have a different name
},
The second issue is very similar; the Id of each of the NonVisualDrawingProperties should also be unique across each NonVisualDrawingProperties instance.
Note that in both cases you will need these values to be unique from the values that already exist in your header. From the header XML that you posted you can see that you already have instances of those properties:
<wp:docPr id="1" name="NormalGraph2" />
and
<pic:cNvPr id="0" name="NormalGraph2.bmp" />
Finally, the third issue I can see is in the code where you add the element. In that code you are finding the Paragraph that contains the tag and then appending a Paragraph to the existing Paragraph. A Paragraph is not allowed to be a child of another Paragraph. Instead, you should just add the Run to the existing Paragraph like so:
wordDoc.MainDocumentPart.Document.Body.Elements<Paragraph>().FirstOrDefault(f => f.InnerText.Contains(tag))?.AppendChild(new Run(element));
or, if you need the separate paragraphs then add the Paragraph after the tag Paragraph against the same Parent node:
var tagNode = wordDoc.MainDocumentPart.Document.Body.Elements<Paragraph>().FirstOrDefault(f => f.InnerText.Contains(tag));
if (tagNode != null)
{
tagNode.Parent.InsertAfter(new Run(element), tagNode);
}
This is my current solution based on the advice in this thread!
The first method gives me the reference id. This id can be reused if I want to add the image more times, but every image insertion should get a unique ID:
AddImageToBody(_imgKReferenceID, $"imgOK{creditNr}", 60, 60, (UInt32)(counter + 100)
public static string InsertAPicture(MainDocumentPart mainPart, string fileName)
{
try
{
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
imagePart.FeedData(stream);
}
return mainPart.GetIdOfPart(imagePart);
}
catch (Exception ex)
{
Logger.Log.Error(ex);
return "";
}
}
internal static Drawing AddImageToBody(string relationshipId, string name , int w = 60, int h = 60, UInt32 id1=1U, UInt32 id2 = 0U)
{
System.Drawing.Size size = new System.Drawing.Size(w, h);
Int64Value width = size.Width/2 * 9525;
Int64Value height = size.Height/2 * 9525;
var draw = new Drawing(
new DW.Inline(
new DW.Extent() { Cx = width, Cy = height },
new DW.EffectExtent()
{
LeftEdge = 0L,
TopEdge = 0L,
RightEdge = 0L,
BottomEdge = 0L
},
new DW.DocProperties()
{
Id = (UInt32Value)id1,
Name = $"{name}"
},
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)id2,
Name = $"{name}"
},
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 = width, Cy = height }),
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"
});
return draw;
}
I need to take a template Word document with a set of bookmarks, and replace them with images (removing the bookmark itself). The examples of working with bookmarks I've seen are confusing and I'm not sure they apply to using an ImagePart, since it seems that things are different depending on content.
Could someone provide a straightforward example?
You can use the below method ReplaceBookmarksWithImage to replace all the bookmarks with a given image. The word template file path and image file path are parameters. You can extend the code if you need different images for each bookmarks.
private static void ReplaceBookmarksWithImage(string wordDocTempaltePath, string imageFilename)
{
WordprocessingDocument doc = WordprocessingDocument.Open(wordDocTempaltePath, true);
// Read all bookmarks from the word doc
foreach (BookmarkStart bookmarkStart in doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
// insert the image
InsertImageIntoBookmark(doc, bookmarkStart, imageFilename);
// remove the bookmark
bookmarkStart.Remove();
}
doc.Close();
}
public static void InsertImageIntoBookmark(WordprocessingDocument doc, BookmarkStart bookmarkStart, string imageFilename)
{
// Remove anything present inside the bookmark
OpenXmlElement elem = bookmarkStart.NextSibling();
while (elem != null && !(elem is BookmarkEnd))
{
OpenXmlElement nextElem = elem.NextSibling();
elem.Remove();
elem = nextElem;
}
// Create an imagepart
var imagePart = AddImagePart(doc.MainDocumentPart, imageFilename);
// insert the image part after the bookmark start
AddImageToBody(doc.MainDocumentPart.GetIdOfPart(imagePart), bookmarkStart);
}
public static ImagePart AddImagePart(MainDocumentPart mainPart, string imageFilename)
{
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
using (FileStream stream = new FileStream(imageFilename, FileMode.Open))
{
imagePart.FeedData(stream);
}
return imagePart;
}
private static void AddImageToBody(string relationshipId, BookmarkStart bookmarkStart)
{
// 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"
});
// add the image element to body, the element should be in a Run.
bookmarkStart.Parent.InsertAfter<Run>(new Run(element), bookmarkStart);
}
and here are the using statements
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
I'm trying to put in the word bookmark, the image in memory stream instead of image file. In the marker I get an image with an "X".
public static ImagePart AddStreamPart(MainDocumentPart mainPart, Stream ImageSignature)
{
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
imagePart.FeedData(ImageSignature);
return imagePart;
}
--Updated to provide full working class example, with 2 sample documents--
www.sklinar.co.uk/wp-content/uploads/mydoc.docx - Original Document with a INCLUDETEXT instruction to merge in Footer.Docx
www.sklinar.co.uk/wp-content/uploads/footer.docx
I have added a ImagePart to my document as well as using FeedData() to supply it with streamed content.
But all I can get to appear in my document is a red box.
My initial code Creates a Run with a Drawing as it's child:
--For this example, I've used a hard-coded FileStream to weed out dodgy images--
Just to get this working, I am using the same footer each time, and this is currently hard-coded with the correct footer:
runToAmend.InsertAfterSelf(CreateImageRun(sourceDocument,run,target.MainDocumentPart.FooterParts.ElementAt(2)));
The runToAmend is taken from a run in the current document - which holds a field which is then removed and the picture (and other text taken from another document) placed in it's place.
public Run CreateImageRun(WordprocessingDocument sourceDoc, Run sourceRunFromOriginalDocument, FooterPart footerPart)
{
ImageData shape = sourceRun.Descendants<ImageData>().FirstOrDefault();
ImagePart p = sourceDoc.MainDocumentPart.GetPartById(shape.RelationshipId) as ImagePart;
ImagePart newPart = footerPart.AddImagePart(ImagePartType.Jpeg);
using (Stream stream = new FileStream(#"C:\Users\SAS\Desktop\IMG_20130803_104521.jpg",FileMode.Open,FileAccess.Read))
{
stream.Position = 0;
newPart.FeedData(stream);
}
string partId = footerPart.GetIdOfPart(newPart);
Drawing newImage = CreateImage(partId);
return new Run(newImage);
}
Code to Create Drawing
private Drawing CreateImage(string relationshipId)
{
// Define the reference of the image.
return 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"
});
}
The XML produced appears correct, and the image gets added to the /Media/ folder.
<w:r>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0" wp14:editId="50D07946">
<wp:extent cx="990000" cy="792000" />
<wp:effectExtent l="0" t="0" r="0" b="0" />
<wp:docPr id="1" name="Picture 1" />
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" />
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="0" name="New Bitmap Image.jpg" />
<pic:cNvPicPr />
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="Raae77c5adb2e48f3" cstate="print">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}" />
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect />
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0" />
<a:ext cx="990000" cy="792000" />
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst />
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
I've spent about 2 days now searching SO, Google MS's poor docs.
public class WordTest
{
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Vml;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
public void MethodName()
{
WordprocessingDocument mainDoc = WordprocessingDocument.Open("mydoc.docx", true);
foreach (var item in mainDoc.MainDocumentPart.FooterParts)
{
ProcessParaIncludeTextMerge(item, item.Footer.Descendants<Run>(), mainDoc);
item.Footer.Save();
}
mainDoc.MainDocumentPart.Document.Save();
}
private void ProcessParaIncludeTextMerge(OpenXmlPart part, IEnumerable<Run> runs, WordprocessingDocument originalDocument)
{
List<Run> paraRuns = runs.ToList();
int runCount = paraRuns.Count();
for (int i = 0; i < runCount; i++)
{
Run r = paraRuns.ElementAt(i);
// check if this is a simple Merge Field
if (r.HasChildren && r.Descendants<FieldCode>().Any())
{
FieldCode code = r.Descendants<FieldCode>().First();
// we check the first fieldcode is a merge field - but we can't *just* use that one, as for
// some stupid reason, the fieldcodes can be split across runs.... :/
if (code.Text.Trim().IndexOf("INCLUDETEXT", StringComparison.InvariantCultureIgnoreCase) > -1) //this is actually piss-poor, but as a merge field can go across n runs, we simply check for the M and let the other function figure it out..
{
MergeIncludeText(i, paraRuns, originalDocument);
}
}
}
}
public Run CreateImageRun(WordprocessingDocument sourceDoc, Run sourceRun, WordprocessingDocument target, FooterPart footerPart)
{
ImagePart newPart = footerPart.AddImagePart(ImagePartType.Png);
ImageData shape = sourceRun.Descendants<ImageData>().FirstOrDefault();
ImagePart p = sourceDoc.MainDocumentPart.GetPartById(shape.RelationshipId) as ImagePart;
Bitmap image = new Bitmap(p.GetStream());
using (Stream s = p.GetStream())
{
s.Position = 0;
newPart.FeedData(s);
}
string partId = footerPart.GetIdOfPart(newPart);
Drawing newImage = CreateImage(partId);
return new Run(newImage);
}
private Drawing CreateImage(string relationshipId)
{
// Define the reference of the image.
return 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"
});
}
private void ReplaceRunsWithRuns(IEnumerable<Run> fieldRuns, IEnumerable<Run> value, WordprocessingDocument source, WordprocessingDocument target)
{
FooterPart f = target.MainDocumentPart.FooterParts.ElementAt(1);
f.Footer.RemoveAllChildren();
Paragraph p = new Paragraph();
//the run has no value to merge into, remove the field.
if (value != null)
{
foreach (var item in value)
{
if (!item.Descendants<Picture>().Any()) //pictures are processed differently - they're an absolute s**t storm to code...
{
p.Append(item.CloneNode(true));
}
else
{
p.Append(CreateImageRun(source, item, target, f));
}
}
}
else
{
}
f.Footer.Append(p);
}
private void MergeIncludeText(int curRunIdx, List<Run> runs, WordprocessingDocument originalDoc)
{
int startRun = GetBeginRun(runs, curRunIdx);
if (startRun == -1)
{
return;
}
int endRun = GetEndRun(runs, startRun);
if (endRun == -1)
{
return;
}
IEnumerable<Run> fieldRuns = WordMLHelpers.GetRunsBetweenTwoPoints(runs, startRun, endRun);
IEnumerable<FieldCode> fieldCodes = fieldRuns.SelectMany(x => x.Descendants<FieldCode>());
string mergeField = string.Concat(fieldCodes.Select(x => x.Text));
string field = GetIncludeTextFilePath(mergeField);
MemoryStream ms = LoadDocumentStream(field);
WordprocessingDocument includeDoc = LoadDocumentFromStream(ms);
IEnumerable<Run> includedRuns = includeDoc.MainDocumentPart.Document.Descendants<Run>();
ReplaceRunsWithRuns(fieldRuns, includedRuns, includeDoc, originalDoc);
}
private string GetIncludeTextFilePath(string mergeFieldText)
{
int quoteStart = mergeFieldText.IndexOf('"') + 1;
int quoteEnd = mergeFieldText.IndexOf('"', quoteStart);
return mergeFieldText.Substring(quoteStart, quoteEnd - quoteStart);
}
private WordprocessingDocument LoadDocumentFromStream(Stream stream)
{
return WordprocessingDocument.Open(stream, true);
}
#region helpers
public static int GetBeginRun(IEnumerable<Run> runs, int curIdx)
{
for (int i = curIdx; i < runs.Count(); i--)
{
if (i == -1)
{
return -1;
}
Run run = runs.ElementAt(i);
if (run.HasChildren && run.ChildElements.OfType<FieldChar>().Count() > 0
&& (run.ChildElements.OfType<FieldChar>().First().FieldCharType == FieldCharValues.Begin))
{
return i;
}
}
throw new Exception("Begin not found");
}
/// <summary>
/// Get the first End Run in a <see cref="List"/>(<see cref="Run"/>)
/// </summary>
/// <param name="runs">The runs.</param>
/// <param name="curIdx">The cur idx.</param>
/// <returns></returns>
/// <exception cref="System.Exception">End not found</exception>
public static int GetEndRun(IEnumerable<Run> runs, int curIdx)
{
//runs.FirstOrDefault(x => x.HasChildren && x.Descendants<FieldChar>().Count > 0 && (x.Descendants<FieldChar>().First().FieldCharType & FieldCharValues.End) == FieldCharValues.End);
for (int i = curIdx; i < runs.Count(); i++)
{
if (i == -1)
{
return -1;
}
Run run = runs.ElementAt(i);
if (run.HasChildren && run.Descendants<FieldChar>().Any()
&& (run.Descendants<FieldChar>().First().FieldCharType == FieldCharValues.End))
{
return i;
}
}
return -1;
}
public static MemoryStream LoadDocumentStream(string template)
{
using (FileStream fs = File.Open(template, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// first read document in as stream
MemoryStream ms = new MemoryStream();
fs.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
}
#endregion
}
I've analyzed your word document. There are a few issues with your word document:
If I try to open your word document in the MS productivity toolkit I get the error
message "Root element is missing".
If I open your document as a zip file (renaming to mergedfooter.zip) then
in the footer2.xml.rels file the relationship for your image is missing.
I think that's the reason you get the "red box".
To further analyze your problem I need the complete code (how do you get the FooterPart)?
Below you will find an example of how to insert an image into the footer of a word document.
Please note, that the example below assumes that your word document already contains a footer and your footer contains a paragraph element.
using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open("mydoc.docx", true))
{
MainDocumentPart mainPart = wordprocessingDocument.MainDocumentPart;
// Search for your footer part here.
// Just for the sake of simplicity I take the second footer part.
FooterPart fp = mainPart.FooterParts.ToList()[2];
// Create new image part.
ImagePart ip = fp.AddImagePart(ImagePartType.Jpeg);
using (FileStream fs = File.Open("mypicture.jpg", FileMode.Open))
{
ip.FeedData(fs);
}
string relationshipId = fp.GetIdOfPart(ip);
// Create the image element using your function.
Drawing img = CreateImage(relationshipId);
Run r = new Run(img);
Paragraph para = fp.RootElement.Descendants<Paragraph>().FirstOrDefault();
if(para != null)
{
para.Append(r);
}
else
{
Console.WriteLine("paragraph is null...");
}
}
EDIT:
After analyzing your newly provided documents:
The reason the releationship for your image is not saved is
because you do not Dispose() or Close() your word document.
So, just add a using statement:
using (WordprocessingDocument mainDoc = WordprocessingDocument.Open("mydoc.docx", true))
{
foreach (var item in mainDoc.MainDocumentPart.FooterParts)
{
ProcessParaIncludeTextMerge(item, item.Footer.Descendants<Run>(), mainDoc);
item.Footer.Save();
}
mainDoc.MainDocumentPart.Document.Save();
}
Furthermore in your ReplaceRunsWithRuns() method you must use
PIC.Picture to reference the correct Picture class:
foreach (var item in value)
{
if (!item.Descendants<PIC.Picture>().Any())
{
p.Append(item.CloneNode(true));
}
else
{
p.Append(CreateImageRun(source, item, target, f));
}
}
By the same token in your CreateImageRun() method I've changed
the first three code lines:
ImagePart newPart = footerPart.AddImagePart(ImagePartType.Jpeg);
A.Blip shape = sourceRun.Descendants<A.Blip>().FirstOrDefault();
ImagePart p = sourceDoc.MainDocumentPart.GetPartById(shape.Embed.Value) as ImagePart;
With theses changes the image appears in the mydoc.docx word document.
As an addition to the accepted answer - I write it as separate answer, because it's important and includes code samples:
Our WordDocumentManager class was inheriting from an abstract class, which in turn implements IDisposable. The Dispose method was overriden like so:
public override void Dispose()
{
document.Close();
document.Dispose();
}
That code executes when the using statement finishes:
using (var manager = new WordDocumentManager()){}
To my surprise, this means that document disposal does not count, so your image relationships will not be saved. If you run into such an issue - please keep in mind that might be the cause.
I resolved that issue with a hack that I wouldn't propose, you might decide on some other solution.
How can I change the font family of the document via OpenXml ?
I tried some ways but, when I open the document, it's always in Calibri
Follow my code, and what I tried.
The Header Builder I think is useless to post
private static void BuildDocument(string fileName, List<string> lista, string tipo)
{
using (var w = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
{
var mp = w.AddMainDocumentPart();
var d = new DocumentFormat.OpenXml.Wordprocessing.Document();
var b = new Body();
var p = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();
var r = new Run();
// Get and format the text.
for (int i = 0; i < lista.Count; i++)
{
Text t = new Text();
t.Text = lista[i];
if (t.Text == " ")
{
r.Append(new CarriageReturn());
}
else
{
r.Append(t);
r.Append(new CarriageReturn());
}
}
// What I tried
var rPr = new RunProperties(new RunFonts() { Ascii = "Arial" });
lista.Clear();
p.Append(r);
b.Append(p);
var hp = mp.AddNewPart<HeaderPart>();
string headerRelationshipID = mp.GetIdOfPart(hp);
var sectPr = new SectionProperties();
var headerReference = new HeaderReference();
headerReference.Id = headerRelationshipID;
headerReference.Type = HeaderFooterValues.Default;
sectPr.Append(headerReference);
b.Append(sectPr);
d.Append(b);
// Customize the header.
if (tipo == "alugar")
{
hp.Header = BuildHeader(hp, "Anúncio Aluguel de Imóvel");
}
else if (tipo == "vender")
{
hp.Header = BuildHeader(hp, "Anúncio Venda de Imóvel");
}
else
{
hp.Header = BuildHeader(hp, "Aluguel/Venda de Imóvel");
}
hp.Header.Save();
mp.Document = d;
mp.Document.Save();
w.Close();
}
}
In order to style your text with a specific font follow the steps listed below:
Create an instance of the RunProperties class.
Create an instance of the RunFont class. Set the Ascii property to the desired font familiy.
Specify the size of your font (half-point font size) using the FontSize class.
Prepend the RunProperties instance to your run containing the text to style.
Here is a small code example illustrating the steps described above:
private static void BuildDocument(string fileName, List<string> text)
{
using (var wordDoc = WordprocessingDocument.Create(fileName, WordprocessingDocumentType.Document))
{
var mainPart = wordDoc.AddMainDocumentPart();
mainPart.Document = new Document();
var run = new Run();
foreach (string currText in text)
{
run.AppendChild(new Text(currText));
run.AppendChild(new CarriageReturn());
}
var paragraph = new Paragraph(run);
var body = new Body(paragraph);
mainPart.Document.Append(body);
var runProp = new RunProperties();
var runFont = new RunFonts { Ascii = "Arial" };
// 48 half-point font size
var size = new FontSize { Val = new StringValue("48") };
runProp.Append(runFont);
runProp.Append(size);
run.PrependChild(runProp);
mainPart.Document.Save();
wordDoc.Close();
}
}
Hope, this helps.
If you are using Stylesheet just add an instance of FontName property at appropriate font index during Fonts initilaization.
private Stylesheet GenerateStylesheet()
{
Stylesheet styleSheet = null;
Fonts fonts = new Fonts(
new Font( // Index 0 - default
new FontSize() { Val = 8 },
new FontName() { Val = "Arial"} //i.e. or any other font name as string
);
Fills fills = new Fills( new Fill(new PatternFill() { PatternType = PatternValues.None }));
Borders borders = new Borders( new Border() );
CellFormats cellFormats = new CellFormats( new CellFormat () );
styleSheet = new Stylesheet(fonts, fills, borders, cellFormats);
return styleSheet;
}
Then use it in Workbook style part as below.
WorkbookStylesPart stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = GenerateStylesheet();
stylePart.Stylesheet.Save();