Closing Word app, vb.net - vb.net

i am trying to search within word documents, using vb.net it worked but i cant seem to close the files after searching them, here is the code i use
how to close the word apps after being searched ?
Dim oWord As Word.Application = Nothing
Dim oDocs As Word.Documents = Nothing
Dim oDoc As Word.Document = Nothing
Dim folderDlg As New FolderBrowserDialog
folderDlg.ShowNewFolderButton = True
If (folderDlg.ShowDialog() = DialogResult.OK) Then
Dim root As Environment.SpecialFolder = folderDlg.RootFolder
End If
Dim l_Dir As IO.DirectoryInfo
Dim fldpath As String = folderDlg.SelectedPath
If IO.Directory.Exists(fldpath) Then
l_Dir = New IO.DirectoryInfo(fldpath)
For Each l_File In Directory.GetFiles(fldpath, "*.docx")
Dim searchFor As String = TextBox1.Text
oWord = New Word.Application()
oWord.Visible = False
oDocs = oWord.Documents
oDoc = oDocs.Open(l_File, False)
oDoc.Content.Find.ClearFormatting()
Dim findText As String = searchFor
Try
If oDoc.Content.Find.Execute(findText) = True Then
MessageBox.Show("OK.")
oWord.NormalTemplate.Saved = True
oWord.ActiveDocument.Close(False)
oDoc.Close()
oWord.Quit()
If Not oDoc Is Nothing Then
Marshal.FinalReleaseComObject(oDoc)
oDoc = Nothing
End If
If Not oDocs Is Nothing Then
Marshal.FinalReleaseComObject(oDocs)
oDocs = Nothing
End If
If Not oWord Is Nothing Then
Marshal.FinalReleaseComObject(oWord)
oWord = Nothing
End If
Else
MessageBox.Show("No.")
End If
Catch ex As Exception
End Try
ComboBox1.Items.Add(l_File)
Next
End If

First thing you should bear in mind is that "releasing the objects" in Word is not as difficult as in Excel and thus you are (unnecessarily) over-complicating things. In any case, you should intend to not over-declare variables (what is the exact point of oDocs?). And, lastly, you should always perform a step-by-step execution when things go wrong to find out what might be happening (you are applying your "objects release" only for "OK" cases, not in any situation: when the result is "No", the objects would have to be released too).
Here you have a corrected code accounting for all the aforementioned issues:
Dim oWord As Word.Application = Nothing
Dim oDoc As Word.Document = Nothing
Dim folderDlg As New FolderBrowserDialog
folderDlg.ShowNewFolderButton = True
If (folderDlg.ShowDialog() = DialogResult.OK) Then
Dim root As Environment.SpecialFolder = folderDlg.RootFolder
End If
Dim l_Dir As IO.DirectoryInfo
Dim fldpath As String = folderDlg.SelectedPath
If IO.Directory.Exists(fldpath) Then
l_Dir = New IO.DirectoryInfo(fldpath)
For Each l_File In Directory.GetFiles(fldpath, "*.docx")
Dim searchFor As String = TextBox1.Text
oWord = New Word.Application()
oWord.Visible = False
Try
oDoc = oWord.Documents.Open(l_File, False)
oDoc.Content.Find.ClearFormatting()
Dim findText As String = searchFor
Try
If oDoc.Content.Find.Execute(findText) = True Then
MessageBox.Show("OK.")
Else
MessageBox.Show("No.")
End If
Catch ex As Exception
End Try
oWord.NormalTemplate.Saved = True
ComboBox1.Items.Add(l_File)
Catch ex As Exception
End Try
oDoc = Nothing
oWord.Quit()
oWord = Nothing
Next
End If
NOTE: note that, when iterating through all the Word files in a folder (and, in general, ones from any MS Office program), you can find temporary copies (starting with "~$...") which might trigger an error when being opened (and thus not allow the object-releasing part to come into picture); also, in general, when opening files something might go wrong; this is what explains the new try...catch I added and why I put the releasing part after it.

I don't know Vb.net, but in F# I used
System.Runtime.InteropServices.Marshal.ReleaseComObject xlApp |> ignore
after ".Quit()", to end the process, but you must search, how to give the name of your word application at the place of xlApp
I will place this after the "End If" at the end.
I hope it will be helpfull for you

Related

Closing word when using interop library - VB.net

