Я хотел бы обновить эту ветку и добавить ответ Адама выше для пользы других.
Мне действительно удалось на днях взломать какой-то рабочий код (до того, как Адам опубликовал свой ответ), но это было довольно сложно. Документация действительно скудная, и там не так много информации.
Я не знал об элементах Inline
и Run
, которые Адам использует в своем ответе, но, похоже, дело в том, чтобы добраться до свойства Descendants<>
, и тогда вы в значительной степени сможете разобрать любой элемент, например нормальное отображение XML.
byte[] docBytes = File.ReadAllBytes(_myFilePath);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(docBytes, 0, docBytes.Length);
using (WordprocessingDocument wpdoc = WordprocessingDocument.Open(ms, true))
{
MainDocumentPart mainPart = wpdoc.MainDocumentPart;
Document doc = mainPart.Document;
// now you can use doc.Descendants<T>()
}
}
Как только вы это получили, поискать вещи довольно легко, хотя вам нужно разобраться, как все это называется. Например, <pic:nvPicPr>
- это Picture.NonVisualPictureProperties
и т. Д.
Как правильно говорит Адам, элемент, который вам нужно найти, чтобы заменить изображение, это элемент Blip
. Но вам нужно найти правильный блик, соответствующий изображению, которое вы пытаетесь заменить.
Адам показывает способ использования элемента Inline
. Я просто нырнул и посмотрел все элементы изображения. Я не уверен, что является лучшим или более надежным способом (я не знаю, насколько непротиворечива структура XML между документами и вызывает ли это нарушение кода).
Blip GetBlipForPicture(string picName, Document document)
{
return document.Descendants<Picture>()
.Where(p => picName == p.NonVisualPictureProperties.NonVisualDrawingProperties.Name)
.Select(p => p.BlipFill.Blip)
.Single(); // return First or ToList or whatever here, there can be more than one
}
См. Пример XML Адама, чтобы понять различные элементы здесь и посмотреть, что я ищу.
Blip имеет идентификатор в свойстве Embed
, например: <a:blip r:embed="rId4" cstate="print" />
, это означает, что Blip сопоставляется с изображением в папке Media (вы можете увидеть все эти папки и файлы, если переименуете .docx). в ZIP-архив и распаковать его). Вы можете найти отображение в _rels\document.xml.rels
:
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png" />
Итак, что вам нужно сделать, это добавить новое изображение, а затем навести этот блик на идентификатор вашего вновь созданного изображения:
// add new ImagePart
ImagePart newImg = mainPart.AddImagePart(ImagePartType.Png);
// Put image data into the ImagePart (from a filestream)
newImg .FeedData(File.Open(_myImgPath, FileMode.Open, FileAccess.Read));
// Get the blip
Blip blip = GetBlipForPicture("MyPlaceholder.png", doc);
// Point blip at new image
blip.Embed = mainPart.GetIdOfPart(newImg);
Полагаю, это просто лишает смысла старый образ в папке «Медиа», который не идеален, хотя, может быть, он достаточно умен, чтобы, так сказать, собрать мусор. Возможно, есть лучший способ сделать это, но я не смог его найти.
Во всяком случае, у вас это есть. Эта ветка теперь является самой полной документацией о том, как поменять изображение в любом месте в Интернете (я знаю это, я потратила часы на поиск). Так что, надеюсь, некоторые люди найдут это полезным.