Get me started programming and debugging Microsoft Office automation - vba

I'm using Microsoft Office 2003 and creating a bunch of template documents to standardize some tasks. I asked this on Superuser.com and got no response so I'm thinking it's too program-y and hoping I'll have better luck here.
I need to automate a work flow that uses a bunch of Office (mostly Word) templates. What I want is to have "My Template Foo.dot" and "My Template Bar.dot", etc. in the "My Foo Bar Stuff" on a shared drive and have users double click on a template to create a new Foo or Bar.
What's I'd really like is for the user to double-click on the Foo template and be prompted for a couple of items related to their task (e.g., a project number) and have a script in the template change the name that Save will default to something like "Foo for Project 1234.doc".
I asked on Google Groups and got an answer that worked....for a while. Then my AutoNew macro stopped kicking in when I created a new document by double-clicking on the template. I have no idea why or how to debug it.
In Class Modules/This Application, I have:
Sub AutoNew()
Dim Project As String
Project = InputBox("Enter the Project Number")
ActiveDocument.SaveAs "Project " & Project & " Notes.doc"
End Sub
In Microsoft Word Objects/ThisDocument, I have:
Private Sub Document_New()
End Sub
I really have no idea why or where that came from.
In Tools/Macro Security... I have Security Level set to "Low".
I'm a software engineering with 25+ years of experience but a complete Office automation noob. Specific solutions and pointers to "this is how to automate Word" FAQs are welcome. Thanks.
Update: If I create a new template (New..., Blank Document, Save As "My New Template.dot"), and insert the AutoNew() macro, it works. So what's inhibiting it from working on my existing template?
Update 2: Removing the module and function from my old template and adding it back works, too.

You can attach a template to a saved document in ordre to access the macros contained in the template in question.
You can do this with the AttachedTemplate property of a Document object (i.e. ActiveDocument).
Please note that I did not try this myself.
Sub AutoNew()
Dim Project As String
Project = InputBox("Enter the Project Number")
ActiveDocument.SaveAs "Project " & Project & " Notes.doc"
ActiveDocument.AttachedTemplate = "\\path\to\templates\My Template Foo.dot"
End Sub
See MSDN - Word 2003 VBA Language Reference - AttachedTemplate Property
Hope that helps.

Check if the macro is still contained in your template. This sounds stupid but it happended to me, too, in Word 2003 under the following circumstances:
Create a template containing macro,
everything fine
Create a new document file based on
the macro, macro kicks in
Notice I could improve the template
here and there a bit, I do it in the
file created in 2) and SaveAs .DOT
Macro in .DOT GONE!
Why? Because the code stored in the .DOT doesn't go over to the doc file.

Related

Need code help on calling a macro from a new VTSO addin for Word

