locked
OpenXML error RRS feed

  • Question

  • User1510859543 posted

    I am trying to use the Open XML 2.0 library to open a Word docx document, replace characters and then open or save the resulting document after replacements.  I get the following "Access denied" exception thrown when I try to run the code. However, the folder I am writing to is a common one that much is written to just fine. I have a feeling that the problem occurs when the new document is attempted to open.  When I try to open it from the file system using Word, I get the error "We're sorry. We can't open MarketingLetterOut.docx because we found a problem with its contents."  When I click "Details" it says "Illegal qualified name character.  Location: Part: /word/document.xml, Line: 2, Column: 11".

    The exception thrown is below.

    An unhandled exception occurred:

    Message: Access is denied

     

     Stack Trace:

       at contacts_Marketing.BtnCreate_Click(Object sender, EventArgs e) in C:\inetpub\wwwroot\BodyShop\contacts\Marketing.aspx.vb:line 125

       at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)

       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

     

    The button click code and search/replace code I am using is below.  I am searching for [customername] and replacing it with the label text of the customer.  Any help is appreciated.

        Protected Sub BtnCreate_Click(sender As Object, e As System.EventArgs) Handles BtnCreate.Click
            Try
                Dim sourceFile As String = Server.MapPath("~/OfficeDocs/Marketing/MarketingLetterTest.docx")
                Dim destinationFile As String = Server.MapPath("~/OfficeDocs/Marketing/")
                destinationFile &= "MarketingLetterOut.docx"
    
                ' Create a copy of the template file 
                File.Copy(sourceFile, destinationFile, True)
    
                ' Create key value pair, key represents words to be replace and 
                'values represent values in document in place of keys.
                Dim keyValues As New Dictionary(Of String, String)()
                keyValues.Add("[customername]", LblCustomer.Text)
                SearchAndReplace(destinationFile, keyValues)
    
                'open the copy
                Process.Start(destinationFile)
    
            Catch ex As Exception
                Throw ex
    
            End Try
        End Sub
    
    
        Public Shared Sub SearchAndReplace(document As String, dict As Dictionary(Of String, String))
            Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(document, True)
                Dim docText As String = Nothing
                Using sr As New StreamReader(wordDoc.MainDocumentPart.GetStream())
                    docText = sr.ReadToEnd()
                End Using
    
                For Each item As KeyValuePair(Of String, String) In dict
                    Dim regexText As New Regex(item.Key)
                    docText = regexText.Replace(docText, item.Value)
                Next
    
                Using sw As New StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create))
                    sw.Write(docText)
                End Using
            End Using
        End Sub

    Wednesday, October 28, 2015 10:49 AM

Answers

  • User1510859543 posted

    I resolved the "Access denied" issue by streaming the .docx file to the browser rather than using the Process.Start method.  However, a new issue has come up with this process.  When I try to do the replacement of text and use "[customername]" it does not perform the replacement and actually just leaves the destination document looking exactly like the source document.  If I change the source document to remove the brackets ( [ and ] ) then it works.  It even fails if I use any special characters.  Does anyone know a way around this?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, October 29, 2015 2:50 PM

