OpenXML asp.net loop through header - asp.net

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" />

Related

Upload large file to Microsoft Access

I am quite new to setup a MS Access data base. Just wondering whether there is a way to upload a coma delimited file with more than 1.5 million rows and ignore the first 3 lines (file header) and the last row (footer).
The header for the content of this file is at the 4th row.
Finally i worked it out myself.
the header and the footer are having different number of columns.
I used line input statement to check each line of the my text file.
Here is my code:
Sub FileUpload_CMP_Funding()
Dim sFile, sText As String
Dim dText As Variant
Dim db As Database
Dim rst As Recordset2
Dim i As Long
sFile = "C:\NotBackedUp\testfile\CMPFUNding.out"
Open sFile For Input As #1
Do While Not EOF(1)
Line Input #1, sText
dText = Empty
dText = Split(vText(i), ",")
'My main content has 24 columns
If UBound(dText) - LBound(dText) + 1 = 24 Then
If dText(0) <> "Product ID" Then 'skip the header row at the 4th rows
Set db = CurrentDb
Set rst = db.OpenRecordset("tblCMP_Funding", dbOpenDynaset)
rst.AddNew
rst!ProductID = Trim(Replace(dText(0), """", ""))
rst!FundID = Trim(Replace(dText(1), """", ""))
""
'Update whatever field is required to be updated
rst.Update
Set db = Nothing
Set rst = Nothing
End If
End If
Loop
Close #1
End Sub
Hope it helps anyone who have same requirement

Website won't release file generated with openxml

Here is the situation:
Asp.Net Web Forms site using Open XML to read in a (via a stream) word document (docx). I then insert some text into the document and then write the file back out to a different location. It is then emailed to an end user. All of this works great.
The problem i am running into is that I can't the new file written by the site. I receive the following error:
"The process cannot access the file (file name here) because it is being used nt another process"
I have confirmed that it is the site (or IIS) that is holding on to the file.
Here is the code that reads the original file and generates the new file:
Private Function GetDocument(worddoc As String) As Integer
Dim byteArray As Byte() = File.ReadAllBytes("\\WEB-DEV-1\HR_Documents\" & worddoc)
Using Stream As New MemoryStream()
Stream.Write(byteArray, 0, CInt(byteArray.Length))
Try
'Set Row & Cell variables
Dim rowNum As Integer = 0
Dim cellNum As Integer = 0
'Set File Stream
Using doc As WordprocessingDocument = WordprocessingDocument.Open(Stream, 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 = "Employee Name: " & ddlEmployeeList.SelectedItem.Text
'Supervisor Name Insert
'Check for form
If ddlFormChoice.SelectedIndex <> 2 Then
'Reset row to supervisors row in table
row = tbl1.Elements(Of TableRow)().ElementAt(1)
ElseIf ddlFormChoice.SelectedIndex = 2 Then
'Reset row to supervisors row in table
row = tbl1.Elements(Of TableRow)().ElementAt(2)
End If
If ddlFormChoice.SelectedIndex <> 2 Then
'Reset cell to supervisor cell in row
cell = row.Elements(Of TableCell)().ElementAt(1)
ElseIf ddlFormChoice.SelectedIndex = 2 Then
'Reset cell to supervisor cell in row
cell = row.Elements(Of TableCell)().ElementAt(0)
End If
'Insert selected Employee Name
p = cell.Elements(Of Paragraph)().First()
r = p.Elements(Of Run)().First()
txt = r.Elements(Of Text)().First()
If ddlFormChoice.SelectedIndex <> 2 Then
txt.Text = "Supervisor: " & ddlSupervisorList.SelectedItem.Text
ElseIf ddlFormChoice.SelectedIndex = 2 Then
txt.Text = "Manager/Supervisor: " & ddlSupervisorList.SelectedItem.Text
End If
doc.Close()
End Using
'Save File to temp location
File.WriteAllBytes("\\WEB-DEV-1\HR_Documents\TempDocs\" & worddoc, Stream.ToArray())
Stream.Close()
Stream.Dispose()
Return 1
Catch ex As Exception
Return Nothing
End Try
End Using
End Function
I close the OpenXML doc and the stream as well dispose of the stream but when I try to delete the file from the main sub that called the function I get the error listed above.
What am I missing?? I closed the doc, the stream and disposed of the stream. Why is the site still holding the file?
Note here the line of code that trys to delete the file;
File.Delete("\\Web-Dev-1\HR_Documents\TempDocs\" & fileAttach)
So after most of the day i finally found out what the problem was. After the document was created, saved , and emailed it was being held by the email method. For some reason i thought that when the method finishes that it disposed of the Mail Message but this not the case.
Once I added the dispose line it all worked fine.
Only been Googling for almost two days. :|

Non-printable characters in file names break my recursive file listing VB Script

I created a VB script to recursively list all of its file and subfolder files. The script begins fine but eventually crashes in any folder containing a file with a non-printable character/s in their filenames, i.e. I see little squares when I browse the folder in Explorer. I'm not sure how to change my below error handling to continue when it finds a file with such characters.
Any advice or solutions would be appreciated. Thank you.
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFolder = "C:\Input\"
Set objFolder = objFSO.GetFolder(strFolder)
Set NewFile = objFSO.CreateTextFile("C:\Output\" & objFolder.Name & " FileList.txt", True)
Set colFiles = objFolder.Files
On Error Resume Next
For Each objFile In colFiles
NewFile.WriteLine(objFile.Path)
If Err Then
Err.Clear
End If
Next
ShowSubFolders(objFolder)
Sub ShowSubFolders(objFolder)
Set colFolders = objFolder.SubFolders
For Each objSubFolder In colFolders
Set colFiles = objSubFolder.Files
For Each objFile In colFiles
NewFile.WriteLine(objFile.Path)
If Err Then
Err.Clear
End If
Next
ShowSubFolders(objSubFolder)
Next
End Sub
NewFile.Close
Create the output text file as unicode so it can handle "non printable" characters. Third parameter of CreateTextFile.
Set NewFile = objFSO.CreateTextFile(" ... ", True, True)
EDITED
If you can not work with unicode files, then file/folder names should be converted from unicode to ansi before writing to output file. This will do the conversion
Function Unicode2Ansi( text )
Unicode2Ansi = text
With (WScript.CreateObject("ADODB.Stream"))
' Put data into stream
.Type = 2 '( adTypeText )
.Charset = "x-ansi"
.Open
.WriteText text
'Retrieve data from stream
.Position = 0
Unicode2Ansi = .ReadText
.Close
End With
End Function
And adapt code to call it NewFile.WriteLine Unicode2Ansi(objFile.Path)

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 can i design a CSV file using VB?

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

Resources