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)?
Related
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.)
I have a problem to add the href into the Literal control. I spend an hour and didn't work on escape double quot. It shows the text instead of href. Would someone show me how to correct it.
There is my code:
dim id as integer=Cint(txtID.text.tostring())
dim href1 as string
Dim href1 As String = "<a target='_blank' class='body'" & "href='#'"
href = href & " onclick=""openWin('OrderForm/pop.aspx'?cId=" & id & "','',500,270);return false;"">" & Link & "</a>"
Dim ltLink As New Literal
ltLink.Text = href1
pnlLink.Controls.Add(ltLink)
Thanks in advance
Ideally, if you want to create markup at server-side, you want to use server control. It is less error prone than creating them manually.
Dim id As Integer = Convert.ToInt32(txtID.text.tostring())
Dim hyperLink = New HyperLink()
hyperLink.Target = "_blank"
hyperLink.CssClass = "body"
hyperLink.NavigateUrl = "~/OrderForm/pop.aspx?cId=" + id
hyperLink.Text = "Open Window"
hyperLink.Attributes("onclick") = "window.open(this.href, 'targetWindow', 'width=500,height=270');return false;"
pnlLink.Controls.Add(hyperLink)
I don't know what is openWin. I just assume you want to open a new windows. If it is a custom fuction, you can just replace mine with yours.
I have a 10 page document. Each page has a header and footer. The header might have two lines of text or one, with each one having a different style. What a want to do is to loop through the document. Read the header and footer of each page, put that into a DataTable so I can build a TOC later on. Any idea, I tried but it's not working correctly, it's not reading each page footer and skipping pages(It seems out of order and I'd like to get the values in the page order since it seems to skip the first page until the last iteration).
Help would be appreciated. JT
Using wordDoc As WordprocessingDocument = WordprocessingDocument.Open(combineDocName, True)
For Each Head As HeaderPart In wordDoc.MainDocumentPart.HeaderParts
For Each currentParagraph As DocumentFormat.OpenXml.Wordprocessing.Paragraph In Head.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph)()
Dim p As ParagraphProperties = currentParagraph.Elements(Of ParagraphProperties)().First()
If p.Count > 0 Then
If (p.ParagraphStyleId IsNot Nothing) Then
If p.ParagraphStyleId.Val.ToString() = "HeaderBar" Then
For Each currentText As Text In Head.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
If (String.IsNullOrEmpty(keepHeaderM)) Then
HeaderBarTxt = currentText.Text.Trim()
ElseIf keepHeaderM <> currentText.Text.Trim() Then
HeaderBarTxt = currentText.Text.Trim()
End If
Next
ElseIf p.ParagraphStyleId.Val.ToString() = "NavigationBar" Then
For Each currentText As Text In Head.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
iCount = currentText.Text.Split(":").Length - 1
If (String.IsNullOrEmpty(keepHeaderM)) Then
HeaderTxt = currentText.Text.Trim()
ElseIf keepHeaderM <> currentText.Text.Trim() Then
HeaderTxt = currentText.Text.Trim()
End If
Next
End If
End If
End If
Next
Next
For Each foot As FooterPart In wordDoc.MainDocumentPart.FooterParts
For Each currentParagraph2 As DocumentFormat.OpenXml.Wordprocessing.Paragraph In foot.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph)()
If currentParagraph2.Count > 0 Then
For Each currentText2 As Text In foot.RootElement.Descendants(Of DocumentFormat.OpenXml.Wordprocessing.Text)()
Dim strTemp As String = currentText2.Text
If strTemp.IndexOf("-") <> -1 Then
FooterTxt = currentText2.Text.Trim()
End If
Next
End If
Next
Next
end using
If you have different headers and footers in the Word file, then I'm assuming that there are multiple sections in your Word document.
You'll have to iterate through these sections and then read the footers and headers in the sections and then save them somewhere in a DataTable.
Coming to the question of creating a TOC.
What you could do is create a separate word document with a TOC created manually say TOC.docx.
Now when you want to add the TOC, you create a copy of TOC.docx and then merge this file with document in which you want to TOC.
Don't forget to set the auto update to true in the settings of the merged document.
<w:updateFields w:val="true" />
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()
In my project I am creating a CSV file, but I want to change it's design. Please help me:
Private Sub ExportDataToCSV()
Dim fileName As String = "CheckRegistrationStatus_" & Format(Now, "yyyyMMddhhmms") & ".csv"
HttpContext.Current.Response.Clear()
' Set the response headers to fit our CSV file
HttpContext.Current.Response.ContentType = "text/plain"
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" & fileName)
Using writer As New System.IO.StreamWriter(HttpContext.Current.Response.OutputStream)
Dim columnHeader As String = String.Empty
For i As Integer = 0 To grd1.Columns.Count - 1
columnHeader += grd1.Columns(i).HeaderText & IIf(i < grd1.Columns.Count - 1, ",", "").ToString()
Next
writer.WriteLine(columnHeader)
'writer.WriteLine(AddCSVHeaderRow()) ' Only if you need custom headers to be added
' Add all the data rows
For Each row As GridViewRow In grd1.Rows
writer.WriteLine(GetCSVLine(row.Cells))
Next
End Using
' End the current response. Otherwise, excel will open with the whole page inside.
HttpContext.Current.Response.End()
End Sub
Private Shared Function GetCSVLine(ByVal cellsToAdd As TableCellCollection) As String
Dim line As String = String.Empty
Dim isFirst As Boolean = True
For Each cell As TableCell In cellsToAdd
If Not isFirst Then
line += ","
End If
isFirst = False
line += """" & Replace(cell.Text, " ", "") & """"
Next
Return line
End Function
Output is being displayed as shown in the following image. But I want to make the header bold and expand the column width . Please help me.
You cannot. The CSV file format is a data-only format. It provides no way to set fonts, column widths or anything else related to styling.
In addition, I don't think your code handles all data correctly. For example, if there's a comma within the data or a double quote, special steps are required. Here's some code I published for creating CSV files in C#.
If you want to produce a formatted Excel document, either in addition to your CSV file or in place of it, you could have a look at the Excel interop libraries.
http://msdn.microsoft.com/en-us/library/bb386107%28v=vs.90%29.aspx
http://support.microsoft.com/kb/301982
http://msdn.microsoft.com/en-us/library/aa188489%28office.10%29.aspx