When I am trying to run the code below the following happens:
1) It opens a "Save PDF File As" Window
2) I have to manually type in the name
3) The code runs
I want to automate steps 1 and 2 so that the code runs without any manual inputs from me and saves it as whatever.pdf in whatever path.
I tried using ExportAsFixedFormat but the problem is that it is saving only the first page as pdf and the remaining 100+ records that are going through the mail merge are not being saved. On top of that, it still opens that Dialog Window from step 1.
ActiveDocument.ExportAsFixedFormat OutputFilename:=whatever.pdf, _
ExportFormat:=wdExportFormatPDF, etc.
The code:
Sub DoMailMerge()
Set myMerge = ActiveDocument.MailMerge
If myMerge.State = wdMainAndSourceAndHeader Or _
myMerge.State = wdMainAndDataSource Then
With myMerge.DataSource
.FirstRecord = 1
.LastRecord = 3
End With
End If
With myMerge
.Destination = wdSendToPrinter
.Execute
End With
End Sub
Any help on this would be greatly appreciated!
[Edit] Corrected object reference. Added SaveAs2
In the OP, an attempt is made to use a pseudo printer to save as a pdf. There are differences between the SaveAs pdf format and the variety of pdf pseudo printers. Is there a reason for printing to a PDF and saving that file, rather than doing a Save As and choosing the PDF format?
With myMerge
.Destination = wdSendToNewDocument
.Execute
End With
ActiveDocument.SaveAs2 "path & filename", wdFormatPDF
The following is sometimes needed to silence prompting with scripted saves. For the above tested method, there were no prompts, so it may not be needed.
Toggle off .DisplayAlerts before SaveAs
Application.DisplayAlerts = wdAlertsNone
ActiveDocument.SaveAs2 "path & filename", wdFormatPDF
Application.DisplayAlerts = wdAlertsAll
Or
Dim tempDisplayAlerts As Long
tempDisplayAlerts = Application.DisplayAlerts
Application.DisplayAlerts = wdAlertsNone
ActiveDocument.SaveAs2 "path & filename", wdFormatPDF
Application.DisplayAlerts = tempDisplayAlerts
Related
Sub CreatePWPDF(DefName, PassPhrase)
'Purpose: Sub to create and password protect PDF copy of the raw workbook
'Function: Utilizes the PDFCreator reference library to create and password protect pdf copies of the raw workbook
'Inputs:
'(1) DefName - The name of the file without the file type extension
'(2) The passphrase to encrypt the PDF
'Notes:
'(1) Requires the PDFCreator reference library enabled to work
'(2) Does not work with PDFCreator version 2.0 or greater since it does not appear to have the PDFCreator reference library
Dim pdfobj As PDFCreator.clsPDFCreator
Dim FPath$, KillFile As String
FPath = ActiveWorkbook.Path & Application.PathSeparator 'Defines the file path. Ensures that the PDF is saved in the same place as the raw workbook
KillFile = FPath & DefName & ".pdf"
Set pdfobj = New PDFCreator.clsPDFCreator 'Define PDF Object variable
With pdfobj
If .cStart("/NoProcessingAtStartup") = False Then 'Check to see if PDFCreator is already running.
MsgBox "Can't initialize PDFCreator. If PDF Creator is already running, close PDFCreator and try again.", vbCritical + _
vbOKOnly, "Critical Error with PDFCreator"
Exit Sub 'If PDFCreator is already running then exit sub. This is necessary in order to prevent errors from occuring.
End If
.cOption("UseAutosave") = 1 'Allows for automatic saving into a directory
.cOption("UseAutosaveDirectory") = 1
.cOption("AutosaveDirectory") = FPath 'Define file path
.cOption("AutosaveFilename") = DefName 'Define file name
.cOption("AutosaveFormat") = 0 ' Set format to PDF
.cOption("PDFUseSecurity") = 1 'Enable password protection
.cOption("PDFOwnerPass") = 1 'Enable editing password
.cOption("PDFOwnerPasswordString") = PassPhrase 'Set editing password
.cOption("PDFDisallowCopy") = 0 'Allow copying of contents in PDF
.cOption("PDFDisallowModifyContents") = 1 'Do not allow modification to PDF
.cOption("PDFDisallowPrinting") = 0 'Allow pdf to be printed
.cOption("PDFHighEncryption") = 1 'Enable strong encryption
.cClearCache 'Clear cache for print job
End With
If Dir(KillFile) <> "" Then 'Deletes existing PDF file with the same name
SetAttr KillFile, vbNormal
Kill KillFile
End If
ActiveWorkbook.PrintOut copies:=1, ActivePrinter:="PDFCreator" 'Print entire workbook to PDF
Do Until pdfobj.cCountOfPrintjobs = 1 'Wait until the entire workbook is printed to PDF
DoEvents 'Wait
Loop
pdfobj.cPrinterStop = False 'Do not stop printer
Do 'Ensure that the file is created before closing PDFCreator
DoEvents 'Wait
Loop Until Dir(FPath & DefName & ".pdf") = DefName & ".pdf"
pdfobj.cClose 'Ensures that PDFCreator closes
Set pdfobj = Nothing
End Sub
My set-up is that I have a bunch of blank templates in a folder. Inside each blank template is a fund code (it is the only thing in the template)
The below macro I created (in an external workbook) goes through the folder with the templates, opens each template, and "fills it out" via a loop.
Basically my macro opens each template, assigns the fund code to a variable and then uses that variable in combination with some text strings to pull in other worksheets/PDF objects related to that specific fund code.
My issue is that in a more meaty version of the below code, I added maybe four or five more PDF objects to insert. It'll go through some of the templates and then randomly stop on a random fund code at a random pdf object insert line saying either "object cannot be found" or "object cannot be inserted"
If I press debug and then press F8 to run that line again, it is able to insert the object no problem. So perhaps my code is running too fast for adobe to handle? I am unsure. Perhaps my code isn't doing things as efficiently as possible. This would save sooo much time for my team, I just can't be having it work half the time.
(also the file names have definitely been correct, so that is not an issue)
Public Sub test()
Set currentbook = ActiveWorkbook
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim wbk As Workbook
Dim filename1 As String
Dim Path As String
Dim a As Long
Path = "C:\Users\Bob\Desktop\Workbooks\"
filename1 = Dir(Path & "*.xlsm")
'--------------------------------------------
'OPEN EXCEL FILES
Do While Len(filename1) > 0 'IF NEXT FILE EXISTS THEN
Set wbk = Workbooks.Open(Path & filename1)
wbk.Activate
'Gets Fund Code
Sheets("Initialize").Select
Dim FdCode As String
FdCode = Worksheets("Initialize").Range("D8")
'--------------------------- PDF ADDS
'Add PDF TB----------------------------------------------------
Worksheets("F.a - Working TB").OLEObjects.Add filename:="C:\Users\Bob\Desktop\Raw Reports\R122 04.30.16 - 04.30.17\" & FdCode & " 04.30.16 TB.PDF", Link:=False, DisplayAsIcon:=False, Left:=40, Top:=40, Width:=150, Height:=10
On Error GoTo 0
'Add PDF Closed Options----------------------------------------------------'
Worksheets("T300.1 - Options (Closed)").OLEObjects.Add filename:="C:\Users\Bob\Raw Reports\Other Reports 04.30.16-04.30.17\Breakout\" & FdCode & " other 04.30.17_ CLOSED OPTIONS POSITION REPORT.PDF", Link:=False, DisplayAsIcon:=False, Left:=40, Top:=40, Width:=150, Height:=10
On Error GoTo 0
ActiveWorkbook.Save
wbk.Close False
filename1 = Dir
Loop
Application.ScreenUpdating = True
End Sub
Here is the software/systems I am using:
Microsoft Office 2010;
Task Scheduler;
Windows Server 2008 R2 Standard
I am running some VBA code within an Excel file that does the following:
1. Retrieves Data from our Database via SQL/ODBC connections
2. Uploads data to a raw data table within the workbook and time stamps the workbook in a cell with the now function
3. Refreshes and formats each pivot table in the workbook
4. Exports and saves specified sheets as a PDF document and saves the document name with the time stamp from step 2
5. Saves the workbook
6. Emails that specific PDF document just created as an email attachment in Excel.
7. Closes the Excel Application
I run this whole series in a private sub called Workbook_Open which checks to see if current time matches the specified runtime. If it does, it runs steps 1-7, if it is an hour later, it closes the workbook (that way I can work on it other than that two hour window).
Here is the code being used:
*Note, this code below is run in the "ThisWorkbook" Excel Object.
'This Macro will use check to see if you opened the workbook at a certain time, if you did, then it will run the Report Automation Macros below.
Private Sub Workbook_Open()
HourRightNow = Hour(Now())
If HourRightNow = 13 Then
Call RefreshDataTables
Call RefreshPivotTables
Call SaveWorkbook
Call ExportToPDFFile
Call EmailPDFAsAttachment
Call CloseWorkbook
ElseIf HourRightNow = 14 Then
Call CloseWorkbook
End If
End Sub
Sub RefreshDataTables()
'
' RefreshDataTables Macro
' This Macro is used to refresh the data from the Dentrix Tables.
'
'This selects the table and refreshes it.
Sheets("raw").Select
Range("D4").Select
Selection.ListObject.QueryTable.Refresh BackgroundQuery:=False
Worksheets("NomenclatureVBA").Range("A2").Formula = "=now()"
End Sub
Sub RefreshPivotTables()
'
' RefreshPivotTables Macro
' This Macro refreshes each Pivot Table in the document.
'
'This goes through each sheet and refreshes each pivot table.
Sheets("D0150 VS D0330 BY BIZLINE").PivotTables("D0150 vs D0330 by BIZLINE").PivotCache.Refresh
Columns("B:DD").Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Sheets("D0150 VS D0330").PivotTables("D0150 COMP EXAM vs D0330 PANO").PivotCache.Refresh
Columns("B:DD").Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
'Formnats to the specific date format below.
End Sub
'--------------------------------------------------------------------------------------------------------------
Sub SaveWorkbook()
' Saves Active (Open) Workbook
ActiveWorkbook.Save
End Sub
'**********************READY************************
'More simplified and tested version of the Export To PDF format
'Make sure to update the filePaths, worksheets,
Sub ExportToPDFFile()
Dim strFilename As String
'Considering Sheet1 to be where you need to pick file name
strFilename = Worksheets("NomenclatureVBA").Range("C2")
Sheets(Array("D0150 VS D0330", "D0150 VS D0330 BY BIZLINE")).Select
Sheets("D0150 VS D0330").Activate
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"\\****(ServerNameGoesHere)****\UserFolders\_Common\DentrixEntrpriseCustomReports\Public\Owner Reports\DataAnalystAutomatedReports\Reports\D0150 COMP EXAM vs D0330 PANO\" & strFilename & ".pdf" _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=False
Sheets("NomenclatureVBA").Select
'This is where the exporting ends, now we will proceed to email the file.
'-----------------------------------------------------------------------------
'The emailing begins here
'This says that if there is a file name stored in the strFileName variable, then....
End Sub
'This Macro Closes the workbook... Note that it closes the very specific workbook you choose.
Sub CloseWorkbook()
'Workbooks("Automated D0150 COMP EXAM vs D0330 PANO.xlsm").Close SaveChanges:=False
Application.DisplayAlerts = False
Application.Quit
End Sub
Then I also have the macro that emails the PDF file in the Modules section of VBA. It looks like this:
Sub EmailPDFAsAttachment()
' Works in Excel 2000, Excel 2002, Excel 2003, Excel 2007, Excel 2010, Outlook 2000, Outlook 2002, Outlook 2003, Outlook 2007, Outlook 2010.
' This example sends the last saved version of the Activeworkbook object .
Dim OutApp As Object
Dim OutMail As Object
Dim FilePath As String
'This part is setting the strings and objects to be things. (e.g. FilePath is setting itself equal to the text where we plan to set up each report)
FilePath = "\\***(ServerGoesHere)***\UserFolders\_Common\DentrixEntrpriseCustomReports\Public\Owner Reports\DataAnalystAutomatedReports\Reports\D0150 COMP EXAM vs D0330 PANO\" _
& Worksheets("NomenclatureVBA").Range("C2") & ".pdf"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
' Change the mail address and subject in the macro before you run it.
'
With OutMail
.To = "email#example.com"
.CC = ""
.BCC = ""
.Subject = Worksheets("NomenclatureVBA").Range("C2")
.HTMLBody = "Hello all!" & "<br>" & _
"Here is this week's report for the Comp Exam vs. Pano." & "<br>" & _
"Let me know what you think or any comments or questions you have!" & "<br>" & _
vbNewLine & Signature & .HTMLBody
.Attachments.Add FilePath
' In place of the following statement, you can use ".Display" to
' display the mail.
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
So this all runs fine when I open up the workbook at the 13th hour (1pm), however, when I try to run this in Task Scheduler during the 13th hour, it runs everything up until the EmailPDFAsAttachment macro/sub and it gets hung up somewhere in the macro and stops running.
I should also state that I have the Trust Center Settings to the following in both Outlook and Excel:
TrustCenterSettings
Anyone know whats causing the macro to run perfectly when I personally open the file and then when I try and open the file via Task Scheduler it stalls in the same spot?
And anyone know how to make it run correctly via Task Scheduler?
Thanks!
We realized that the server limited my permissions in the task scheduler. When I went my IT Director switched my permissions to Admin, it ran the task scheduler perfectly!
Sorry for the false alarm... I wouldn't have posted the question originally, but I spent all last week working on it. Thanks everybody for looking!
That was my guess. You have to mkae sure your password is entered correctly. If you fat-finger a key and enter your password incorrectly, the Task Scheduler will accept it even though it shouldn't. In my opionion, it should prompt the user and notify him/her of the error. Maybe Microsoft will change this sometime in the near future.
I have a VBA script in place so that if a cell is blank then Excel will prompt the file to be saved.
This is ensure that the template is not altered. However, when the user clicks save in the "Save As" dialogue box, the file does not save.
This is the code I am using:
If Worksheets("Input").Range("E2").Value = "" Then
Application.EnableEvents = False
Application.GetSaveAsFilename InitialFileName:="\\ac35542\Problem Management\Action Plans\ChangeMe.xlsm", FileFilter:="Excel Macro-Enabled Workbook (*.xlsm),*.xlsm"
Application.EnableEvents = True
MsgBox "Please ensure fill in the Problem Reference Number, Problem Title, and Select a Contract", vbExclamation, "PR Reference & Title"
Worksheets("Input").Select
Range("E2").Select
End If
Why is the file not saving?
As follow up from MSDN
Application.GetSaveAsFilename displays the standard Save As dialog box
and gets a file name from the user without actually saving any
files..
use this one instead:
Dim fileSaveName
If Worksheets("Input").Range("E2").Value = "" Then
Application.EnableEvents = False
fileSaveName = Application.GetSaveAsFilename(InitialFileName:="\\ac35542\Problem Management\Action Plans\ChangeMe.xlsm", FileFilter:="Excel Macro-Enabled Workbook (*.xlsm),*.xlsm")
Application.EnableEvents = True
If fileSaveName <> "False" Then
Application.DisplayAlerts = False
ThisWorkbook.SaveAs (fileSaveName)
Application.DisplayAlerts = True
End If
MsgBox "Please ensure fill in the Problem Reference Number, Problem Title, and Select a Contract", vbExclamation, "PR Reference & Title"
Worksheets("Input").Select
Range("E2").Select
End If
I think Dmitry Pavliv's method is fine, but I think the "InitialFileName:="\ac35542\Problem Management\Action Plans\ChangeMe.xlsm" part makes it a little bit less dynamic.
For me, the below code worked perfectly:
ExportPath = Application.GetSaveAsFilename(FILEFILTER:="Excel Files (*.xlsx), *.xlsx", Title:="")
'Basically, user will specify the path and give it a name and click on Save. It won't get saved until the next line though.
ActiveWorkbook.SaveAs (ExportPath)
I have a template with a header/footer and text formatting. I would like to write a macro to fill this template with the contents of an .rtf or .doc file. Also, I would like to merge the formatting so that I keep the header and formatting from the template file, and the pictures in the .rtf or .doc files.
Cut-and-paste works great. If I open and save the template file, open the file to insert, select all, and paste special with "merge formatting", then I get exactly what I want. I just want a more scalable solution.
I wrote a macro that does most of this, but it fails to merge the formatting and drops (or hides) the header and footer. I thought the correct approach would use the InsertFile method, but I can't figure it out.
Any pointers would be appreciated (I'm new to both Word and VBA).
Sub InsertFile()
currentPath = ActiveDocument.Path
Set FileBox = Application.FileDialog(msoFileDialogFilePicker)
With FileBox
.Title = "Select the File that you want to insert"
.InitialFileName = currentPath & "\" & "*.rtf"
.AllowMultiSelect = False
If .Show = -1 Then
FiletoInsert = .SelectedItems(1)
End If
End With
Selection.Range.InsertFile FiletoInsert
Set FileBox = Nothing
End Sub
Update - I also tried this approach, which seems to use cut-and-paste, but the results are the same.
Here's the best that I can do. It pastes as plain text, but that's better than nothing (or pasting with original formatting).
Sub InsertFile()
' inserts selected file into current document (strips formatting)
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Title = "Select the File that you want to insert"
.Show
FiletoInsert = .SelectedItems(1)
End With
' get content from my file
Application.Documents.Open (FiletoInsert)
Application.Selection.WholeStory
Application.Selection.Copy
Application.ActiveWindow.Close
' paste without formatting
Application.Selection.PasteSpecial DataType:=wdPasteText
End Sub
Sub InsertFile()
' inserts selected file into current document (strips formatting)
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Title = "Select the File that you want to insert"
.Show
FiletoInsert = .SelectedItems(1)
End With
Selection.InsertFile FileName:=FiletoInsert, Range:="", _
ConfirmConversions:=False, Link:=False, Attachment:=False
End Sub
I've tried this same call in my own VBA macro, and find that
Selection.Range.InsertFile (FiletoInsert)
Seems to work when I only pass the one parameter filename. Make sure the filename is complete.