Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

i have a WordGeneratorService. Here I get a Template from my Database, load the template to a MemoryStream and replace the bookmarks with text or objects(DataTables). For strings it's working fine. But a soon as i want to replace a bookmark with a Datatable i get the error message stream is not expandable.

Can anybody give me some advice?

Thanks

What I have tried:

C#
public byte[] GenerateDocumentTest(IDictionary<string, object> values, string settingsType, string settingsEntry)
       {

           SettingsEntry settings = this._unitOfWork.SettingsEntryRepository.FindByAlias(settingsType, settingsEntry);

           if (null != settings)
           {
               byte[] template = settings.File;
               if (template.Length > 0)
               {
                   return this.GenerateDocumentTest(values, template);
               }

           }

           return null;
       }


C#
public byte[] GenerateDocumentTest(IDictionary<string, object> values, byte[] template)
        {

            if (values == null) throw new ArgumentException("Fehlende Einträge!");

            MemoryStream stream = new MemoryStream(template);
                                    
            using (var doc = WordprocessingDocument.Open(stream, true))
            {
                if (doc.MainDocumentPart.HeaderParts != null)
                    foreach (var header in doc.MainDocumentPart.HeaderParts)
                        ProcessBookmarksPartTest(values, DocumentSection.Header, header);

                ProcessBookmarksPartTest(values, DocumentSection.Main, doc.MainDocumentPart);

                if (doc.MainDocumentPart.FooterParts != null)
                    foreach (var footer in doc.MainDocumentPart.FooterParts)
                        ProcessBookmarksPartTest(values, DocumentSection.Footer, footer);

                stream.Position = 0;
                byte[] result = stream.ToArray();
                return result;
            }



        }


