PDDoc.Save Adobe Acrobat method not working in Excel VBA - excel

Our office runs Arobat DC Pro and Excel 2016, we have been using the code below (scaled down version) in Excel VBA for years to save active Adobe PDF documents (that is, the open PDF doc that most recently had focus).
Since recently upgrading Arobat DC Pro to a newer version, the Acrobat PDDoc.Save method no longer works. It does not throw an error, it just doesn't save the active PDF.
I have had our IT dept. do an uninstall/reinstall of Acrobat PRO on a couple of computers but code still does not work.
Note, the Adobe Acrobat reference library is selected in VBA.
Any suggestions on how to fix?
Sub SaveActivePDF()
Dim AcroApp As Acrobat.CAcroApp
Dim PdDoc As Acrobat.CAcroPDDoc
Dim avdoc As Acrobat.CAcroAVDoc
Dim boolWasSaved As Boolean
Set AcroApp = CreateObject("AcroExch.App")
Set avdoc = AcroApp.GetActiveDoc
Set PdDoc = avdoc.GetPDDoc
DayTime = Format(Now, "yymmddhmmss")
Username = Environ("USERNAME")
PdfNewPath = "C:\Users\" & Username & "\Desktop\TEST PDF " & DayTime & ".pdf"
boolWasSaved = PDDoc.Save(PDSaveFull, PdfNewPath) '<-- NOT WORKING
If boolWasSaved = True Then
MsgBox "PDF WAS SAVED!"
Else: MsgBox "ERROR - PDF not saved"
End If
End Sub

For the record, access to the Acrobat library was blocked by sofware updates that changed default settings.
The issue was resolved as follows: Open any PDF > Edit > Preferences > Security (Enhanced) > ** UNCHECK ** check box "Enable Protected Mode at startup (Preview)" > exit all PDFs.

VBA idle->press "F2"-> search "AcroPDDoc"->locate its method "Save"
Function Save(nType As Integer, sFullPath As String) As Boolean
In Adobe's acrobatsdk_iacguide.pdf, description of Parameter nType is a little bit confusing. Not sure what integer is for PDSaveFull
nType is a logical OR of one or more of the following flags: PDSaveIncremental — Write changes only, not the complete file. This
will always result in a larger file, even if objects have been
deleted.
PDSaveFull — Write the entire file to the filename specified by
szFullPath.
PDSaveCopy — Write a copy of the file into the file specified by
szFullPath, but keep using the old file. This flag can only be
specified if PDSaveFull is also used.
PDSaveCollectGarbage — Remove unreferenced objects; this often reduces
the file size, and its usage is encouraged. This flag can only be
specified if PDSaveFull is also used.
PDSaveLinearized — Save the file optimized for the web, providing hint
tables. This allows the PDF file to be byte-served. This flag can only
be specified if PDSaveFull is also used.

Related

VBA Sharepoint Check In File after Upload

Been using this code for a while to upload a file to SharePoint and noticed the other day that when the file is uploaded, it is checked out to myself automatically and have to go into SharePoint and manually check-in so that others can view the file. Any way to modify or add to my code below to auto check-in a file after it uploads? Totally stumped and any help would be greatly appreciated.
Sub SharePointUpload()
Dim WSN
Dim spAdd
Set WSN = CreateObject("WScript.Network")
spAdd = "https://mysharepoint/test"
WSN.mapnetworkdrive "N:", spAdd
ActiveWorkbook.Save
Dim SharepointAddress As String
Dim LocalAddress As String
Dim objNet As Object
Dim FS As Object
' Where you will enter Sharepoint location path
SharepointAddress = "\\mysharepoint\test"
' Where you will enter the local file path
LocalAddress = "C:\data\sample_file.xlsm"
Set objNet = CreateObject("WScript.Network")
Set FS = CreateObject("Scripting.FileSystemObject")
If FS.FileExists(LocalAddress) Then
FS.CopyFile LocalAddress, SharepointAddress
Else: MsgBox "File does not exist!"
End If
Set objNet = Nothing
Set FS = Nothing
WSN.removenetworkdrive "N:"
End Sub
I had the same issue with our SharePoint Document library even with option Require Check Out switched off - some documents (Word, Excel) were uploaded as Checked Out automatically (green arrow mark) whereas others were in fact Checked In from upload. Moreover when I wanted to Check In manually such documents, I got error message about missing mandatory field, although there was no field in the library set as mandatory.
The reason in my case was the field Title. This field is presented in library as default text field and it is also presented in Office files. I noticed that for Office files with empty field Title the document is automatically Checked Out during upload. When uploaded document contained some text in Title property, no Check Out was set. I also tried to use workflow to change the Title and then Check Out file (after creation), but it was not working - initial Check In was required to start the workflow. Manual change of document properties works but that's too tedious...
The first programmatic option to handle this issue could be to fill Title property of uploaded document when empty (i.e. add file name or any other text). Should work well with many languages. Example with Python:
from docx import Document
path = 'D:/myfile.docx'
document = Document(path)
document_property = document.core_properties
if not document_property.title:
document_property.title = 'Everything is Awesome'
document.save(path)
In VBA Title should accessible via Wb.BuiltinDocumentProperties("Title").
Another successful option for me was to find column Title in Columns of Document library and rename it to something else (I used Titlex as new name), then try to upload new document with empty Title - this time there was no automatic Check Out for the uploaded document. Then I could set the Titlex back to Title without returning the issue.

