antonmihaylov / OpenXmlTemplates

Word .docx templating system that is designer (no scripting tags) and server-friendly (no word installation required)
GNU Lesser General Public License v3.0
92 stars 25 forks source link

The provided SdtElement is not a content control (Parameter 'sdtElement') #9

Closed dgwaldo closed 4 years ago

dgwaldo commented 4 years ago

We've ran into a little problem after upgrading our code... Our templates are made in Word 2013 and are docx.

Handler is implemented as follows. After getting this error I attempted a few things. I tried with multiple document templates, and I tried using the TemplateDocument() class with a hard coded path.

public async Task<Result<Stream>> Handle(FillDocxFileCommand request, CancellationToken cancellationToken) {
            var file = request.Form.Files[0];
            var jsonData = request.Form["data"];
            var variableSource = new VariableSource();
            variableSource.LoadDataFromJson(jsonData);

            var outStream = new MemoryStream();
            await file.CopyToAsync(outStream);
            var document = WordprocessingDocument.Open(outStream, true);
            var tempDoc = new TemplateDocument(document);
            var templateEngine = new DefaultOpenXmlTemplateEngine();
            templateEngine.ReplaceAll(tempDoc, variableSource);
            document.Dispose();

            if (outStream == null || outStream.Length == 0) {
                return new NotFoundResult<Stream>();
            }

            outStream.Position = 0;

            return new FileResult<Stream>(outStream, "application/octet-stream", file.Name + ".docx");
  }
dgwaldo commented 4 years ago

I pulled the code local and ran it. Ran into the same issue where VS2019 can't open the project or solution file. I copied everything into a new solution and applied this fix... Looks like it just needed to include SdtCell as a valid element. Our templates are heavy on the tables...


        /// <summary>
        /// Verifies if this element is a content control
        /// </summary>
        public static bool IsContentControl(this OpenXmlElement e)
        {
            return e is SdtBlock || e is SdtRun || e is SdtCell;
        }
antonmihaylov commented 4 years ago

That's a good find, thank you for the contribution!