This project has moved and is read-only. For the latest updates, please go here.

ReplaceText does not replace text in header

Nov 17, 2010 at 8:32 PM

I have the following code:

using (DocX document = DocX.Load(@destFile))
            {
                /*
                 * Replace each instance of the string pear with the string banana.
                 * Specifying true as the third argument informs DocX to track the
                 * changes made by this replace. The fourth argument tells DocX to
                 * ignore case when matching the string pear.
                 */
                document.ReplaceText("$_ECODE_$", "E#0001" + tbEcode.Text, true, true, false);
                document.ReplaceText("$_INITIALS_$", tbInitials.Text, true, true, false);
                document.ReplaceText("$_VISITDATE_$", dtpVisitDate.Text, true, true, false);
                document.ReplaceText("$_VISITNUMBER_$", cbVisitNumber.Text, true, true, false);
                // Save changes made to this document
                document.Save();
            }

$_ECODE_$, $_INITIALS_$ and $_VISITDATE_$ are all in my document header, but when I execute this code, nothing in the headers changes, only the document body.

Is there something else I need to do?

 

Cheers,

Sean

Nov 17, 2010 at 8:43 PM
Sean,

ReplaceText was written before support for Headers and Footers was added. I will update ReplaceText as soon as I get the chance (probably tomorrow) to also replace text in Headers and Footers.

For the moment you could loop through the Paragraphs in the Headers\Footers and call ReplaceText on each Paragraph.

Regards,
Cathal
Nov 20, 2010 at 3:14 PM

Thanks Cathal,

 

When do you expect to commit the changes?  I'd rather not have to write code to iterate through each paragraph in each header/footer!

If I can help, let me know.

Thanks,

Sean

Nov 20, 2010 at 4:49 PM
srwright,

I have just submitted the changeset you requested. Please download and
evaluate change-set: 57843. Let me know if you have any issues.

Happy coding,
Cathal
Nov 21, 2010 at 2:34 PM

Thanks Cathal!  I'll run it through its paces today and let you know the results.

 

Cheers,

 

Sean

Nov 21, 2010 at 3:30 PM
Edited Nov 21, 2010 at 3:39 PM

Hey Cathal,

 

It seems I cannot run my original code (see above) anymore; I currently get the following errors on the ReplaceText methods:

Error    4    The best overloaded method match for 'Novacode.Container.ReplaceText(string, string, bool, System.Text.RegularExpressions.RegexOptions, Novacode.Formatting, Novacode.Formatting, Novacode.MatchFormattingOptions)' has some invalid arguments   

In the previous version there appeared to be 4 different ReplaceText methods with different overrides.  It seems now there is only one.

 

*** UPDATE ***

Ok, I should have looked at it with the OBjectBrowser first.  I just needed to change my parameters.  Much easier than having so many overrides. 

Thanks!

 

Sean

Nov 21, 2010 at 4:27 PM
srwright,

> In the previous version there appeared to be 4 different ReplaceText methods
> with different overrides.  It seems now there is only one.

.NET 4.0 introduced a new feature called Optional Parameters. This
features removes the need for over loading functions.

Take ReplaceText() as an example, it can take up to 8 parameters. To
provide the same functionality without using OptionalParameters the
code base would be bloated with many function overloads.

I did not consider the fact that this would break backwards
compatibility. I want to use Optional Parameters to reduce the code
base but I do not want users to have to update their old code. I need
to think about this for awhile.

Thank you for bringing this to my attention.

Regards,
Cathal
Nov 22, 2010 at 2:52 PM

Hi Cathal,

I recompiled and tested the routine with my document template and still, the headers were not modified.

Here's my code:

using (DocX document = DocX.Load(@destFile))
            {
                /*
                 * Replace each instance of the string pear with the string banana.
                 * Specifying true as the third argument informs DocX to track the
                 * changes made by this replace. The fourth argument tells DocX to
                 * ignore case when matching the string pear.
                 */
                document.ReplaceText("$_ECODE_$", "E#0001" + tbEcode.Text, false, RegexOptions.IgnoreCase, null, null, MatchFormattingOptions.ExactMatch);
                document.ReplaceText("$_INITIALS_$", tbInitials.Text, false, RegexOptions.IgnoreCase, null, null, MatchFormattingOptions.ExactMatch);
                document.ReplaceText("$_VISITDATE_$", dtpVisitDate.Text, false, RegexOptions.IgnoreCase, null, null, MatchFormattingOptions.ExactMatch);
                document.ReplaceText("$_VISITNUMBER_$", cbVisitNumber.Text, false, RegexOptions.IgnoreCase, null, null, MatchFormattingOptions.ExactMatch);
                // Save changes made to this document
                document.Save();
            }
Am I supplying the correct parameters?

Nov 22, 2010 at 2:59 PM
Hi srwright,

I have tested the new ReplaceText() function on a few files and it is
working correctly for me.

Can you send me the document you are having problems with? If this
document contains sensitive information then please try to create a
simple example document that ReplaceText() fails on.

Once I have your document I will debug the problem on my side.

Cheers,
Cathal
Nov 23, 2010 at 5:52 PM

Hey Cathal,

 

Top of the mornin' to ya!

 

Did you get a chance to look at the files I sent?

Nov 23, 2010 at 9:00 PM
srwright,

unfortunately I did not: PhD deadlines took precedence :-)
I will take a look when I get home tonight.

Top of the evening' to ya!
Cathal
Nov 24, 2010 at 12:02 AM

srwright,

it took me a few hours, but I finally understand this bug. The new ReplaceText() is working fine: there is actually something 'fishy' about your document.

See below for an explanation
---------------------------------- 

Every .docx document contains a tag <w:sectPr> within its structure.
This tag contains a few nested tags of type <w:headerReference> which tell Word.exe where each unique header is stored.
A .docx document typically contains 3 headers, these are by default

header1.xml - Default\Odd Header
header2.xml - First Header
header3.xml - Even Header

Your 'fishy' document contained three <w:sectPr> tags within its structure and these tags were not --as far as I understand it-- in the correct position.
Two of these tags where actually embedded inside <w:Ppr> tags which to me makes no sense.

DocX was ignoring the first two nested tags and only found --the tag that was in the correct location-- the third tag.
Unfortunately only the first tag, the incorrectly placed tag, contained the correct location for the default header's Xml file.

Here is what I think is happening. Word.exe is searching the Xml tree and only returning the first <w:sectPr> tag that it finds regardless of where it is located.
I have uploaded a new change-set which implements this crazy logic.

@srwright  I tested this change-set: 58002 on the document you provided me and it appears to work correctly now.

Happy coding,
Cathal

P.S. Word.exe is capable of making some very 'fishy' .docx documents.

Nov 24, 2010 at 2:41 PM

Cathal,

 

Brilliant!  I'm happy to hear you were able to find the problem and even work around it.  It makes me think that I need to re-work my document templates.  I'm wondering, if they were created originally as .doc files, opened in Word 2007 and saved as .docx files, could that have contributed to the 'fishiness' of the sectPrs?

Also, will this new changeset break any of the previous versions?

Cheers (and Thanks!),

 

Sean

Nov 24, 2010 at 6:18 PM
Sean,

>> I'm wondering, if they were created originally as .doc files, opened in Word 2007 and saved as .docx files, could that have contributed to the 'fishiness' of the sectPrs?
Its very likely, conversion is a very difficult task.

Also, will this new changeset break any of the previous versions?
No it will not.

Cheers,
Cathal