I have successfully been able to convert a word doc to pdf - but I can't get the winword process to end.
Dim wordApplication As Object = New Microsoft.Office.Interop.Word.Application
Dim wordDocument As Object
wordApplication.displayalerts = Word.WdAlertLevel.wdAlertsNone
wordDocument = New Microsoft.Office.Interop.Word.Document
'wordDocument = Nothing
Dim outputFilename As String
Dim filename As String
filename = "c:\TestInvoice.doc"
Try
wordDocument = wordApplication.Documents.Open(filename, ReadOnly:=False)
outputFilename = System.IO.Path.ChangeExtension(filename, "pdf")
If Not wordDocument Is Nothing Then
wordDocument.ExportAsFixedFormat(outputFilename, Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF, False, Microsoft.Office.Interop.Word.WdExportOptimizeFor.wdExportOptimizeForOnScreen, Microsoft.Office.Interop.Word.WdExportRange.wdExportAllDocument, 0, 0, Microsoft.Office.Interop.Word.WdExportItem.wdExportDocumentContent, True, True, Microsoft.Office.Interop.Word.WdExportCreateBookmarks.wdExportCreateNoBookmarks, True, True, False)
End If
'Threading.Thread.Sleep(3000)
If File.Exists(System.IO.Path.ChangeExtension(filename, "pdf")) Then
MessageBox.Show(System.IO.Path.ChangeExtension(filename, "pdf"))
End If
'wordDocument = Nothing
'wordApplication.Documents(filename).Close(Word.WdSaveOptions.wdDoNotSaveChanges)
'wordDocument.dispose()
'wordApplication.quit(False)
wordDocument.close()
wordApplication.application.quit(False)
wordApplication = Nothing
I've tried pretty much everything and have been scratching my head for the past few days - can you point me in the right direction?
Have you tried a Using statement?
Try wrapping everything in this.
Using wordApplication As Object = New Microsoft.Office.Interop.Word.Application
End Using

VB.Net: Searching Word Document By Line