Change built-in Document properties without opening

I am attempting to run the below line of code in a sub. The purpose of the sub overall is to automatically create agendas for recurring meetings, and notify the relevant people.
'Values for example;
MtgDate = CDate("11/06/2020")
Agenda ="Z:\Business Manual\10000 Management\11000 Management\11000 Communications\Operations Meetings\11335 - OPS CCAR Performance Review Agenda 11.06.20.docx" 'NB it's a string
'and the problematic line:
Word.Application.Documents(Agenda).BuiltinDocumentProperties("Publish Date") = MtgDate
Two questions:
1) Can I assign a document property just like that without opening the document? (bear in mind this vba is running from an excel sheet where the data is stored)
2) Will word.application.documents accept the document name as a string, or does it have to be some other sort of object or something? I don't really understand Word VBA.
Attempts so far have only resulted in
runtime error 427 "remote server machine does not exist or is
unavailable"
or something about a bad file name.
Although Publish Date can be found under Insert > Quick Parts > Document Property it isn't actually a document property. It is a "built-in" CustomXML part, a node of CoverPageProperties, and can be addressed in VBA using the CustomXMLParts collection.
The CustomXML part is only added to the document once the mapped content control is inserted.
Below is the code I use.
As already pointed out for document properties the document must be open.
Public Sub WriteCoverPageProp(ByVal strNodeName As String, ByVal strValue As String, _
Optional ByRef docTarget As Document = Nothing)
'* Nodes: Abstract, CompanyAddress, CompanyEmail, CompanyFax, CompanyPhone, PublishDate
'* NOTE: If writing PublishDate set the content control to store just the date (default is date and time).
'* The date is stored in the xml as YYYY-MM-DD so must be written in this format.
'* The content control setting will determine how the date is displayed.
Dim cxpTarget As CustomXMLPart
Dim cxnTarget As CustomXMLNode
Dim strNamespace As String
If docTarget Is Nothing Then Set docTarget = ActiveDocument
strNodeName = "/ns0:CoverPageProperties[1]/ns0:" & strNodeName
strNamespace = "http://schemas.microsoft.com/office/2006/coverPageProps"
Set cxpTarget = docTarget.CustomXMLParts.SelectByNamespace(strNamespace).item(1)
Set cxnTarget = cxpTarget.SelectSingleNode(strNodeName)
cxnTarget.Text = strValue
Set cxnTarget = Nothing
Set cxpTarget = Nothing
End Sub
You cannot modify a document without opening it. In any event, "Publish Date" is not a Built-in Document Property; if it exists, it's a custom one.
Contrary to what you've been told, not all BuiltinDocumentProperties are read-only; some, like wdPropertyAuthor ("Author"), are read-write.
There are three main ways you could modify a Word document or "traditional" property (which are the ones you can access via .BuiltInDocumentProperties and .CustomProperties):
a. via the Object Model (as you are currently trying to do)
b. for a .docx, either unzipping the .docx, modifying the relevant XML part, and re-zipping the .docx.
c. For "traditional" properties, i.e. the things that you can access via .BuiltInDocumentProperties and .CustomDocumentProperties, in theory you can use a Microsoft .dll called dsofile.dll. But it hasn't been supported for a long time, won't work on Mac Word and the Microsoft download won't work on 64-bit Word. You'd also have to distribute and support it.
But in any case, "Publish Date" is not a traditional built-in property. It's probably, but not necessarily, a newer type of property called a "Cover Page Property". Those properties are in fact pretty much as "built-in" as the traditional properties but cannot be accessed via .BuiltInDocumentProperties.
To modify Cover Page properties, you can either use the object model or method (b) to access the Custom XML Part in which their data is stored. Method (c) is no help there.
Not sure where your error 427 is coming from, but I would guess from what you say that you are trying to see if you can modify the property in a single line, using the fullname of the document in an attempt to get Word to open it. No, you can't do that - you have to use GetObject/CreateObject/New to make a reference to an instance of Word (let's call it "wapp"), then (say)
Dim wdoc As Word.Document ' or As Object
Set wdoc = wapp.Documents.Open("the fullname of the document")
Then you can access its properties, e.g. for the read/write Title property you can do
wdoc.BuiltInDocumentProperties("Title") = "your new title"
wdoc.Save
If Publish Date is the Cover Page Property, once you have a reference to the Word Application and have ensured the document is open you can use code along the following lines:
Sub modPublishDate(theDoc As Word.Document, theDate As String)
' You need to format theDate - by default, Word expects an xsd:dateTime,
' e.g. 2020-06-11T00:00:00 if you only care about the date.
Const CPPUri As String = "http://schemas.microsoft.com/office/2006/coverPageProps"
Dim cxn As Office.CustomXMLNode
Dim cxps As Office.CustomXMLParts
Dim nsprefix As String
Set cxps = theDoc.CustomXMLParts.SelectByNamespace(CPPUri)
If cxps.Count > 0 Then
With cxps(1)
nsprefix = .NamespaceManager.LookupPrefix(CPPUri)
Set cxn = .SelectSingleNode(nsprefix & ":CoverPageProperties[1]/" & nsprefix & ":PublishDate[1]") '/PublishDate[1]")
If Not (cxn Is Nothing) Then
cxn.Text = theDate
Set cxn = Nothing
End If
End With
End If
Set cxps = Nothing
As for this, "Will word.application.documents accept the document name as a string", the answer is "yes", but Word has to have opened the document already. as mentioned above. Word can also accept an integer index into the .Documents collection and may accept just the name part of the FullName string.
Finally, if you do end up using a "traditional Custom Document Property", even after you have set the property and saved the document (approximately as above) you may find that the new property value has not actually saved! If so, that's down to an old error in Word where it won't save unless you have actually visited the Custom Document Property Dialog or have modified the document content in some way, e.g. adding a space at the end.

