VBA; Open PDF in existing PDF window (as a new tab) - vba

I am trying to use VBA to open a PDF in an existing Adobe Acrobat window.
Currently, however, my code is opening the pdf in a separate Adobe window each time it is run.
End goal: VBA opens a PDF in an existing Adobe acrobat window in the form of a new PDF tab.
Here is my code:
Sub openPDF(sPath As String)
Dim primaryDoc As Object, PrimaryAVDoc As Object, appAdobe As Object ' Open Adobe instance
Dim zPath As String
Dim adobeDoc As Variant, PDFPageView As Variant
Set appAdobe = CreateObject("AcroExch.App")
' Create Adobe PDF object
Set primaryDoc = CreateObject("AcroExch.PDDoc")
Set PrimaryAVDoc = CreateObject("AcroExch.AVDoc")
If PrimaryAVDoc.Open(sPath, "") = True Then
PrimaryAVDoc.BringToFront
Call PrimaryAVDoc.Maximize(True)
Set PDFPageView = PrimaryAVDoc.GetAVPageView()
' Zoom (optional)
' Call PDFPageView.ZoomTo(2, 50)
End If
Set primaryDoc = Nothing
Set PrimaryAVDoc = Nothing
Set appAdobe = Nothing
End Sub

Whilst heavily used by programmable graphics applications, generally:-
This is a user application setting (depending on version user interface) it is unlikely to be externally program related (but see note below). Each user installation, just like in a browser, has user settings/preferences and this is thus a user run time option. I am not going to install every version or yours just to prove your user version does or does not have the required setting.
Many PDF viewers have legacy and Tabbed mode options (often addressable via DDE in Windows or Pipes in other systems) that may or may not be externally addressable for reuse windows. Those that are SyncTeX Aware usually have widest range of settings for external IDE calls. Adobe is SyncTeX Aware but offers fewer choices.
Here the upper quartiles setting is open as separate windows.
Lower view all files are now opened in tabs mode.

Related

Lotus Notes VBA make MS Word visible

All,
I am trying to use MS Word to print the current web page.
I have a print button that call an agent and run on the server.
The problem is that it make MS Word visible on the server console and not on the user machine.
If I run my agent locally, it will make MS Word visible on the user (or my machine).
I know this is all working like it should but I am wondering if there is a way to make MS Word visible when called from a button on the web calling an agent.
this is some of the code I am talking about:
Dim objWord As Variant
Dim docWord As Variant
Set objWord = CreateObject("Word.Application")
objWord.Visible = true
Dim object As NotesEmbeddedObject
Dim rtitem As Variant
Set docWord = objWord.Documents.Open("L:\Lotus\Domino\data\domino\html\Attachments\cal\templates\gage-grid111.docx")
Basically no. All LotusScript on the web runs on the Domino server and can't do anything with client software, and there's nothing you can do about that as far as I know.
Some alternatives might be possible depending on the requirements of your application.
Firstly, does the thing you're printing have to be a Word document? If the same content can be generated with HTML and CSS, then you could open that as a normal web page and print it using client-side javascript.
If it really must be a Word document, then one of the following options might suit you:
Store the Word document in a Notes document accessible to the web user, or in some other server-side location accessible by a URL, then show the web user a link to the Word document so they can download and print it; or...
I've never tried this, but it might be possible to control Word on the client machine using ActiveXObject in javascript, or there may be some other Windows-only javascript feature to do this. If this is possible, browser support is likely to be limited, and subject to security restrictions.
What exactly do you mean by "use Word to print the current page"? If it's the exact contents of the screen, why use Word when a browser can print the page? How is your web page created, using a Notes form or XPages?
Probably the best you can do is use CSS directives for when the document is printed. Either make a 2nd form that displays the data exactly as you want them printed, or put a hidden div in the same form (e.g. at the bottom) that contains the info to be printed. Use CSS in such a way that the original info isn't printed, only the normally hidden div.
You could print to a PDF file, I don't know if/how printing to Word works.

