Copy all elements from word doc - asp.net

I'm trying to copy all the elements from a word doc to a new word doc. When I try to get all ChildElements I get the message "Object reference not set to an instance of an object" on this line "For Each element As OpenXmlElement In templatedoc.MainDocumentPart.Document.Body.ChildElements"
Please help
Code:
Dim containerElement = NewDocument.MainDocumentPart.Document.Descendants().FirstOrDefault()
Dim clonedElements = New List(Of OpenXmlElement)
For Each element As OpenXmlElement In templatedoc.MainDocumentPart.Document.Body.ChildElements
clonedElements.Add(element.Clone())
Next
containerElement.RemoveAllChildren()
containerElement.Append(clonedElements)

Thanks guys and girls!
Here is my final working code:
' Copy XML parts to define document
NewDocument.AddPart(templatedoc.GetPartById("rId3"), "rId3")
NewDocument.AddPart(templatedoc.GetPartById("rId2"), "rId2")
'// Add a main document part.
Dim mainPart = NewDocument.AddMainDocumentPart()
' // Add a Body
mainPart.Document = New Document(New Body())
'Copy Document XMLParts - must be in specific order
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId8"), "rId8")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId3"), "rId3")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId7"), "rId7")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId2"), "rId2")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId1"), "rId1")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId6"), "rId6")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId5"), "rId5")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId4"), "rId4")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId9"), "rId9")
'// Copy text from template document
Dim containerElement = NewDocument.MainDocumentPart.Document.Descendants().FirstOrDefault()
Dim clonedElements = New List(Of OpenXmlElement)
Dim elementstocopy = templatedoc.MainDocumentPart.Document.Body.ChildElements
For Each element As OpenXmlElement In elementstocopy
clonedElements.Add(element.Clone())
Next
containerElement.RemoveAllChildren()
containerElement.Append(clonedElements)
mainPart.Document.Save()

Related

Open XML SDK Open and Save not working

I am having trouble with the Open XML SDK opening and saving word documents.
I am using the following code (VB.Net):
Try
'Set Path
Dim openPath As String = "../Documents/" & worddoc
Dim savePath As String = "\\web-dev-1\HR_Documents\" & worddoc
Using doc As WordprocessingDocument = WordprocessingDocument.Open("/Documents/" & worddoc, True)
'Employee Name Insert
'Find first table in document
Dim tbl1 As Table = doc.MainDocumentPart.Document.Body.Elements(Of Table).First()
'First Row in tbl
Dim row As TableRow = tbl1.Elements(Of TableRow)().ElementAt(0)
'Find first cell in row
Dim cell As TableCell = row.Elements(Of TableCell)().ElementAt(0)
'Insert selected Employee Name
Dim p As Paragraph = cell.Elements(Of Paragraph)().First()
Dim r As Run = p.Elements(Of Run)().First()
Dim txt As Text = r.Elements(Of Text)().First()
txt.Text = ddlEmployeeList.SelectedItem.Text
'Save File
'Supervisor Name Insert
'Find second table in document
Dim tbl2 As Table = doc.MainDocumentPart.Document.Body.Elements(Of Table).First()
'First Row in tbl
Dim row2 As TableRow = tbl2.Elements(Of TableRow)().ElementAt(0)
'Find first cell in row
Dim cell2 As TableCell = row2.Elements(Of TableCell)().ElementAt(0)
'Insert selected Employee Name
Dim p2 As Paragraph = cell2.Elements(Of Paragraph)().First()
Dim r2 As Run = p2.Elements(Of Run)().First()
Dim txt2 As Text = r2.Elements(Of Text)().First()
txt2.Text = ddlSupervisorList.SelectedItem.Text
End Using
Return 1
Catch ex As Exception
Return Nothing
End Try
The trouble starts on the first using statement. It throws the following error:
Could not find a part of the path 'C:\Documents\Hourly_Employee_Performance_Review .docx
I have placed the word documents in a folder of the ASP.NET site called Documents. I also have created a public share on the dev server to see if maybe that would help.
The problem is that it doesn't use the supplied path variable. I have gone through the documentation for OPEN XMl SDK but all it talks about is the Using Statement and its need and use for it.
Can anyone tell me, show me, or point to a site that has examples of how to set both the open path and save path?
You need a path to the file which is based on the filesytem, not a URL. You can do that with
Dim openPath As String = Path.Combine(Server.MapPath("~/Documents"), worddoc)
And then to open the file:
Using doc As WordprocessingDocument = WordprocessingDocument.Open(openPath, True)
It appears that you will need to do the same for the location to save to, but you didn't say if "\\web-dev-1" is a different server; if it were that would need other considerations.
(Not tested, some typos may exist. You will need an Imports System.IO.)