Is there a resolution in VBA for the error Run-time error '429' when trying to connect to a website?

I am trying to create a VBA to download a google sheet into excel so I can compile stock market data daily. I would simply use power query for this but I am doing this on my personal laptop which is a mac and does not support power query. I am relatively new to coding so have been leaning on following online instructions. The instruction includes this:
Set objWebCon = CreateObject("MSXML2.XMLHTTP.3.0")
This line when ran creates an error message saying:
"
Run-time error '429':
ActiveX component can't create object
"
I think the issue lies within the fact that the instruction is based on a windows operating system. Any solution I've searched for is specific to windows operating systems.
Does anybody here know if I can change the "MSXML2.XMLHTTP.3.0" part of my code to fit it better to mac? Not sure if this is what needs to be done but any guidance would be super appreciated.
I attached my full code below but feel free to ignore it if not relavent. Thank you!!
Sub DownloadGoogleSheets()
Dim ShtUrl As String, Location As String, FileName As String
Dim objWebCon, objWrit As Object
'Sheet Url
ShtUrl = "https://docs.google.com/spreadsheets/d/1wpA_epxtlz96sxETqKttJwsy9Aubb15H8xslcSQ20T0/export?format=csv&id=1wpA_epxtlz96sxETqKttJwsy9Aubb15H8xslcSQ20T0" & gid = 1319327791
'Location
Location = ThisWorkbook.Path & "\" '/Users/[myName]/Desktop/Stock Analysis/n"
'FileName
FileName = "GoogleSheet.csv"
'Connection to Website
Set objWebCon = CreateObject("MSXML2.XMLHTTP.3.0")
'Writer
Set objWrit = CreateObject("ADODB.Stream")
'Connecting to the Website
objWebCon.Open "Get", ShtUrl, False
objWebCon.Send (ShtUrl)
'Once page is fully loaded
If objWebCon.Status = 200 Then
'Write the text of the sheet
objWrit.Open
objWrit.Type = 1
objWrit.Write objWebCon.ResponseBody
objWrit.Position = 0
objWrit.SaveToFile Location & FileName
objWrit.Close
End If
Set objWebCon = Nothing
Set objWrit = Nothing
End Sub