All replies

  • User1578460427 posted
    Make sure that you have got the latest Microsoft Office Service Pack installed.
    Wednesday, October 28, 2015 5:38 PM
  • User1510859543 posted

    I do on the workstation but this is a web application and is running on a web server Win 2012 R2.

    Should I be using a more recent version of Open XML?

    Wednesday, October 28, 2015 5:43 PM
  • User1578460427 posted
    Which version of Open XML are you running?

    Latest version is Open XML SDK 2.5.
    Wednesday, October 28, 2015 6:16 PM
  • User1510859543 posted

    2.0

    Wednesday, October 28, 2015 7:39 PM
  • User614698185 posted

    Hi dlchase,

    When I try to open it from the file system using Word, I get the error "We're sorry. We can't open MarketingLetterOut.docx because we found a problem with its contents."  When I click "Details" it says "Illegal qualified name character.  Location: Part: /word/document.xml, Line: 2, Column: 11".

    Based on your error, I think you could refer to the following documents to fix it:

    https://support.microsoft.com/en-us/kb/2528942

    http://answers.microsoft.com/en-us/office/forum/office_2010-word/word-2010-document-will-not-open-illegal-xml/0d6d05df-d201-4537-a154-7b2a3df4e32a?auth=1

    http://bhrnjica.net/2014/01/23/how-to-manually-fix-content-error-in-microsoft-word/

    Best Regards,

    Candice Zhou

    Thursday, October 29, 2015 1:08 AM
  • User1578460427 posted
    Are you able to post the contents of the /word/document.xml?
    Thursday, October 29, 2015 2:23 AM
  • User1510859543 posted

    I have no idea what that filename is. Nor do I have a folder named word.

    Thursday, October 29, 2015 7:52 AM
  • User1510859543 posted

    I don't really want to "fix" a file every time I run this, I just want to open the new file created by the code.

    Also, the "Access denied" error occurs on the code line of Process.Start(destinationFile) which, I think, is trying to open the file in the browser?

    Thursday, October 29, 2015 7:53 AM
  • User1510859543 posted

    I resolved the "Access denied" issue by streaming the .docx file to the browser rather than using the Process.Start method.  However, a new issue has come up with this process.  When I try to do the replacement of text and use "[customername]" it does not perform the replacement and actually just leaves the destination document looking exactly like the source document.  If I change the source document to remove the brackets ( [ and ] ) then it works.  It even fails if I use any special characters.  Does anyone know a way around this?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, October 29, 2015 2:50 PM
  • User1578460427 posted
    Some special characters need to be escaped in XML: https://support.microsoft.com/en-us/kb/308060

    Try replacing the left square bracket with [ and the right square bracket with ]
    Thursday, October 29, 2015 7:06 PM
  • User1510859543 posted

    It just bypassed the entry of [customername] and did not replace it when I used [ for left bracket, etc. for the replacement text.

    Friday, October 30, 2015 8:50 AM
  • User1578460427 posted

    Are you able to post the contents of the source file docx?
    Friday, October 30, 2015 2:10 PM
  • User1510859543 posted

    No because it contains confidential data.  However, I have already changed it to remove the brackets around the fields.  It works perfect when I don't have the brackets.  So if I search for the word customername it works perfectly.  If I change the document and search for [customername] it bypasses the entire word.  Are there other characters I can use around the text in the source docx file?  The concept is to allow the user to create documents and use placeholders (like [ and ] ) around them so I can do a search and replace in the file stream.

    Friday, October 30, 2015 2:20 PM
  • User1578460427 posted

    It is the Microsoft Word spell checker on [customername], which is causing the search and replace to fail because the of the XML structure.

    See the difference between the following two examples, which both use a .docx with the following paragraph.

    This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long. Here come the field that we are searching for. The field is [customername]. This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long.

    Example 1 - Word Document with the [customername] unrecognised by the spellchecker i.e. red squiggly line under [customername] results in the following XML output.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>" & vbCrLf & "<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">
    	<w:body>
    		<w:p w:rsidR="00987645" w:rsidRDefault="00C74BE3">
    			<w:r>
    				<w:t>This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long. Here come the field that we a</w:t>
    			</w:r>
    			<w:r w:rsidR="00B350DA">
    				<w:t>re searching for. The field is [</w:t>
    			</w:r>
    			<w:proofErr w:type="spellStart"/>
    			<w:r>
    				<w:t>customername</w:t>
    			</w:r>
    			<w:proofErr w:type="spellEnd"/>
    			<w:r w:rsidR="00B350DA">
    				<w:t>].</w:t>
    			</w:r>
    			<w:r>
    				<w:t xml:space="preserve"> This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long.</w:t>
    			</w:r>
    		</w:p>
    		<w:sectPr w:rsidR="00987645" w:rsidSect="00987645">
    			<w:pgSz w:w="11906" w:h="16838"/>
    			<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
    			<w:cols w:space="708"/>
    			<w:docGrid w:linePitch="360"/>
    		</w:sectPr>
    	</w:body>
    </w:document>

    Example 2 - Word document with the [customername] recognised by the spellchecker i.e. NO red squiggly line under [customername] results in the following XML output.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>" & vbCrLf & "<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">
    	<w:body>
    		<w:p w:rsidR="00987645" w:rsidRDefault="00C74BE3">
    			<w:r>
    				<w:t>This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long. Here come the field that we are searching for. The field is [customername]. This is a test letter with some test text. Here is some more test text and some more test text. Somewhere in this test text is a field that is to be searched for. There goes some more dummy text. This is another test sentence, which is extremely long.</w:t>
    			</w:r>
    		</w:p>
    		<w:sectPr w:rsidR="00987645" w:rsidSect="00987645">
    			<w:pgSz w:w="11906" w:h="16838"/>
    			<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
    			<w:cols w:space="708"/>
    			<w:docGrid w:linePitch="360"/>
    		</w:sectPr>
    	</w:body>
    </w:document>

    You can view the XML structure of your Word document by adding a breakpoint on the following line, so that you can view the contents of the docText variable. 

    Public Shared Sub SearchAndReplace(document As String, dict As Dictionary(Of String, String))
            Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(document, True)
                Dim docText As String = Nothing
                Using sr As New StreamReader(wordDoc.MainDocumentPart.GetStream())
                    docText = sr.ReadToEnd() 'PUT A BREAKPOINT HERE TO SEE YOUR DOCUMENTS XML STRUCTURE
                End Using
    
                For Each item As KeyValuePair(Of String, String) In dict
                    Dim regexText As New Regex(item.Key)
                    docText = regexText.Replace(docText, item.Value)
                Next
    
                Using sw As New StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create))
                    sw.Write(docText)
                End Using
            End Using
        End Sub

    Sunday, November 1, 2015 4:59 PM
  • User1510859543 posted

    I'm not clear with what your recommended solution is.

    Sunday, November 1, 2015 5:21 PM
  • User1578460427 posted

    Simple solution is to not use the square brackets or any other placeholder symbols.
    Sunday, November 1, 2015 6:03 PM
  • User1510859543 posted

    Yes, and as I mentioned that process works great.  I was using the brackets to help qualify the text to replace so that my instructions to users was to just put them at start and end of text to replace.

    Monday, November 2, 2015 8:55 AM
  • User-1157115462 posted

    I'm sorry for not giving you the answer to your question but I would like to tell you there are 3rd party libraries for Word document manipulation. Instead of wrestling Open XML it is much easier to get yourself a toolkit that already does exacly what you need without constant fear of producing a corupt document. The majority of 3rd party libraries cost money but I bet that you have already spend more and that your solution is poor compared to a polished and stable product.

    Tuesday, November 3, 2015 10:11 AM