Мне приснился кошмар, когда я пытался добавить Chart в MemoryStream в памяти.
Я создаю документ Word на лету, используя OpenXML, и у меня есть диаграмма, которая также динамически генерируется из данных в базе данных.
Я получаю шаблон из базы данных в виде байтового массива, передавая его в метод, который также принимает бизнес-объект, который содержит набор данных для заполнения закладок, содержащихся в этом шаблоне.
Вот метод:
public Stream Parse(byte[] array, AudiometryReport AudReport)
{
using (MemoryStream Stream = new MemoryStream())
{
Stream.Write(array, 0, (int)array.Length);
Stream.Position = 0;
using (document = WordprocessingDocument.Open(Stream, true))
{
XDocument doc = document.MainDocumentPart.GetXDocument();
List<XElement> bookmarks = doc.Descendants()
.Where(n => n.NodeType == XmlNodeType.Element && n.Name.LocalName == "bookmarkStart")
.ToList();
PropertyInfo[] reportInfo = AudReport.GetType().GetProperties();
foreach (XElement bm in bookmarks)
{
try
{
if (bm.LastAttribute.Value == "AudiometryChart")
{
string partId = InsertImage(document.MainDocumentPart);
var element = AddImageToDocument(document.MainDocumentPart, partId);
//var element = InsertImageXElement(partId);
//bm.ReplaceWith(new XElement(w + "r", element));
}
else
{
string val = reportInfo.Single(x => x.Name == bm.LastAttribute.Value).GetValue(AudReport, null).ToString();
bm.ReplaceWith(new XElement(w + "r",
new XElement(w + "t", val)));
}
}
catch
{ }
}
document.MainDocumentPart.PutXDocument();
//foreach (BookmarkStart bm in (IEnumerable<BookmarkStart>)document.MainDocumentPart.Document.Descendants<BookmarkStart>())
//{
// if (bm.Name == "AudiometryChart")
// {
// // Insert the chart object here.
// //AddImage(document);
// }
// populateStaffDetails(AudReport.Report.Employee, bm);
// populateAudiometryDetails(AudReport, bm);
//}
}
MemoryStream s = new MemoryStream();
Stream.WriteTo(s);
s.Position = 0;
return s;
}
}
Изображение InsertImage берет MainDocumentPart и присоединяет новый ImagePart из изображения, которое я передаю из базы данных. Я передаю идентификатор этой части обратно вызывающему методу.
private string InsertImage(MainDocumentPart docPart)
{
//DrawingsPart dp = docPart.AddNewPart<DrawingsPart>();
//ImagePart part = dp.AddImagePart(ImagePartType.Png, docPart.GetIdOfPart(dp));
ImagePart part = docPart.AddImagePart(ImagePartType.Png);
Chart cht = new ChartBuilder().DoChart(Data, new string[] { "Left", "Right", "Normal" });
using (MemoryStream ms = new MemoryStream())
{
cht.SaveImage(ms, ChartImageFormat.Png);
ms.Position = 0;
part.FeedData(ms);
}
//int count = dp.ImageParts.Count<ImagePart>();
int count = docPart.ImageParts.Count<ImagePart>();
return docPart.GetIdOfPart(part);
}
Последняя часть - это серьезная неприятность, которая, как утверждается, требуется добавить одно изображение в одно слово документа, но какого черта - вот оно, в любом случае:
private Run AddImageToDocument(MainDocumentPart docPart, string ImageRelId)
{
string ImageFileName = "Audiometry Chart Example";
string GraphicDataUri = "http://schemas.openxmlformats.org/drawingml/2006/picture";
long imageLength = 990000L;
long imageHeight = 792000L;
var run = new Run(
new Drawing(
new wp.Inline(
new wp.Extent() { Cx = imageLength, Cy = imageHeight },
new wp.EffectExtent()
{
LeftEdge = 19050L,
TopEdge = 0L,
RightEdge = 9525L,
BottomEdge = 0L
},
new wp.DocProperties()
{
Id = (UInt32Value)1U,
Name = "Inline Text Wrapping Picture",
Description = ImageFileName
},
new wp.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 = ImageFileName },
new pic.NonVisualPictureDrawingProperties()),
new pic.BlipFill(
new a.Blip() { Embed = ImageRelId },
new a.Stretch(
new a.FillRectangle())),
new pic.ShapeProperties(
new a.Transform2D(
new a.Offset() { X = 0L, Y = 0L },
new a.Extents() { Cx = imageLength, Cy = imageHeight }),
new a.PresetGeometry(
new a.AdjustValueList()) { Preset = a.ShapeTypeValues.Rectangle }))
) { Uri = GraphicDataUri }))
{
DistanceFromTop = (UInt32Value)0U,
DistanceFromBottom = (UInt32Value)0U,
DistanceFromLeft = (UInt32Value)0U,
DistanceFromRight = (UInt32Value)0U
}
));
return run;
}
Итак, я решил проблемы, из-за которых поток памяти вызывал проблемы, преждевременно закрыв и, возможно, дюжину других ненужных проблем любительских садовых дорожек, но это изображение просто не будет отображаться в моем документе. Разочарование. Предложения или божественное вдохновение очень приветствуются прямо сейчас.
(этот вопрос был сильно отредактирован, поэтому некоторые ответы могут не относиться к формулировке этого вопроса).