create Xml Document from Node

Trying to create a new xml document from an existing xml node that is passed into a method. This with VB.NET. How to do ?
Private Shared Sub WriteChanges(parentNode As XmlNode, nodeName As String, m As Model.ModelBaseWithTracking)
Dim xml As New XmlDocument()
If parentNode.Name = "#document" Then
'Need code here
End If
End Sub
This is simple. You can create nodes in the XML document as following:
Private Shared Sub WriteChanges(parentNode As XmlNode, nodeName As String, m As Model.ModelBaseWithTracking)
Dim xml As New XmlDocument()
If parentNode.Name = "#document" Then
//To create root elemet
Dim root As XmlElement = xml.CreateElement("document")
xml.AppendChild(root)
//To add child node to root element
Dim child As XmlElement = xml.CreateElement("document1")
root.AppendChild(child)
child.SetAttribute("id", "1")
//Add more nodes same as shown above..
End If
End Sub

OpenXml Edit text in the header of a word file

I'm using Open XML and I should change the text in the header of a word file. To change a specific paragraph in the document I have used the following code:
Dim body = wdDoc.MainDocumentPart.Document.Body
Dim paras = body.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph)()
Dim header = body.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Header)()
For Each para In paras
For Each run In para.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Run)()
For Each testo In run.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
If (testo.Text.Contains("<$doc_description$>")) Then
testo.Text = testo.Text.Replace("<$doc_description$>", "replaced-text")
End If
Next
Next
Next
thanks in advance!
Ported to C# from Hans answer!
//Gets all the headers
foreach (var headerPart in doc.MainDocumentPart.HeaderParts)
{
//Gets the text in headers
foreach(var currentText in headerPart.RootElement.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>())
{
currentText.Text = currentText.Text.Replace("[Thanks]", "Thanks");
}
}
You can use the following code to replace a tag in the header of a word document:
Using wdDoc = WordprocessingDocument.Open("header.docx", True)
For Each headerPart In wdDoc.MainDocumentPart.HeaderParts
For Each currentParagraph In headerPart.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph)()
For Each currentRun In currentParagraph.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Run)()
For Each currentText In currentRun.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
If (currentText.Text.Contains("$doc-description$")) Then
Console.WriteLine("found")
currentText.Text = currentText.Text.Replace("$doc-description$", "replaced-text")
End If
Next
Next
Next
Next
End Using
First, enumerate all HeaderParts of the word document. Then search for all Text elements
containing the tag to replace. Then replace the tag with your text.
Please note that you should use a tag without <> and _ characters. If your
tag contains these characters then word splits the text among multiple Text elements.
If you want to change the text in a table (or in any other element) just search
for all Text elements:
Using wdDoc = WordprocessingDocument.Open("header.docx", True)
For Each headerPart In wdDoc.MainDocumentPart.HeaderParts
For Each currentText In headerPart.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
If (currentText.Text.Contains("$doc-description$")) Then
Console.WriteLine("found")
currentText.Text = currentText.Text.Replace("$doc-description$", "replaced-text")
End If
Next
Next
End Using
thanks for the reply actually works :)
I also tried with the following code:
For Each headref In mainDoc.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.HeaderReference)()
headerRelationshipId = headref.Id.Value
headerType = headref.Type.Value.ToString()
Dim header01 As DocumentFormat.OpenXml.Wordprocessing.Header = DirectCast(wdDoc.MainDocumentPart.GetPartById(headerRelationshipId), HeaderPart).Header
Dim headerText As New StringBuilder()
For Each text00 As DocumentFormat.OpenXml.Wordprocessing.Text In header01.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
If (text00.Text.Contains("")) Then
text00.Text = text00.Text.Replace("", "replaced-text")
End If
Next
Next
But if I wanted to change the text in a table (instead of a paragraph)?

How to get Description of Youtube embeded videos in my asp.net application?