In vb.net when calling a method from an instance of Outlook.Application, a pop up halts code execution

We have a vb.net windows application that creates an instance of Outlook.Application to open an email .MSG file, and save it as a .HTML by calling the Outlook.Application SaveAs() method.
However, sometimes the call to .SaveAs() causes a popup to appear, for example when saving a .MSG that is digitally signed, there is a confirmation popup.
This popup causes the code execution to halt until the user interacts and clicks YES or NO on the pop up. Since our application runs on a server and requires no user interaction this causes the application to halt periodically until a technician logs into the server and clicks 'yes' on the popup.
Is there a way to avoid this pop up, or have 'YES' automatically get selected?
I've tried investigating the documentation for Outlook.Application but of course the documentation is very lacking on MSDN.
Here is some example vb.net code:
outlookapp = CreateObject("Outlook.Application")
Dim olItem As Object = outlookapp.CreateItemFromTemplate("C:\msg\message.msg")
olItem.SaveAs("C:\html\convertedmessage.html", 5)
If message.msg is digitally signed, when calling SaveAs() to save it as an HTML file, you get a pop up that the MSG is digitally signed, this halts the code until you click yes or no.
Note: Outlook objects do not support the DisplayAlerts flag of Word objects.
Firstly, Outlook is not designed to be used in a service or a server side application with no user present.
In your particular case, you can do the following:
1 Use Extended MAPI (C++ or Delphi only) to open the MSG file (OpenIMsgOnIStg etc.), then construct the HTML file explicitly in your code.
2 Parse the MSG file (its format is documented) or use one of several commercial components (such as the one from Aspose) to read the MSG files.
3 Use Redemption (I am its author) and its RDOSession.GetMessageFromMsgFile / RDOMail.SaveAs(..., olHTML) methods to open the MSG file and perform the conversion.
dim Session As RDOSession = CreateObject("Redemption.RDOSession")
dim Msg As RDOMail = Session.GetMessageFromMsgFile("C:\msg\message.msg")
Msg.SaveAs("C:\html\convertedmessage.html", 5)

Closing the AutomationFactory Object

We currently spin up adobe reader to print out a pdf from our legacy silverlight product which works fine with the following code:
Dim shell = AutomationFactory.CreateObject("Shell.Application")
shell.ShellExecute(path, "", "", "print", 1)
This works great, the problem is that after the printing has been done the Adobe reader application is still left open which is a little annoying to the user base.
My question is how do we close the adobe reader application from code?
Thanks
You cannot.
You call the Adobe Reader and another process, another program is opened. Nothing that you can do anymore but killing the task.
But the problem with killing the task is that you possibly it will close another PDF file opened after your print file be opened in the new instance of Adobe Reader.
I think that's OK in a custom software or in a closed and known environment of users if you choose to kill the Adobe process. But the users should be warned about this behavior. By manual of software or user training.
I used this to send a pdf to the standard printer
Dim pd As New System.Drawing.Printing.PrintDocument
Dim p As New PrintDialog()
p.SelectedPagesEnabled = False
If p.ShowDialog() = True Then
pd.DocumentName = pdfFile
pd.PrinterSettings.PrinterName = p.PrintQueue.Name
pd.PrintController = New System.Drawing.Printing.StandardPrintController()
pd.OriginAtMargins = False
pd.Print()
End If
Maybe works for you you too.

Accessing Excel Object without using Shape.Activate() on a Word document using VBA