I'm attempting to read through a Word Document (800+ pages) line by line, and if that line contains certain text, in this case Section, simply print that line to console.
Public Sub doIt()
SearchFile("theFilePath", "Section")
Console.WriteLine("SHit")
End Sub
Public Sub SearchFile(ByVal strFilePath As String, ByVal strSearchTerm As String)
Dim sr As StreamReader = New StreamReader(strFilePath)
Dim strLine As String = String.Empty
For Each line As String In sr.ReadLine
If line.Contains(strSearchTerm) = True Then
Console.WriteLine(line)
End If
Next
End Sub
It runs, but it doesn't print out anything. I know the word "Section" is in there multiple times as well.
As already mentioned in the comments, you can't search a Word document the way you are currently doing. You need to create a Word.Application object as mentioned and then load the document so you can search it.
Here is a short example I wrote for you. Please note, you need to add reference to Microsoft.Office.Interop.Word and then you need to add the import statement to your class. For example Imports Microsoft.Office.Interop. Also this grabs each paragraph and then uses the range to look for the word you are searching for, if found it adds it to the list.
Note: Tried and tested - I had this in a button event, but put where you need it.
Try
Dim objWordApp As Word.Application = Nothing
Dim objDoc As Word.Document = Nothing
Dim TextToFind As String = YOURTEXT
Dim TextRange As Word.Range = Nothing
Dim StringLines As New List(Of String)
objWordApp = CreateObject("Word.Application")
If objWordApp IsNot Nothing Then
objWordApp.Visible = False
objDoc = objWordApp.Documents.Open(FileName, )
End If
If objDoc IsNot Nothing Then
'loop through each paragraph in the document and get the range
For Each p As Word.Paragraph In objDoc.Paragraphs
TextRange = p.Range
TextRange.Find.ClearFormatting()
If TextRange.Find.Execute(TextToFind, ) Then
StringLines.Add(p.Range.Text)
End If
Next
If StringLines.Count > 0 Then
MessageBox.Show(String.Join(Environment.NewLine, StringLines.ToArray()))
End If
objDoc.Close()
objWordApp.Quit()
End If
Catch ex As Exception
'publish your exception?
End Try
Update to use Sentences - this will go through each paragraph and grab each sentence, then we can see if the word exists... The benefit of this is it's quicker because we get each paragraph and then search the sentences. We have to get the paragraph in order to get the sentences...
Try
Dim objWordApp As Word.Application = Nothing
Dim objDoc As Word.Document = Nothing
Dim TextToFind As String = "YOUR TEXT TO FIND"
Dim TextRange As Word.Range = Nothing
Dim StringLines As New List(Of String)
Dim SentenceCount As Integer = 0
objWordApp = CreateObject("Word.Application")
If objWordApp IsNot Nothing Then
objWordApp.Visible = False
objDoc = objWordApp.Documents.Open(FileName, )
End If
If objDoc IsNot Nothing Then
For Each p As Word.Paragraph In objDoc.Paragraphs
TextRange = p.Range
TextRange.Find.ClearFormatting()
SentenceCount = TextRange.Sentences.Count
If SentenceCount > 0 Then
Do Until SentenceCount = 0
Dim sentence As String = TextRange.Sentences.Item(SentenceCount).Text
If sentence.Contains(TextToFind) Then
StringLines.Add(sentence.Trim())
End If
SentenceCount -= 1
Loop
End If
Next
If StringLines.Count > 0 Then
MessageBox.Show(String.Join(Environment.NewLine, StringLines.ToArray()))
End If
objDoc.Close()
objWordApp.Quit()
End If
Catch ex As Exception
'publish your exception?
End Try
Here's a sub that will print each line that the search-string is found on, rather than each paragraph. It will mimic the behavior of using the streamreader in your example to read/check each line:
'Add reference to and import Microsoft.Office.Interop.Word
Public Sub SearchFile(ByVal strFilePath As String, ByVal strSearchTerm As String)
Dim wordObject As Word.Application = New Word.Application
wordObject.Visible = False
Dim objWord As Word.Document = wordObject.Documents.Open(strFilePath)
objWord.Characters(1).Select()
Dim bolEOF As Boolean = False
Do Until bolEOF
wordObject.Selection.MoveEnd(WdUnits.wdLine, 1)
If wordObject.Selection.Text.ToUpper.Contains(strSearchTerm.ToUpper) Then
Console.WriteLine(wordObject.Selection.Text.Replace(vbCr, "").Replace(vbCr, "").Replace(vbCrLf, ""))
End If
wordObject.Selection.Collapse(WdCollapseDirection.wdCollapseEnd)
If wordObject.Selection.Bookmarks.Exists("\EndOfDoc") Then
bolEOF = True
End If
Loop
objWord.Close()
wordObject.Quit()
objWord = Nothing
wordObject = Nothing
Me.Close()
End Sub
It is a slightly modified vb.net implementation of nawfal's solution to parsing word document lines

Reading line from Word document

I am creating an Excel VBA script to send reports via email. I made the following function to validate an attachment before including it on the email.
The function below will open the word document, check if the first line matches a customer ID and return a bool.
It works, however, when I read the data from Word, it includes some hidden quotes into the text.
While both strings are 123a, when I paste them into another text editor, I see the one i read from Word as "123a". If i print them using MsbBox, both are equal to 123a.
Function ValidateAttachment(attachmentURL As String, customerID As String) As Boolean
Dim oWord As Word.Application
Dim oWdoc As Word.Document
Set oWord = CreateObject("Word.Application")
Set oWdoc = oWord.Documents.Open(attachmentURL)
If StrComp(oWdoc.Paragraphs(1).Range.Text, customerID, vbTextCompare) = 0 Then
ValidateAttachment = True
Else
ValidateAttachment = False
End If
oWord.Quit
Set oWord = Nothing
Exit Function
End Function
This is what i see when i write both results into regular cells. Even I i make a simple formula IF to check for equality, it doesn't work.
Try:
If StrComp(Replace(oWdoc.Paragraphs(1).Range.Text,chr(34),""), customerID, vbTextCompare) = 0 Then
I found how to deal with the invisible quotes.
Using this did the trick:
Application.WorksheetFunction.Clean()
And here is the final code:
Function ValidateAttachment(attachmentURL As String, customerID As String) As Boolean
Dim oWord As Word.Application
Dim oWdoc As Word.Document
Set oWord = CreateObject("Word.Application")
Set oWdoc = oWord.Documents.Open(attachmentURL)
Dim x As String
x = "123a"
Application.Sheets(1).Columns(3).Rows(2) = Replace(oWdoc.Paragraphs(1).Range.Text, Chr(34), "")
If StrComp(Application.WorksheetFunction.Clean(oWdoc.Paragraphs(1).Range.Text), customerID, vbTextCompare) = 0 Then
ValidateAttachment = True
Else
ValidateAttachment = False
End If
oWord.Quit
Set oWord = Nothing
Exit Function
End Function