Using Print Dialog with Excel Object, Will Only Print to Default Printer Despite Dialog Selection

I have made a quick app for a dept at work that takes users input text fields and writes them to an excel object. The challenge of the project was that it needed to create the worksheet, write to it, print it, clear out certain confidential information, then save it, (has to print before being saved). Everything works great except that when I use the print dialog to select which printer to send it to, it will only print to the user's default printer or last printer used. I don't want to change their default printers as that will confuse them and cause chaos with some other software we have that is really particular to it's printing locations. I've searched tirelessly online and only found solutions for if I am printing a word document and not a worksheet object.
I believe this is all the relevant code:
Imports Excel = Microsoft.Office.Interop.Excel
Dim objExcel As New Excel.Application
Dim objWorkbook As Excel.Workbook
Dim objWorksheet As Excel.Worksheet
Dim PrintDialog1 As New PrintDialog()
Dim result As DialogResult = PrintDialog1.ShowDialog()
If result = DialogResult.OK Then
PrintDialog1.PrinterSettings = PrintDocument1.PrinterSettings
objWorksheet.PrintOutEx()
MessageBox.Show(PrintDialog1.PrinterSettings.PrinterName)
MsgBox("Order Printing Completed")
ElseIf result = DialogResult.Cancel Then
objExcel.DisplayAlerts = False
objWorkbook.Saved = True
objWorkbook.Close(False)
objExcel.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(objWorksheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(objWorkbook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(objExcel)
ProgressBar1.Value = 200
ProgressBar1.Visible = False
Exit Sub
End If
Also first question on Exchange, so I don't have a lot of privileges, (aka won't be able to respond to comments right away until allowed), also new to coding in general, and this websites' stricter than MLA question and answer protocol, so be kind.
Open the Printers & Scanners settings in Windows.
At the bottom of your list of printers & scanners make sure that "Allow Windows to manage my default printer" is selected/checked/ticked.
Should fix your problem.

How do I make an Excel VBA Function that works when I reopen the document?

OK, I've just written a very simple VBA script that goes off and grabs the file size of a file found at a specified location (edit update code from dscarr):
Public Function FileSize(path As String) As Variant
On Error GoTo Err_FileSize:
Dim retVal As Variant
Dim filesys As Object
Dim file As Object
retVal = ""
Set filesys = CreateObject("Scripting.FileSystemObject")
Set file = filesys.GetFile(path)
retVal = file.Size
Exit_FileSize: On Error Resume Next
FileSize = retVal
Exit Function
Err_FileSize: retVal = "Error: " & Err.Description
Resume Exit_FileSize
End Function
If I import this into a new workbook, save the document as a "Excel Macro-Enabled Workbook" alongside an empty file called readme.txt and then put "./readme.txt" in A1 and "=FileSize(A1)" in A2, A2 evaluates properly to the file size of readme.txt, 0 bytes. Great. If I then save the document, close and reopen it, I'm warned that macros are disabled. If I enable them, the content of A2 has changed to #VALUE! and nothing I do will make the function work again. Has anyone seen this before, can anyone point out the mistake that I'm making here?
edit: the issue seems to be caused by me using relative paths. I can't explain why it works for a new workbook, but not once saved and reopened, but using absolute paths solves the problem, which as dscarr identified, was a "File Not Found" issue.
I duplicated your code in an Excel 2007 Macro Enabled workbook and found that it worked just fine with the following caveats
It does not automatically update the value (e.g. run the FileSize function) when you open the workbook. This can be compensated for by adding some code to the Worrkbook_Open event handler that calculates the workbook.
I get the #VALUE error when it cannot find the file that is specified. Indeed, when the file is missing or incorrectly named the line "Set file = filesys.GetFile(path)" throws the error number 53 "File Not Found". In this case the return value is never set because the line of code that sets it is never called. You could try setting a default value of "File Not Found" before actually attempting to retrieve the file size.
In Excel 2010, Go File->Options->Trust Center->Macro Settings and make sure the Enable option button has been selected.

Resources