I am using the below code to get the Title and description of the youtube video embeded in my asp.net application. I am able to see the Title, but not description.
I use Atomfeed to do this...
Problem is i get the Description as "Google.GData.Client.AtomTextConstruct" for all my videos.
Private Function GetTitle(ByVal myFeed As AtomFeed) As String
Dim strTitle As String = ""
For Each entry As AtomEntry In myFeed.Entries
strTitle = entry.Title.Text
Next
Return strTitle
End Function
Private Function GetDesc(ByVal myFeed As AtomFeed) As String
Dim strDesc As String = ""
For Each entry As AtomEntry In myFeed.Entries
strDesc = entry.Summary.ToString()
Next
Return strDesc
End Function
I believe that when the XML from the atom feed is parsed, that the description is not handled. Take a look at this: http://code.google.com/p/google-gdata/wiki/UnderstandingTheUnknown
But what happens with things that are not understood? They end up as
an element of the ExtensionElements collection, that is a member of
all classes inherited from AtomBase, like AtomFeed, AtomEntry,
EventEntry etc...
So, what we can do is pull out the description from the extensionelement like this:
Dim query As New FeedQuery()
Dim service As New Service()
query.Uri = New Uri("https://gdata.youtube.com/feeds/api/standardfeeds/top_rated")
Dim myFeed As AtomFeed = service.Query(query)
For Each entry In myFeed.Entries
For Each obj As Object In entry.ExtensionElements
If TypeOf obj Is XmlExtension Then
Dim xel As XElement = XElement.Parse(TryCast(obj, XmlExtension).Node.OuterXml)
If xel.Name = "{http://search.yahoo.com/mrss/}group" Then
Dim descNode = xel.Descendants("{http://search.yahoo.com/mrss/}description").FirstOrDefault()
If descNode IsNot Nothing Then
Console.WriteLine(descNode.Value)
End If
Exit For
End If
End If
Next
Next
Also, the reason why you are getting "Google.GData.Client.AtomTextConstruct" is because Summary is an object of type Google.GData.Client.AtomTextConstruct, so doing entry.Summary.ToString() is just giving you the default ToString() behavior. You would normally do Summary.Text, but this of course is blank because as I say above, it's not handled properly by the library.
For youtube, I fetch the information for each video using the Google.GData.YouTube.
Something like this returns a lot of information from the video.
Dim yv As Google.YouTube.Video
url = New Uri("http://gdata.youtube.com/feeds/api/videos/" & video.Custom)
r = New YouTubeRequest(New YouTubeRequestSettings("??", "??"))
yv = r.Retrieve(Of Video)(url)
Then it's possible to get the description with: yv.Description

System.InvalidOperationException: This document already has a 'DocumentElement' node

I have a trouble on appending new node to xmldocument (created in the memory). I have select the root node with the XmlDocument.SelectSingleNode() method, it work sometimes and in the other time it will give me "System.InvalidOperationException: This document already has a 'DocumentElement' node." error. More information, this xml document is multi level xml document.
By the way, when i try it with unit test it work fine (always), when i implement it in ASP.NET 3.5, it become weird, work sometimes and fail sometimes. Any idea, why this can help? All advise and suggestion are welcome.
Thanks.
You can select the root node of the XmlDocument using the Property "DocumentElement". Or i think you can use the Property "FirstChild" (untested).
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
XmlElement rootNode = doc.DocumentElement;
This worked for me.
xmlOriginFile = New XmlDocument()
xmlTargetFile = New XmlDocument()
xmlOriginFile.Load(readFile) //readFile is a string that hold path to xml document
xmlTargetFile.Load(writeFile) //writeFile is a string that hold path to xml document
Dim fileNav As XPathNavigator = xmlOriginFile.CreateNavigator()
Dim fileItr As XPathNodeIterator = fileNav.Select("//data")
Dim addToDestNodes As List(Of XmlNode) = New List(Of XmlNode)
While (fileItr.MoveNext())
Dim addNode As XmlNode = CType(fileItr.Current, IHasXmlNode).GetNode()
addToDestNodes.Add(addNode)
End While //loop thru nodes
If addToDestNodes.Count > 0 Then
For Each addedNode As XmlNode In addToDestNodes
Dim addTargetNode As XmlNode = xmlTargetFile.ImportNode(addedNode, True)
xmlTargetFile.DocumentElement.AppendChild(addTargetNode)
Next
End If
xmlTargetFile.Save(xmlTarget) //xmlTarget is a string that hold path to xml document
XML has a root element and you have to add new element within this root element.
XmlElement eleParent = docDestn.CreateElement("EleParent");
XmlElement eleChild = docDestn.CreateElement("Item");
eleParent.AppendChild(eleChild);
XMLNode rootNode= xmlDoc.SelectSingleNode("RootEle");
rootNode.AppendChild(eleParent);
Plps. refer the link for detail: http://navinpandit.blogspot.in/2016/12/exception-this-document-already-has.html

Resources