Word Automation with .NET - Single Landscape pages

I'm trying to set a single page to be landscape, however every method I try changes the entire document rather than the section\paragraph I set PageSetup on. Here's an example, the first page should be portrait and the second should be landscape:
Dim wrdApp As Word.Application
Dim wrdDoc As Word._Document
Public Sub test()
Dim wrdSelection As Word.Selection
Dim wrdDataDoc As Word._Document
Dim sText As String
wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
wrdDataDoc = wrdApp.Documents.Open("C:\Temp\Doc1.docx")
wrdDataDoc.PageSetup.Orientation = WdOrientation.wdOrientPortrait
Dim oPara1 As Paragraph
sText = "Test Report Title"
oPara1 = wrdDataDoc.Content.Paragraphs.Add
oPara1.Range.Text = sText
oPara1.Range.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter
oPara1.Range.InsertParagraphAfter()
Dim para As Word.Paragraph = wrdDataDoc.Paragraphs.Add()
para.Range.InsertBreak()
wrdApp.Selection.GoTo(Word.WdGoToItem.wdGoToLine, Word.WdGoToDirection.wdGoToLast)
wrdDataDoc.Sections(1).PageSetup.Orientation = WdOrientation.wdOrientLandscape
wrdSelection = wrdApp.Selection()
wrdDataDoc.Tables.Add(wrdSelection.Range, NumRows:=9, NumColumns:=4)
With wrdDataDoc.Tables.Item(1)
'Code for table here
End With
End Sub
You need to insert a page break, try this:
oPara1.Range.InsertBreak Type:=wdSectionBreakNextPage
wrdDataDoc.Sections(wrdDataDoc.Sections.Count).PageSetup.Orientation = wdOrientLandscape

VB.Net Split word document into separate documents(pagebreak as delimiter)

A word document has several pages. How to split this pages into separate documents using VB.Net ?
I wish to automate this process.
I used ms tutorial for basic learning: http://support.microsoft.com/kb/316383
But i do not know how to find page breaks in a document and move content of that page to separate document.
Solution:
Private Sub ParseWordDoc(ByVal Filename As String, ByVal NewFileName As String)
Dim WordApp As Microsoft.Office.Interop.Word.Application = New Microsoft.Office.Interop.Word.Application()
Dim BaseDoc As Microsoft.Office.Interop.Word.Document
Dim DestDoc As Microsoft.Office.Interop.Word.Document
Dim intNumberOfPages As Integer
Dim intNumberOfChars As String
Dim intPage As Integer
'Word Constants
Const wdGoToPage = 1
Const wdStory = 6
Const wdExtend = 1
Const wdCharacter = 1
'Show WordApp
WordApp.ShowMe()
'Load Base Document
BaseDoc = WordApp.Documents.Open(Filename)
BaseDoc.Repaginate()
'Loop through pages
intNumberOfPages = BaseDoc.BuiltInDocumentProperties("Number of Pages").value
intNumberOfChars = BaseDoc.BuiltInDocumentProperties("Number of Characters").value
For intPage = 1 To intNumberOfPages
If intPage = intNumberOfPages Then
WordApp.Selection.EndKey(wdStory)
Else
WordApp.Selection.GoTo(wdGoToPage, 2)
Application.DoEvents()
WordApp.Selection.MoveLeft(Unit:=wdCharacter, Count:=1)
End If
Application.DoEvents()
WordApp.Selection.HomeKey(wdStory, wdExtend)
Application.DoEvents()
WordApp.Selection.Copy()
Application.DoEvents()
'Create New Document
DestDoc = WordApp.Documents.Add
DestDoc.Activate()
WordApp.Selection.Paste()
DestDoc.SaveAs(NewFileName & intPage.ToString & ".doc")
DestDoc.Close()
DestDoc = Nothing
WordApp.Selection.GoTo(wdGoToPage, 2)
Application.DoEvents()
WordApp.Selection.HomeKey(wdStory, wdExtend)
Application.DoEvents()
WordApp.Selection.Delete()
Application.DoEvents()
Next
BaseDoc.Close(False)
BaseDoc = Nothing
WordApp.Quit()
WordApp = Nothing
End Sub
Credit goes to "Jay Taplin"