C#
private void ProcessBookmarksPartTest(IDictionary<string, object> values, DocumentSection documentSection, object section)
        {
            IEnumerable<BookmarkStart> bookmarks = null;
            //Holen der einzelnen Bookmarks für jede Dokumentsektion
            switch (documentSection)
            {
                case DocumentSection.Main:
                    {
                        bookmarks = ((MainDocumentPart)section).Document.Body.Descendants<BookmarkStart>();
                        break;
                    }
                case DocumentSection.Header:
                    {
                        bookmarks = ((HeaderPart)section).RootElement.Descendants<BookmarkStart>();
                        break;
                    }
                case DocumentSection.Footer:
                    {
                        bookmarks = ((FooterPart)section).RootElement.Descendants<BookmarkStart>();
                        break;
                    }
            }

            if (bookmarks == null)
            {
                return;
            }
            foreach (var bmStart in bookmarks)
            {
                if (!values.ContainsKey(bmStart.Name))
                    continue;
                BookmarkEnd bmEnd = null;
                switch (documentSection)
                {
                    case DocumentSection.Main:
                        {
                            bmEnd = (((MainDocumentPart)section).Document.Body.Descendants<BookmarkEnd>().Where(b => b.Id == bmStart.Id.ToString())).FirstOrDefault();
                            break;
                        }
                    case DocumentSection.Header:
                        {
                            bmEnd = (((HeaderPart)section).RootElement.Descendants<BookmarkEnd>().Where(b => b.Id == bmStart.Id.ToString())).FirstOrDefault();
                            break;
                        }
                    case DocumentSection.Footer:
                        {
                            bmEnd = (((FooterPart)section).RootElement.Descendants<BookmarkEnd>().Where(b => b.Id == bmStart.Id.ToString())).FirstOrDefault();
                            break;
                        }
                }

                if (bmEnd == null)
                    continue;
                var rProp = bmStart.Parent.Descendants<Run>().Where(rp => rp.RunProperties != null).Select(rp => rp.RunProperties).FirstOrDefault();
                if (bmStart.PreviousSibling<Run>() == null && bmEnd.ElementsAfter().Count(e => e.GetType() == typeof(Run)) == 0)
                {
                    bmStart.Parent.RemoveAllChildren<Run>();
                }
                else
                {
                    var list = bmStart.ElementsAfter().Where(r => r.IsBefore(bmEnd)).ToList();
                    var trRun = list.Where(rp => rp.GetType() == typeof(Run) && ((Run)rp).RunProperties != null).Select(rp => ((Run)rp).RunProperties).FirstOrDefault();
                    if (trRun != null)
                        rProp = (RunProperties)trRun.Clone();
                    for (var n = list.Count(); n > 0; n--)
                        list[n - 1].Remove();
                }

                var dictValue = values[bmStart.Name];

                if (dictValue.GetType().Equals(typeof(DataTable)))
                {
                    DataTable dictTable = dictValue as DataTable;

                    //Elternelement des aktuellen Bookmarks
                    OpenXmlElement bmParent = bmStart.Parent;

                    DocumentFormat.OpenXml.Wordprocessing.Table wordTable = new DocumentFormat.OpenXml.Wordprocessing.Table();
                    TableProperties tblProp = new DocumentFormat.OpenXml.Wordprocessing.TableProperties(
                        new TableBorders(new Border()
                        {
                            Val = new DocumentFormat.OpenXml.EnumValue<BorderValues>(BorderValues.DotDash),
                            Size = 24
                        }
                        )
                    );
                    wordTable.AppendChild<TableProperties>(tblProp);
                    for (int i = 0; i < dictTable.Rows.Count; i++)
                    {
                        DocumentFormat.OpenXml.Wordprocessing.TableRow tr = new DocumentFormat.OpenXml.Wordprocessing.TableRow();
                        for (int j = 0; j < dictTable.Columns.Count; j++)
                        {

                            DocumentFormat.OpenXml.Wordprocessing.TableCell wordTableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell();
                            wordTableCell.Append(new TableCellProperties(new TableCellWidth() { Type = TableWidthUnitValues.Dxa, Width = "2880" }));
                            wordTableCell.Append(new Paragraph(new Run(new Text(dictTable.Rows[i][j].ToString()))));
                            tr.Append(wordTableCell);
                        }
                        wordTable.Append(tr);
                    }
                    bmParent.InsertAfterSelf(wordTable);




                }
                    else if (dictValue.GetType().Equals(typeof(string)))
                    {
                        //Der Wert im Dict ist Text

                        string bmText = dictValue as string;

                        if (!string.IsNullOrEmpty(bmText) && bmText.Contains(Environment.NewLine))
                        {
                            OpenXmlElement insertElement = bmStart.Parent.PreviousSibling();
                            string[] rows = bmText.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                            foreach (string row in rows)
                            {
                                Paragraph np = new Paragraph();
                                Run nRun = new Run();
                                if (rProp != null) nRun.RunProperties = (RunProperties)rProp.Clone();
                                nRun.AppendChild(new Text(row));
                                np.AppendChild(nRun);
                                if (insertElement.Parent != null) insertElement.InsertAfterSelf(np);
                                else insertElement.Append(np);
                                insertElement = np;
                            }
                        }
                        else
                        {
                            var nRun = new Run();
                            if (rProp != null) nRun.RunProperties = (RunProperties)rProp.Clone();
                            nRun.Append(new Text(bmText));
                            bmStart.InsertAfterSelf(nRun);
                        }
                    }
                    else
                    {
                        throw new Exception("Der Übergebenen Wert ist weder string noch Datatable");
                    }
                }
            }
Posted
Updated 10-Aug-17 2:58am

1 solution

The "stream is not expandable" message means something is trying to increase the size of the MemoryStream. The only way to get a MemoryStream instance that supports this is to use the constructor which takes the initial capacity[^], or the parameterless constructor. Every other constructor creates a non-resizable stream.
C#
MemoryStream stream = new MemoryStream(template.Length);
stream.Write(template, 0, template.Length);
stream.Seek(0L, SeekOrigin.Begin);

using (var doc = WordprocessingDocument.Open(stream, true))
{
    ...
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900