OpenXML SDK: встроенный объект OLE сжимается после редактирования
Я должен создать очень большой документ Word, который содержит много графиков (да, это должен быть Word). Графики создаются сторонним приложением. Поскольку стороннее приложение поддерживает только документы Word, размер которых меньше 8 МБ, а документы, которые мне нужно сгенерировать, гораздо больше, я строю изображения для отдельных документов, по одному, затем извлекаю их и добавляю в окончательный документ.
Используемый ими "формат изображения" - это нечто запатентованное, встроенное через OLE. Двойной щелчок открывает приложение в фоновом режиме, которое позволяет масштабировать и панорамировать изображение. Теперь, выходя из этого графического редактора, картинка внезапно сжимается, разрушая макет документа. Оригинальный документ, из которого я извлекаю изображение, не демонстрирует такого поведения.
В настоящее время я занимаюсь:
- Разместите изображение во временном документе, пусть оно будет
temp.docx
- Открой
temp.docx
какWordprocessingDocument
- Извлечь проприетарные данные двоичного изображения, пусть это будет
plot.bin
- Извлеките его представление WMF, пусть
plot.wmf
- Поиск соответствующего
Shape
объект, создать клон егоShapetype
ребенок - Добавить
plot.bin
какEmbeddedObjectPart
- Добавить
plot.wmf
какImagePart
- Создать
Shape
сImageData
ребенок ссылается на идентификаторplot.wmf
- Создать
OleObject
- Добавьте картинку к абзацу
EmbeddedObject
часть
Когда я смотрю на генерируемый XML, он выглядит идентично исходному документу.
Вот часть кода:
/// <summary>
/// Adds a picture
/// </summary>
/// <param name="doc">Document to add picture to</param>
/// <param name="pictureFile">File with proprietary picture data</param>
/// <param name="wmfRepresentationFile">WMF representation of the proprietary picture file</param>
/// <param name="pictureNumber">A rising number of the embedded picture. Incremented upon
/// embedding the picture!</param>
private static void AddPicture(WordprocessingDocument doc,
string pictureFile,
string wmfRepresentationFile,
Shapetype shapeType,
ref int pictureNumber) {
LOG.Debug("Embedding the picture in the document");
var emObj = doc.MainDocumentPart.AddEmbeddedObjectPart("application/vnd.openxmlformats-officedocument.oleObject");
using (var pictureIn = new FileStream(pictureFile, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var oleOut = emObj.GetStream(FileMode.OpenOrCreate, FileAccess.Write)) {
oleOut.Position = 0;
pictureIn.CopyTo(oleOut);
oleOut.Flush();
}
// An OLE embedded object also needs an image part.
var image = doc.MainDocumentPart.AddImagePart(ImagePartType.Wmf);
using (var imageIn = new FileStream(wmfRepresentationFile, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var imageOut = image.GetStream(FileMode.OpenOrCreate, FileAccess.Write)) {
imageOut.Position = 0;
imageIn.CopyTo(imageOut);
imageOut.Flush();
}
// Get some IDs we need for the linking
var objectPartId = doc.MainDocumentPart.GetIdOfPart(emObj);
var objectId = ("_" + emObj.GetHashCode().ToString() + "000000").Substring(0, 11);
var imagePartId = doc.MainDocumentPart.GetIdOfPart(image);
// Create a new paragraph with the embedded object.
// First, a "Shape"
var shape = new Shape() {
Id = "_x0000_i10" + pictureNumber,
Style = "width:500.0pt;height:600.0pt", // Sets the size of the picture in the document
Ole = new TrueFalseBlankValue(),
Type = "#_x0000_t75",
};
// This must contain the "imagedata" - a link to the image representation of the
// empty active picture
shape.AppendChild(new ImageData() {
Title = "",
RelationshipId = imagePartId
});
// Now, the link to the active picture itself
var ole = new OleObject() {
Type = OleValues.Embed,
ProgId = "Foo.Proprietary.Picture.1",
ShapeId = "_x0000_i10" + pictureNumber,
DrawAspect = OleDrawAspectValues.Content,
ObjectId = objectId,
Id = objectPartId
};
// Now, wrap everything into a Paragraph / Run / EmbeddedObject
var pictureParagraph = new Paragraph(new Run(new EmbeddedObject(shapeType, shape, ole)));
// And append it
doc.MainDocumentPart.Document.Body.AppendChild(pictureParagraph);
// Increase the image counter
pictureNumber++;
}
Что я пропускаю / делаю неправильно?