Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying Hyperlink with openxml

Tags:

c#

openxml

I'm trying to modify a hyperlink inside a word document. The hyperlink is originally pointing to a bookmark in a external document. What I want to do is change it to point to an internal bookmark that as the same Anchor.

Here's the code I use... It seem to work when I what the variables but when I look at the saved document it is exactly like the original.

What is the reason my chances don't persist?

// read file specified in stream 
MemoryStream stream = new MemoryStream(File.ReadAllBytes("C:\\TEMPO\\smartbook\\text1.docx"));
WordprocessingDocument doc = WordprocessingDocument.Open(stream, true);

MainDocumentPart mainPart = doc.MainDocumentPart;

// The first hyperlink -- it happens to be the one I want to modify 
Hyperlink hLink = mainPart.Document.Body.Descendants<Hyperlink>().FirstOrDefault();
if (hLink != null)
{
    // get hyperlink's relation Id (where path stores)
    string relationId = hLink.Id;
    if (relationId != string.Empty)
    {
        // get current relation
        HyperlinkRelationship hr = mainPart.HyperlinkRelationships.Where(a => a.Id == relationId).FirstOrDefault();
        if (hr != null)
        {
            // remove current relation
            mainPart.DeleteReferenceRelationship(hr);
            // add new relation with relation 
            // mainPart.AddHyperlinkRelationship(new Uri("C:\\TEMPO\\smartbook\\test.docx"), false, relationId);
        }
    }

    // change hyperlink attributes
    hLink.DocLocation = "#";
    hLink.Id = "";
    hLink.Anchor = "TEST";
}
// save stream to a new file
File.WriteAllBytes("C:\\TEMPO\\smartbook\\test.docx", stream.ToArray());
doc.Close();
like image 971
Benoit Letourneau Avatar asked Nov 01 '25 02:11

Benoit Letourneau


1 Answers

You have not yet saved your OpenXmlPackage when you write the stream ...

// types that implement IDisposable are better wrapped in a using statement
using(var stream = new MemoryStream(File.ReadAllBytes(@"C:\TEMPO\smartbook\text1.docx")))
{
   using(var doc = WordprocessingDocument.Open(stream, true))
   {
      // do all your changes
      // call doc.Close because that SAVES your changes to the stream
      doc.Close(); 
   }
   // save stream to a new file
   File.WriteAllBytes(@"C:\TEMPO\smartbook\test.docx", stream.ToArray());
} 

The Close method states explicitly:

Saves and closes the OpenXml package plus all underlying part streams.

You could also set the AutoSave property to true in which case the OpenXMLPackage will be saved when Dispose is called. The using statement I used above would guarantee that that will happen.

like image 62
rene Avatar answered Nov 02 '25 17:11

rene