Setting page layout in MS-project from VBA script - vba

I am working on a script that generates a MS-project plan from inside of excel. All is working fine but I have trouble setting the header and footer. It looks like I need to identify the view name, but I constantly get a runtime error 1101 or some other errors.
I am working on a danish version of MS-project (Side=Page, Sider=Pages) and according to the title of the pagesetup menu my default view is "Gantt-diagram". Also tried with "Gantt Chart" without luck.
Dim pjapp As Object
Dim newproj As Object
Set pjapp = CreateObject("MSProject.application")
pjapp.Visible = True
Set newproj = pjapp.Projects.Add
Set ActiveProject = newproj
' here I want to remove the legend (does not work)
pjapp.FilePageSetupLegendEx Name:="Gantt-diagram", LegendOn:=pjNoLegend
' here I want to set the footer
pjapp.FilePageSetupFooter Alignment:=pjRight
pjapp.FilePageSetupFooter Text:="&[Side] of &[Sider] just some text here"
' setting page to A3 format - this somehow works
pjapp.FilePageSetupPage PaperSize:=8
' here I want to setup the header (does not work)
pjapp.FilePageSetupHeader Name:="Gantt-diagram", Alignment:=pjRight, Text:="My header"

Here are a few things to try:
It looks like you are using early binding (otherwise intrinsic constants like pjNoLegend would cause a debug error), so declare the Project object as their native type (e.g. Dim pjapp As MSProject.Application).
Use FilePageSetupLegend instead of FilePageSetupLegendEx.
Call FilePageSetupHeader using positional arguments rather than the names and skip the view name argument (it will default to the current view). For example: pjapp.FilePageSetupFooter , pjRight, "&[Side] of &[Sider] just some text here"
ActiveProject is a reserved word in MS Project so use a different variable name there or just delete that line of code since you already have an object variable, newproj, and it is already the active project.
Note: To use early binding (easier), include a reference to the Microsoft Project Object Library. To do this, in the VB Editor, go to Tools: References and check the appropriate reference (it might be listed as "Microsoft Office Project Object Library" and will include the version number--I'm using 2013 which is v15.0). Also make sure there aren't any incorrect references checked (e.g. references to the wrong version).

Related

How to load MSXML2.DOMDocument object

I have Word VBA code that is supposed to create an Msxml2.DOMDocument object and load an Xml file into it:
Set XDoc = CreateObject("MSXML2.DOMDocument")
XDoc.async = False: XDoc.validateOnParse = False
XDoc.Load (XmlFileName)
This code runs on my computer.
On a coworker's computer the Load method returns False and doesn't load the data.
I tried switching from MSXML 3.0 to MSXML 6.0 by changing the first line of code to
Set XDoc = CreateObject("MSXML2.DOMDocument60")
as well as changing the project's reference to v6.0. This resulted in failure to create the object, giving the error message
"Runtime error 429: ActiveX component can't create object"
I tried reregistering the .dll files for both MSXML versions, with no effect.
What might be causing the code to run on my machine but not on others?
How might I resolve the respective errors for either v3.0 or v6.0?
I figured out what was causing this problem. The XML file I was trying to load was inside a zip file and before loading it I had to find its name using pattern matching. My coworkers computer had the "File name extensions" checkbox unchecked so the file name that VBA read didn't match the required pattern that included the .xml extension. After I checked the checkbox it worked perfectly.

VBA object to delphi declaration

I have the below VBA code from a vendor website. I managed to import the TLB libraries into a Delphi project and made references to the corresponding unit files. However, I'm struggling to convert the below VBA specific object declaration to Delphi. How do I do this?
Dim app As Attachmate_Reflection_Objects_Framework.ApplicationObject
Dim terminal As Attachmate_Reflection_Objects_Emulation_IbmHosts.ibmTerminal
Dim view As Attachmate_Reflection_Objects.view
Dim frame As Attachmate_Reflection_Objects.frame
Set app = GetObject("Reflection Workspace")
'Get handles to the frame, view, and terminal objects
Set frame = app.GetObject("Frame")
Set view = frame.SelectedView
Set terminal = view.Control
At the end of the Generated Typelibrary is normally a Section with Co Classes. This are the ones you can Use the replace the
Set app = GetObject("Reflection Workspace")
with something like:
MyDelphiComClass := CoReflection_Workspace.Create;
i did not read it, but this seems to have some knowledge in it:Building a COM Client Application
At a first glance it looks somewhat complete.

What to do when I get run time error 91 Object variable or With block variable not set

I'm installing HTML e-mail template in Outlook.
I'm following these guidelines: https://www.outlook-apps.com/insert-html-to-outlook-emails/ (section How to insert clean HTML code to Outlook that has 8 steps).
I did it about a month ago with a success. The html template was able to be nicely opened in Outlook (like it is described in step 8).
Today I've deleted the one that worked and tried to installed a new one. I have no idea what I've done differently but it does not work anymore.
I get the error: run time error 91 Object variable or With block variable not set
The only code that I actually write in is the one that I copy paste from step 5 and then I write the following path:
C:\Users\Maja\Documents\news.html - Because this is where my html template is placed.
What I expect is that when I do step 8, a new e-mail with my html template (news.html) would open.
Most probably a new email is opened in the Explorer window. The code listed on the page uses the ActiveInspector property which returns the topmost Inspector object on the desktop. If there is no inspector window shown you may get the error described in your post.
Anyway, I'd suggest setting a breakpoint in VBA editor and run the code under the debugger attached.
Try to remove the condition from the code:
Dim insp As Inspector
Dim wordDoc As Word.Document
Set insp = ActiveInspector
Set wordDoc = insp.WordEditor
wordDoc.Application.Selection.InsertFile "e:\test.html", , False, False, False
Problem solved. I was foolish enough to not having first opened a new Outlook email and only than go to Developer tab -> Macros to select my template.
That is probably why I had this error with the email being opened in Explorer window, like Eugene has suggested.

Making QRCode ActiveX Control for MS Access: Control Source Property

I wanted to implement a QR Code to Access2010 and I found https://github.com/yas78/QRCodeLibVBA. Referencing XLAM from Access did not work and I didn't want to insert all modules directly to Access as it makes the project messy.
So I decided to create an OCX file using ancient VB6 as it seemed to be the easiest way to encapsulate all the bits together into one simple object.
Finally, I have made an OCX that has several key properties: DataString which is the string to be displayed, ByteModeCharsetName, ErrorCorrectionLevel, ForeRGB and BackRGB, there are also methods Refresh, Cls and events OnClick and OnDblClick
It works fine in VB6 apps + Excel sheets + Excel forms but it behaves weird in Access forms, reports, etc.
Everything looks as one would expect in Excel:
This is how it looks in Access:
The custom properties are visible on the tab "Other" but they are not offered in VBA editor at all! However it does compile when entered manually.
Resizing control behaves weird
Control's Events like OnClick are not displayed at tab Event of Property Sheet
Here are my questions:
Are the Controls for Access "different" than for other office apps?
Why the hell are the properties hidden in editor?
How to "move" some properties to other tabs (categories), for example ForeRGB to tab Format (as usual for TextBoxes etc.)?
How to create ControlSource propety (on the DATA tab) which could be directly bound to a recordset without having to use a VBA? This way, I hope, I could use the control on the continuous forms as well. In fact, this is most important question.
Some tips for resizing? (not important)
I think I'm pretty close to my goal but I'm stuck at this point. I know the VB6 is obsolete but after reading Creating Custom Controls for ms access 2010 VB6 seems to be easy choice. Any alternatives for writing OCX?
EDIT: Final working control is available here https://github.com/Combinatix/QRCodeAX
For 4. try setting your control's DataBindingBehavior to vbSimpleBound so that a scalar property (ControlSource in your case) can be bound via DataSource and DataMember properties.
For 3. use Tools->Procedure Attributes... menu, select ControlSource in Name, expand Advanced>> and select Data in Property Category combobox. You can do the same through Object Browser (F2). Find your control, right click your property/method (should be bold) and choose Properties... context menu option. This works with methods and is more versatile than Tools->Procedure Attributes... approach.
To answer your questions one by one:
Yes. ActiveX controls in Access are certainly different than in other Office applications.
In Access, there's one general CustomControl control that encapsulates all ActiveX controls, and offers a default set of events, properties and methods for any control, such as border properties, the requery method, and the enter event.
The object of the control being encapsulated can be accessed by using the CustomControl.Object proprty
These properties aren't displayed because you're referring to a custom control in the general sense, and only get the properties for it.
To get the object you want, use the following:
Dim qrObj As QRCode
Set qrObj = QR.Object
That's plain not possible, tab layout is determined by Access
Also not possible. The ActiveX control must include that functionality, this one doesn't. Generally, using ActiveX controls in continuous subforms to display something different for every row is hard to impossible
Resizing the outer control, and then calling CustomControl.SizeToFit should generally just work
Some of the things I deem not possible can be achieved by modifying the ActiveX Control's source code, of course.
A very different and much less cumbersome approach would be to generate the QR code online and download them to be displayed in a (bound) picture control.
I wrote an article on displaying online images:
Show pictures directly from URLs in Access forms and reports
Some code is, of course, needed, but much less than that at GiHub you refer to, though to much to list here in full.
It uses this function retrieve the images:
' Download (picture) file from a URL of a hyperlink field to a
' (temporary) folder, and return the full path to the downloaded file.
'
' This can be used as the control source for a bound picture control.
' If no Folder is specified, the user's IE cache folder is used.
'
' Typical usage in the RecordSource for a form or report where Id is
' the unique ID and Url is the hyperlink field holding the URL to
' the picture file to be displayed:
'
' - to a cached file where parameter Id is not used:
'
' Select *, UrlContent(0, [Url]) As Path From SomeTable;
'
' - or, where Id is used to create the local file name:
'
' Select *, UrlContent([Id], [Url], "d:\somefolder") As Path From SomeTable;
'
' Then, set ControlSource of the bound picture control to: Path
'
' 2017-05-28. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function UrlContent( _
ByVal Id As Long, _
ByVal Url As String, _
Optional ByVal Folder As String) _
As Variant
Const NoError As Long = 0
Const Dot As String = "."
Const BackSlash As String = "\"
Dim Address As String
Dim Ext As String
Dim Path As String
Dim Result As String
' Strip leading and trailing octothorpes from URL string.
Address = HyperlinkPart(Url, acAddress)
' If Address is a zero-length string, Url was not wrapped in octothorpes.
If Address = "" Then
' Use Url as is.
Address = Url
End If
If Folder = "" Then
' Import to IE cache.
Result = DownloadCacheFile(Address)
Else
If Right(Folder, 1) <> BackSlash Then
' Append a backslash.
Folder = Folder & BackSlash
End If
' Retrieve extension of file name.
Ext = StrReverse(Split(StrReverse(Address), Dot)(0))
' Build full path for downloaded file.
Path = Folder & CStr(Id) & Dot & Ext
If DownloadFile(Address, Path) = NoError Then
Result = Path
End If
End If
UrlContent = Result
End Function
I pasted this URL into a record:
https://chart.googleapis.com/chart?cht=qr&chs=300x300&chl=23457
and it worked right away:
Full code can be found at GitHub: VBA.PictureUrl

