VB.Net saving word document without prompt - vb.net

Thanks in advance for any help you can give me.
I'm trying to create a VB application that will open an existing Word document, make some changes and save it with a new file name. Making the changes to the document is easy. Saving the document seems like it should be just as easy but there is one serious problem. When I try to save the document, the save as dialog opens. This is supposed to be automated so that doesn't work. I have tried a whole bunch of variations of:
Sub Main()
Dim oWord As Word.Application
Dim oDoc As Word.Document
Dim fileName As String
Dim templateName As String
Dim newFileName As String
'Start Word and open the document template.
oWord = CreateObject("Word.Application")
oWord.Visible = False
oWord.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone
templateName = "C:\tmp\template.dotx"
fileName = "C:\tmp\document.docx"
newFileName = "C:\tmp\new document.docx"
oDoc = oWord.Documents.Add(templateName)
'oDoc = oWord.Documents.Open(fileName) I have tried both using a template and opening a docx file.
<make changes>
oDoc.SaveAs2(newFileName)
oWord.Documents.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
oWord.Application.Quit()
oWord = Nothing
End Sub
It always stops here:
oDoc.SaveAs2
and opens the save as dialog. I need to find a way to suppress the save as dialog or a new way of editing the word files. Everything I have found so far about the problem has either not been solved/updated or was related to Word addins. I don't have any of the addins that people said caused the problem. To be safe, I disabled all word addins.
I would appreciate it if anyone has either solved it or has a different approach. I'm not stuck on the idea of using VB. The only reason I'm going this route is because I think it gives me the best library for editing charts and formatting the documents.
Thanks, Steve

I found the problem. The answer lies in what I was doing in the part I omitted where I was making changes to the document. Part of those changes are to update data in the charts in the document. I had something like:
For Each oShape As Word.InlineShape In oDoc.InlineShapes
If oShape.HasChart And oShape.Range.Bookmarks.Item(1).Name = "ChartName" Then
Console.WriteLine("Updating ChartName")
Dim oWorkbook As Excel.Workbook
oWorkbook = oShape.Chart.ChartData.Workbook
oWorkbook.Worksheets(1).Range("B2").FormulaR1C1 = "9"
oWorkbook.Worksheets(1).Range("B3").FormulaR1C1 = "5"
oWorkbook.Worksheets(1).Range("B4").FormulaR1C1 = "1"
oWorkbook.Application.Quit()
End If
Next
I changed it to:
For Each oShape As Word.InlineShape In oDoc.InlineShapes
If oShape.HasChart And oShape.Range.Bookmarks.Item(1).Name = "ChartName" Then
Console.WriteLine("Updating ChartName")
Dim oWorkbook As Excel.Workbook
oWorkbook = oShape.Chart.ChartData.Workbook
oWorkbook.Worksheets(1).Range("B2").FormulaR1C1 = "9"
oWorkbook.Worksheets(1).Range("B3").FormulaR1C1 = "5"
oWorkbook.Worksheets(1).Range("B4").FormulaR1C1 = "1"
oShape.Chart.Refresh()
oWorkbook.Close(True)
End If
Next
Now it works

myDoc.SaveAs(fileNameAndPath)
Works for me in Word 2007

Related

Printing pdf through automating word with VB net without showing dialog