I have a tried reading an embedded excel document in a word document. I followed the code specified at this blog article:
http://vbadud.blogspot.com/2010/08/how-to-read-excel-sheet-embedded-in.html
Dim oWB As Excel.Workbook
Dim oIShape As InlineShape
For Each oIShape In ActiveDocument.InlineShapes
If InStr(1, oIShape.OLEFormat.ProgID, "Excel") Then
oIShape.OLEFormat.Activate
Set oWB = oIShape.OLEFormat.Object
oWB.Sheets(1).Range("A1").Value = "ProdID"
End If
Next oIShape
It works fine but the Activate line causes the document to flicker on each excel document I read. I tried to remove the oIShape.OLEFormat.Activate code but it causes the next line to throw a "Runtime error '430' (class does not support Automation or does not support expect).
The question is there any other way to access embedded excel without calling the Activate method?
This is tricky! The short answer is, no. Not with an embedded Excel.
I did some experimentation and some research. Since I could not find any sources that specifically explained the behavior. this is somewhat a guess on my part. It appears that when you embed the Excel spreadsheet into your word document essentially Word stores a link of spreadsheet, which displays only the appearance because it needs to be interpreted with the Excel program. Until you actually active the shape, you cannot interact with it because that cannot be done with Word directly. This article alludes to the behavior, but doesn't explain it. Here's a quote:
If you edit the object in Word, click anywhere outside the object to return
to the destination file.
If you edit the object in the source program in a separate window,
click Exit on the File menu of the source program to return to the
destination file.
You may have noticed that even if you use. Application.ScreenUpdating = false it still does the flickering you mention. This is because you are using a different application when you access the shapes! Every time you active the shape, the object specific menus etc load.
A possible work around:
If instead of embedding Excel Spreadsheets via the insert menu, you can instead add a control. On my machine using Office 2003 the comparible one is: Microsoft Office Spreadsheet 11.0 This is technically a web control, but the methods and behavior are very comparable to an Excel workbook.
Using the control instead of the handy inserted object, with a slight variation of your code I was able to comment out your activate command and the code ran as expected. Specifically, I had to change these lines:
Dim oWB As Spreadsheet instead of Excel.Workbook.
If InStr(1, oIShape.OLEFormat.ProgID, "OWC11.Spreadsheet.11") Then instead of "Excel"
Basically you can decide... Activate your embedded object that requires Excel to interpret, or use a different control that doesn't require activation.

Directory picker for Visual Basic macro in MS Outlook 2007

I wrote a Visual Basic macro for archiving attachments for Outlook 2007, but did not find a totally satisfactory way for showing a directory picker from the Outlook macro. Now, I don't know much about either Windows APIs or VB(A) programming, but the "standard" Windows file dialog I see most often in Microsoft applications would seem like an obvious choice, but it does not seem to be easily available from Outlook's macros.
Ideally, the directory picker should at least allow to manually paste a file path/URI as a starting point for navigation, since I sometimes already have an Explorer window open for the same directory.
What are the best choices for directory pickers in Outlook macros?
Two things I already tried and did not find totally satisfactory are (the code is simplified and w/o error handling and probably also runs in older Outlook versions):
1) Using Shell.Application which does not allow me to actually paste a starting point via the clipboard or do other operations like renaming folders:
Set objShell = CreateObject("Shell.Application")
sMsg = "Select a Folder"
cBits = 1
xRoot = 17
Set objBFF = objShell.BrowseForFolder(0, sMsg, cBits, xRoot)
path = objBFF.self.Path
2) Using the Office.FileDialog from Microsoft Word 12.0 Object Library (via tools/references) and then using Word's file dialog, which somehow takes forever on my Vista system to appear and does not always actually bring Word to the foreground. Instead, sometimes Outlook is blocked and the file dialog is left lingering somewhere in the background:
Dim objWord As Word.Application
Dim dlg As Office.FileDialog
Set objWord = GetObject(, "Word.Application")
If objWord Is Nothing Then
Set objWord = CreateObject("Word.Application")
End If
objWord.Activate
Set dlg = objWord.FileDialog(msoFileDialogFolderPicker)
path = dlg.SelectedItems(1)
Any other ideas?
Your best bet will probably be to use the Windows32 API for this. See this MSDN article for sample VBA code on how to interact with the API.
The article outlines a few different techniques, but I'd suggest searching the article for "COMDLG32.dll" and following the steps outlined in that section.