Close MS Project using VSTO

I have a VSTO on MS Project. I use VB.NET. What I need is when I press the button I created on the ribbon, it will perform some codes which will update the info of some task, however, I would need to close the MS Project automatically. I tried application.FileCloseEx(), but it only closes the file, the MS Project is still loaded. I need similar to clicking the x button of the window.
Thanks,
Gilbert
If your MS Project application object is represented by "appMSProject" then it's as simple as:
appMSProject.Quit
OR say in a macro running under Project:
Application.Quit
Here's how I do it in VBA from Excel or Access. As far as I can tell the objects & methods are the same in VB.NET. Bottom line is that I create an instance of the MS Project object which starts the app & opens a file, execute some work, close the file, then destroy the MS Project object by setting it to Nothing. That has the effect of closing the app. You can also use "appMSProject.Quit" followed by setting it to Nothing. Frankly the 2nd option looks more orderly & easier to understand in code. Anyway, here's a sample of the way I do it:
Dim appMSProject As MSProject.Application
Dim prjPrj As MSProject.Project
Dim strPrjFile As String
strPrjFile = "C:\where_is_my_file\file_name.mpp"
Set appMSProject = New MSProject.Application
appMSProject.FileOpenEx Name:=strPrjFile
Set prjPrj = appMSProject.ActiveProject
'''Do something in here with the prjPrj
'Close the file, in my case w/o saving
appMSProject.FileCloseEx pjDoNotSave
'Destroy the objects
Set prjPrj = Nothing
Set appMSProject = Nothing
FYI - In this example I'm doing background work so I don't show the app. I also use "early binding".
Here's an MSDN example that does show the app with more info on early -vs- late binding - https://msdn.microsoft.com/en-us/library/office/ff865152.aspx