I've finally encountered a problem, where I didn't already find the answer here or anywhere else on the web:
My program grabs some measurement values from an instrument (I cannot directly control it so I have to wait until the measurement was done by the user and parse the report), calculates some derived values and shall put these values back into the pdf report, which was automatically generated by the instrument control software.
It all works until I come to the line where the printout is started. It always opens the word print dialog instead of silently overwriting my file. I actually don't understand what I am doing wrong when calling PrintOut.
Here is the example code:
Imports Microsoft.Office.Interop
Module Example
Private Sub PrintReport()
Dim intAnswer As Integer
Dim strReportFileName As String = ""
Dim appWord As New Word.Application
Dim wdDoc As Word.Document
dim strPPF as string = "0.5" 'For testing, normally a parameter
dim strFolder as string = "C:\UVVis-Data" 'For testing, normally a parameter
'Find and open the PDF file of the report:
strReportFileName = (From fi As IO.FileInfo In (New IO.DirectoryInfo(strFolder.GetFiles("*.pdf")) Order By fi.LastWriteTime Descending Select fi)(0).FullName 'It will be always the newest file in that folder
appWord.Visible = False 'hide word from the user
wdDoc = appWord.Documents.Open(strReportFileName) 'open the PDF report
'Replace the placeholders which were defined in the report template earlier:
With appWord.Selection.Find
.Text = "#PPF#"
.Replacement.ClearFormatting()
.Replacement.Text = strPPF
.Execute(Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)
End With
'Print out the modified report:
'wdDoc.PrintOut(False, False,, strReportFileName,,,,,,, True) 'this was my first approach
wdDoc.PrintOut(Background:=False, Append:=False, OutputFileName:=strReportFileName, PrintToFile:=True) 'this also doesn't work as intended
'Close the file and restore word to it's normal state:
wdDoc.Close(Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges)
appWord.Visible = True
appWord.Quit()
End Sub
end Module
Use the Document.ExportAsFixedFormat method which saves a document as PDF or XPS format.
Public Sub ExportAsFixedFormat_Example()
wdDoc.ExportAsFixedFormat pbFixedFormatTypePDF, "pathandfilename.pdf"
End Sub
Thank you for the input.
I found a second problem with my code: I cannot overwrite the original document once it is open in word.
I solved this by first moving the pdf to a temporary folder, opening that temporary file in word and deleting it after word is closed.

How to check pdf check box

I am trying to read one pdf and a VBA userform and then fill out another pdf.
I wrote code to read all text in a pdf and then find certain sub strings based on tokens that I can find in the string. It is intended to populate the fields in the destination pdf based on the substrings and check the appropriate text boxes based on the user form. I can get the code to fill the substrings and then save the document, but it won't check the boxes.
Before the code used a AVDoc, but I switched to a JSO because I don't want the pdf to pop up, and the jso avoids that problem.
I tried pdfBool.value = cBool(vbaBool), pdfBool.value = 1, pdfBool.value = "1", jso.setValue("checked"), jso.setValue("yes"), etc.
This code will run without crashing. I reduced the number of variables to one string and one bool for the sake of the example.
Sub main()
‘findString grabs all text from a pdf file. This code works.
Dim mystr As String
If findString(mystr) = False Then
Application.StatusBar = "Cannot find Source PDF"
Exit Sub
End If
Dim mypath As String
mypath = ActiveWorkbook.Path & "\destination.pdf"
Dim aApp As acrobat.AcroApp
Dim pdfDoc As acrobat.CAcroPDDoc
Dim jso As Object
Set aApp = CreateObject("AcroExch.App")
Set pdfDoc = CreateObject("AcroExch.PDDoc")
If pdfDoc.Open(mypath) = True Then
Set jso = pdfDoc.GetJSObject
Dim vbaText As String
Dim vbaBool As String
vbaText = returnString("Token1")
vbaBool = userForm.checkBox1.value
Dim pdfText As Object
Dim pdfBool As Object
Set pdfText = jso.getField("TextField1")
Set pdfBool = jso.getField("CheckBox1")
pdfText.Value = vbaText
pdfBool.Value = vbaBool
'save pdffile
Dim fileSavePath As String
fileSavePath = ActiveWorkbook.Path & "\My Save File.pdf"
pdfDoc.Save PDSaveFull, fileSavePath
'clean up memory
Set pdfDoc = Nothing
Set pdfText = Nothing
Set pdfBool = Nothing
Set jso = Nothing
End If
aApp.Exit
Set aApp = Nothing
Unload userForm1
End Sub
Ok, so after some searching, I have found a solution. Basically, forms created using Living Cycle don't work well with checkboxes. I asked somebody in my organization and they confirmed that Living Cycle was used on forms for a while until we got rid of it. Honestly, I don't know what Living Cycle is, but the solution seemed to work and so I think whatever the issue was related to something called "Living Cycle".
The solution? Redo the pdf form: I exported the pdf to an Encapsulated PostScript file. This stripped away all the fields. After that, I used the prepare form tool which automatically found all the relevant fields. Fortunately, with my pdf, it found all of the fields perfectly, though there was one or two extra ones that I had to delete. The field names and the code need to match so adjustments need to either be made to the PDF or to the code, but once I made that adjustment, everything was perfect.
Try jso.getfield(pdfFieldName).Value = "Yes" or "No". The value is case sensitive so you have to use Yes or No.

Automation of PDF String Search using Excel VBA - OLE error

I'm getting this error, "Microsoft Excel is waiting for another application to complete an OLE action" when trying to automate a PDF string search and record findings in excel. For certain PDFs this error is not popping. I assume this is due to the less optimized PDFs taking a longer time to search string while indexing page by page.
To be more precise, I have a workbook containing two sheets. One contains a list of PDF file names and the other has a list of words that I want to search. From the file list the macro would open each PDF file and take each word from the list of words and perform a string search. If found it would record each finding in a new sheet in the same workbook with the file name and the found string.
Below is the code I'm struggling with. Any help is welcome.
Public Sub SearchWords()
'variables
Dim ps As Range
Dim fs As Range
Dim PList As Range
Dim FList As Range
Dim PLRow As Long
Dim FLRow As Long
Dim Tracker As Worksheet
Dim gapp As Object
Dim gAvDoc As Object
Dim gPDFPath As String
Dim sText As String 'String to search for
FLRow = ActiveWorkbook.Sheets("List Files").Range("B1").End(xlDown).Row
PLRow = ActiveWorkbook.Sheets("Prohibited Words").Range("A1").End(xlDown).Row
Set PList = ActiveWorkbook.Sheets("Prohibited Words").Range("A2:A" & PLRow)
Set FList = ActiveWorkbook.Sheets("List Files").Range("B2:B" & FLRow)
Set Tracker = ActiveWorkbook.Sheets("Tracker")
'For each PDF file list in Excel Range
For Each fs In FList
'Initialize Acrobat by creating App object
Set gapp = CreateObject("AcroExch.App")
'Set AVDoc object
Set gAvDoc = CreateObject("AcroExch.AVDoc")
'Set PDF file path to open in PDF
gPDFPath = fs.Cells.Value
' open the PDF
If gAvDoc.Open(gPDFPath, "") = True Then
'Bring the PDF to front
gAvDoc.BringToFront
'For each word list in the range
For Each ps In PList
'Assign String to search
sText = ps.Cells.Value
'This is where the error is appearing
If gAvDoc.FindText(sText, False, True, False) = True Then
'Record findings
Tracker.Range("A1").End(xlDown).Offset(1, 0) = fs.Cells.Offset(0, -1).Value
Tracker.Range("B1").End(xlDown).Offset(1, 0) = ps.Cells.Value
End If
Next
End If
'Message to display once the search is over for a particular PDF
MsgBox (fs.Cells.Offset(0, -1).Value & " assignment complete")
Next
gAvDoc.Close True
gapp.Exit
set gAVDoc = Nothing
set gapp = Nothing
End Sub
I have now found the answer to this problem.
I'm using Acrobat Pro and whenever I open a PDF file, it opens with limited features due to Protected View settings. If I disable this function or if I click Enable All Features and save changes to the PDF files, VBA macro runs smooth.
It's funny, I'm posting an answer to my own problem.

Edit links to a file in VBA (in Publisher)

I am trying to edit the links to a lot of Excel file using Publisher. Given that Microsoft seems to not allow to use relative links, I am trying to create something similar in VBA. I did not have found a lot of documentation online, just some reference to LinkSources.
Is there anyway possible to change those links with VBA?
I assume you know how to add the reference to the Excel object library. Then to read the links:
dim xl as New Excel.Application
xl.Visible = True
Dim wb As Workbook
Set wb = xl.Workbooks.Open("C:\path to \Myworkbook.xlsx")
Dim v As Variant
v = wb.LinkSources(xlExcelLinks)
Dim first_link as String
first_link = v(1)
MsgBox "First link is to " & first_link
To change the links:
Dim new_link as String
new_link = "C:\path to\Alternative link.xlsx"
wb.ChangeLink first_link, new_link
Hopefully you get the idea.

Add Word docs to Word App without saving to Filesystem

I'm trying to create word documents on the fly in VB.NET, and I've found that the documentation on all of this seems very scarce. Right now my program works by looping through a database table, and for each row it pulls out the variables. The program then loops through and parses a template word doc, replacing variables in that template with variables from the database, then saving as a new doc.
Instead, for every "new doc" that I would be creating, I want to just append it onto another doc, that way when it comes time to parse 1000 rows in the table, I don't have to create and save 1000 different word documents to the filesystem.
I can't seem to find anything out there about this. Everything mentions merging documents (I actually want to append, not merge) or the only way I can append ("Insert") a document is by using WordApplication.Selection.InsertFile(newWordDocument.FullName). This works, but requires me to save newWordDocument to the filesystem before inserting it.
Is there a way to, while still in memory, add newWordDocument to my WordApplication object?
Here's the pseudocode of what I have now
For each row in TableOfVariables
Dim WordApplication as New Word.Application
Dim tempDoc as New Word.Document
tempDoc = WordApplication.Documents.Add
tempDoc = fillVariablesOfTheDocument(tempDoc, row)
tempDoc.Save() 'This is the problem - it saves as a new file rather than appending into WordApplication
Next
You didn't make an assignment, just a statement with
objWordApp.Documents.Add(tempDoc) 'This is where the problem is!
Dim wordApp as new Microsoft.Office.Interop.Word.Application
wordApp.Visible = true
Dim doc as Word.Document
doc = wordApp.Documents.Add
and you don't have to save it until you are good and ready. This also works
Dim Word As Word.Application
Dim Doc As Word.Document
'Start Word and open the document template.
Word = CreateObject("Word.Application")
Word.Visible = True
Doc = Word.Documents.Add
from http://support.microsoft.com/kb/316383
Took a while, but somehow I found out about MailMerge, which I had no idea existed. Long story short, I can have a template document with variables, and I can have an input excel document. The excel document will have a header row which contains the variable names, and each individual cell of the excel doc will represent the variable that will go into the document. When I execute MailMerge, the template will be replaced with n amount of pages (where n is the number of excel rows). This solves my problem of adding multiple documents to 1 big excel document. I tested this with 1,000 rows in my excel doc, and it worked flawlessly.
Here's the code I ended up with:
Dim wrdSelection As Word.Selection
Dim wrdMailMerge As Word.MailMerge
Dim wrdMergeFields As Word.MailMergeFields
' Create an instance of Word and make it visible.
wrdAppMailMrg = CreateObject("Word.Application")
wrdAppMailMrg.Visible = True
' Add a new document.
wrdDocMailMrg = wrdAppMailMrg.Documents.Open("Template.docx")
wrdDocMailMrg.Select()
wrdSelection = wrdAppMailMrg.Selection()
wrdMailMerge = wrdDocMailMrg.MailMerge()
'Open Data Source
wrdDocMailMrg.MailMerge.OpenDataSource("InputVariables.xlsx", SQLStatement:="SELECT * FROM [Sheet1$]")
' Perform mail merge.
wrdMailMerge.Destination = _
Word.WdMailMergeDestination.wdSendToNewDocument
wrdMailMerge.Execute(False)
' Close the original form document.
wrdDocMailMrg.Saved = True
wrdDocMailMrg.Close(False)
' Release References.
wrdSelection = Nothing
wrdMailMerge = Nothing
wrdMergeFields = Nothing
wrdDocMailMrg = Nothing
wrdAppMailMrg = Nothing
Now I just have to tweak it to make it run faster and clean up the UI, but the functionality is completely there.