I have created a new addin with a ribbon in MVS. On click of button1 I want to run a macro that is stored in a .dotm file in the Startup folder in Word. The .dotm file is called MyMacros and the macro is titled "TableMacro".
The module name in Word is titled NewMacros and the top rows of the macro in Word are:
Sub TableMacro()
`
` TableMacro
I am sure the macro is started with the code below but even this is guess:
Private Sub Button1_Click_1(sender As Obeject, e As RibbonControlEventArgs) Handles Button1.Click
`code to call TableMacro'
End Sub
I know how to write macros but I have no idea the code needed to trigger the macro stored in the MyMacros.dotm file.
To search all global templates, including the Building Block template, from a VSTO add-in, you can use this:
Dim wApp = Globals.ThisAddIn.Application
Dim i As Integer, Tmplt As Word.Template = Nothing
For i = 1 To wApp.Templates.Count
If wApp.Templates(i).Name = "MyMacros.dotm" Then
Tmplt = wApp.Templates(i)
wApp.Run(Tmplt.Name & "!TableMacro")
End If
Next
The value of performing it this way is you now have an object variable set to a specific global template and you can then get at AutoText, Styles, etc. and of course macros that are stored in that specific global template.
Your VSTO code has a Microsoft.Office.Interop.Word.Application object. Say you're storing that reference in a variable named hostApp, you could do this:
hostApp.Run("TableMacro")
That requires the .dotm file to be the "active" document. If the document isn't active and you have a reference to it (say, theDocument), I think this might work (untested):
hostApp.Run(theDocument.Name & "!TableMacro")
The object VB.NET uses is the same one VBA uses, so if Application.Run "MyMacros!TableMacro" works in VBA, it will work in VB.NET. I'd try to fiddle in VBA first to get the syntax right - you get instant feedback, vs needing to build and launch the host, load the add-in and test the thing with VSTO.
The following Run syntax worked for me from within a VSTO Add-in to run VBA code in a Template loaded as an add-in. It uses the module name plus the macro name.
Keep in mind that Run can only work with public subs...
Globals.ThisAddIn.Application.Run("Module1.TestPublicVarx")

VBA Dynamic Save As, Microsoft Project to Excel

I am trying to create a macro that will export a Microsoft Project file into an excel file. Through the use of macro recording I have got a line of code that accomplishes this using the export wizard, but I want the file path and file name to be dynamic so I can use this macro on different projects. I have been searching many other threads and the Microsoft website with no luck. Is this possible?
Here is what I have:
sub formatAndSave ()
FileSaveAs Name:="C:\Users\XXXXXX\SharePoint\Projects\ProjectType\HxH\myProject.xlsx",_
FormatID:="MSProject.ACE", map:="myMap"
end sub
One idea I tried was:
Active.Workbook.SaveAs FileName:=Title
Any help would be very much appreciated!
For the sake of simplicity, let's assume for all answers below your project is located at c:\projects\myProj.mpp
I think you're after the string replace function. Something like:
Dim excelFilePath As String
excelFilePath = Replace(ActiveProject.FullName, ".mpp", ".xlsx")
Debug.Print excelFilePath
'the output would be c:\projects\myProj.xlsx
If you're unfamiliar with string manipulation in VB/VBA, just search the web for "VBA string manipulation". Microsoft has a decent article here: https://msdn.microsoft.com/en-us/library/aa903372(v=vs.71).aspx
A few other things that may be handy for you are these variables:
ActiveProject.FullName 'shows full path & name, so you'd get "c:\projects\myProj.mpp"
ActiveProject.Path 'shows just the path, so you'd get "c:\projects\"
ActiveProject.Name 'shows just the file name, so you'd get "myProj.mpp"
Finally, one caveat I've seen is that the ActiveProject.FullName and ActiveProject.Name variables may or may not provide the file extension depending on your local windows environment settings. I've observed that if Windows Explorer is configured to hide file extensions, then these variables also withhold the extension; if Explorer is configured to show them, then they are provided in the variables. Make sure your code is robust to both cases, or make sure you have control over the environment where you code will run.

Macro to save e-mail as text file, to be used in a rule

My problem is very similar to this thread and this one. I think my issue is to combine these two questions.
I am running:
OS: Windows 7 Enterprise Professional
Outlook 2010
VBA version 7.0
By reading these two questions as well as some other pages from Microsoft and elsewhere, I was able to open the VB editor and paste into it, this simple code:
Sub SaveEmail(msg As Outlook.MailItem)
' save as text
msg.SaveAs "C:\Users\mel\mailsave\email.txt" & Format(Now, "YYYYMMDDHHMMSS"), _
olTXT
End Sub
Is the "format" portion of my msg.SaveAs line, going to save a unique text file for each email matching my rule?
How do I run this macro to test and if successful, how do I run it repeatedly?
I tried going to the run menu and selecting run "sub/user form" item but the next dialog box is asking what to run and does not populate a list of macros available for running. Clicked on "save" icon but nothing changed.
Specifying a method with that signature (Sub method (var As Outlook.MailItem)) allows you to use the method when creating a mailbox rule. As far as I understand your question, you're beyond that point.
Question 1
The format portion of your code is only going to save a unique file at most once per second. You're appending the current date and time to the file. Your main problem, however, is not the timestamp, but the file format. You should apply the timestamp before the file extension, e.g.
msg.SaveAs "C:\Users\mel\mailsave\email" & Format(Now, "YYYYMMDDHHMMSS") & ".txt", olTXT
Question 2
If you add the macro to a rule, it will be run when the rule is matched. The macro can be tested by creating a method that grabs the currently selected mail, e.g.
Sub TestSaveEmail()
Call SaveEmail(ActiveExplorer.Selection(1))
End Sub
This macro can then be run by setting the cursor within the method and pressing F5.
The macro can also be added to the Outlook user interface by customizing the ribbon and adding a macro button. For help on customizing the ribbon, refer to the following article:
Customize the ribbon

Word macros not running correctly when opened from PowerPoint action button

I have a Word template (suggestion from) which includes an autonew macro to insert a reference number at a book mark and an action button (Submit)which saves the resulting document with the reference number as part of the file name and closes Word. This works perfectly well when opening the template via Windows Explorer.
We also have a PowerPoint show with action settings hyperlinking to various documents. The link will open the above template OK but does not insert the reference number. Also when the 'submit' button is hit, the file saves as another template with the reference number included.
I am not sure if the issue is Word or PowerPoint-related. The code for the Word template is
Sub AutoNew()
REF = System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", _
"MacroSettings", "REF")
If REF = "" Then
REF = 1
Else
REF = REF + 1
End If
System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", "MacroSettings", _
"REF") = REF
ActiveDocument.Bookmarks("REF").Range.InsertBefore Format(REF, "000#")
End Sub
Private Sub CommandButton1_Click()
REF = System.PrivateProfileString("L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Settings.Txt", _
"MacroSettings", "REF")
ActiveDocument.SaveAs FileName:="L:\Local\Lab\Section - Support Services\Health and Safety\H&S Suggestions\Suggestion " & Format(REF, "000#.doc")
Application.Quit
End Sub
Any help or pointers would be appreciated as if it works I'd like to use for various other templates.
From the description, it's kind of hard to get an accurate idea of what's happening, but it SOUNDS like the the AUTONEW just might not get run in that particular combination.
You could verify this by using some logging or MSGBOX calls to see exactly what macros are being run, when.
Check the docs on Autonew here
http://support.microsoft.com/kb/211659
Sounds like it won't run if the macro is saved in Normal, which doesn't sound like the case here but it's worth noting.
You might also consider using the AutoOpen macro and checking other elements to make sure this is a brand new doc instead of one that's already been saved (like checking the content of the Document.Fullname property).

How to add/Delete lines of code to a "ThisWorkbook" of excel file using vb.net?

As per my application I want to write some Lines code in "ThisWorkbook" of Excel file using vb.net,before that we need to check the file for existance of code.
Please let me know any code or links for reference..
thank you...
It's possible but it's also very likely that the user's macro security settings will prevent this from working initially.
To adjust the security settings (all examples for Excel 2003):
(from a workbook): Tools > Macro > Security > Trusted Publishers
You now need to check the box which says "Trust access to Visual Basic project"
To read the code:
(from the VBA editor): Tools > References and add "Microsoft Visual Basic For Applications Extensibility 5.3" (the actual file is VBE6EXT.OLB)
To work out which VBProject is which, use the FileName property:
For Each vbpItem In Application.VBE.VBProjects
If (vbpItem.FileName = "C:\foo.xls") Then
Set vbpProject = vbpItem
End If
Next vbpItem
Once you have the project, you can refer to the module by name:
vbpProject.VBComponents("ThisWorkbook")
and you can check how many lines there are like this:
If (vbpProject.VBComponents("ThisWorkbook").CodeModule.CountOfLines <> 147) Then
With the CodeModule object, you can read back specific lines (via the Lines property) and change lines (with the ReplaceLine method)
The only thing I can find that would do this is ThisWorkbook.VBProject.VBComponents.Count which counts the number of Modules in your VB solution, which is Sheets + ThisWorkbook + anything additional. I can't find anything that would let you do a diff of the code.
Are you trying to do a security check of some sort? If random code was being inserted into your workbooks, wouldn't a black hat delete this coded in check? Why not just use signatures and digitally sign it?