CommandBars("Text").Controls not deleted when exiting the document - VBA word add-in - vba

I'm trying to create a add in for MS Word with VBA.
It has a "AutoExec" procedure that creates a new item in the CommandBar("Text") collection (right click menu) and a "AutoExit" that deletes this created item.
As an example, I tried the code below that create an item "How Many Pages?", which executes a macro displaying the number of pages in the active document.
This is the AutoExec Code:
Public Sub AutoExec()
Dim objcommandbutton As CommandBarButton
Call MsgBox("AutoExec")
Set objcommandbutton = Application.CommandBars("Text").Controls.Add _
(Type:=msoControlButton, Before:=1)
objcommandbutton.Caption = "How Many Pages?"
objcommandbutton.OnAction = "HowManyPages"
End Sub
This is the AutoExit Code:
Public Sub AutoExit()
Dim objcommandbutton As CommandBarControl
Call MsgBox("AutoExit")
For Each objcommandbutton In Application.CommandBars("Text").Controls
If objcommandbutton.Caption = "How Many Pages?" Then
objcommandbutton.Delete
End If
Next objcommandbutton
End Sub
This is the Main Macro Code:
Public Sub HowManyPages()
If Documents.Count > 0 Then
Call MsgBox(ActiveDocument.BuiltInDocumentProperties("Number of Pages"))
Else
Call MsgBox("No document is currently active.")
End If
End Sub
When exiting the document, the Button previously added in CommandBars("Text") collection is not deleted. I see this when I open a new blank Word document and the button remains in the right click menu.
I know that the routine is performed correctly because there is a MsgBox instruction to verify it.
This only happen with the AutoExit subroutine of a add-in, that is, loaded as a add-in: running the code in a macro with vba module works fine.
Any help?

When working with the CommandBars object model in Word it's necessary to always specify the Application.CustomizationContext.
Word can save keyboard layouts and CommandBar customizations in various places: the Normal.dotm template, the current template or the current document. The default when you create a CommandBar addition may not be the3 same as the default when trying to delete something.
Since this is an add-in, I assume you want the change for the entire Word environment (any open document). In that case, use the context NormalTemplate. Use this before any calls to CommandBar:
Application.CustomizationContext = NormalTemplate
Note: for saving a customization in the current document: = ActiveDocument; for saving in the template attached to the current document: = ActiveDocument.AttachedTemplate.

I solved my problem with a workaround:
I was trying to "add" a template (.dotm) as a add-in (in the "Templates and Add-ins" window) to use my VBA project in a new document. That's why I was using the AutoExec() and AutoExit() procedures.
But only now I figure out that just "attaching" the .dotm template to the active document (in the same "Templates and Add-ins" window, as show in the figure below) makes the functions Private Sub Document_Open() and Private Sub Document_Close() to run normally. Which solves my problem.
Even so, I think there is a certain "issue" with the AutoExit() procedure when trying to change the CommandBars itens. But that's ok for now.
enter image description here

Related

Outlook Custom Form Script Won't Run

Since the most recent security update for Outlook my code won't run. Using Outlook 2010. Have a contact form with custom code behind. I click a custom button to open a post item in the History folder. The post item has custom code behind it to write information to a text file. Very important for this to run. Since a few days ago the code on the post item doesn't run anymore. But if I save the post item, close it and reopen it the code runs fine. What is happening and how do I fix it?
'this is the code on the contact form
Sub CallFromButton
'get the folder
Dim HistFolder
Set HistFolder = Application.Session.GetDefaultFolder(18).Folders("History")
'add a post item
Dim blgItem 'PostItem
Set blgItem = HistFolder.Items.Add("IPM.Post.ClientHistory2")
'set some information
blgItem.BillingInformation = "60000"
blgItem.UserProperties("ClientName") = item.FullName
blgItem.UserProperties("blgDate") = Now
blgItem.Display
'... more code
End Sub
'this is the code behind the post item
Sub Item_Open()
Dim LogPage
Set LogPage = Item.GetInspector.ModifiedFormPages("Log Item")
LogPage.Controls("ResumeBtn").Visible = False
LogPage.Controls("BoxDesc").SetFocus
Item.UserProperties("blgFileName") = "C:\Temp\12345.txt"
'... more code
End Sub
Function Item_Write()
'... more code
End Function
A recent Windows update caused this. You can either uninstall it, or wait for a fix from Microsoft: https://social.technet.microsoft.com/Forums/office/en-US/e6147cb8-fe1c-4d90-a65a-33b8a7b22a6d/june-security-patch-and-issue-with-custom-forms?forum=outlook

Adding shapes/pages to visio on shape drop

Hello I am fairly new to VBA in visio, and I am trying to add functionality to a visio template so that a page will be added to the active document whenever a specific shape is dropped onto a page. I looked through MSDN and found an example using Application.ShapeAdded function but the active document I am working in doesn't seem to be responding to my modified code.
Private Sub Document_ShapeAdded(ByVal vsoShape As Visio.IVShape)
Dim vsoMaster As Visio.Master
'Get the Master property of the shape.
Set vsoMaster = vsoShape.Master
'If Visio shape added is named "SC" add a new page
If vsoMaster.Name = "SC" Then
NewPage
End If
End Sub
I drop the shape master "SC", which I confirmed is the name of the shape master, and nothing happens. The MSDN verbage describes Application.ShapeAdded as an event listener to the open application. Am I missing something or is there possibly a better way to do this I am not thinking of?
Here is the MSDN description: https://msdn.microsoft.com/en-us/library/office/ff766392.aspx
The Document_ShapeAdded event will only apply to the document in which the VBA code is located.
You'd have to declare an application object withevents and have it watch for that event.
Example (in an object or ThisDocument module):
Private WithEvents App as Visio.Application
Private Sub App_ShapeAdded(ByVal Shape As IVShape)
Call ActiveDocument.Pages.Add() ' etc..
End Sub
Alternatively, if it's something simple, you could just add a shapesheet CALLTHIS function on the master shape in question, which just fires a VBA routine to add a new page or whatever you have to do.

Context-menu and keyboard shortcut return different results on the same method

I have a vba sub ("sub") in excel 2013, which opens another workbook, reads some data out of it, return this data and close the newopened workbook. It is possible to run this sub via keyboard shortcut and a entry in the context menu.
This call (the "UTILS.sub" this is) works perfectly fine:
' Add the sub-call to a new context menu entry
Call UTILS.addContextMenuEntry("Caption", 2556, "UTILS.sub")
But this call doesn't:
' Add the sub-call to a new keyboard shortcut
App.OnKey "+^{M}", "UTILS.sub"
If i call sub with the keyboard shortcut it breaks without an error. I've managed to work out the specific code line, at which it breakes via debugging:
'[...]
Application.ScreenUpdating = False
' Open the external Workbook
Set wbHandle = Workbooks.Open("wb.xls", ReadOnly:=True)
MsgBox "Debug"
'[...]
wb.xls opens (and displays), but the MsgBox "Debug" does not. Nothing after the "Open"-line does run and no breakpoint after this line will be hit. Another strange thing: If i debug a call of sub with a breakpoint before that line, it all works perfectly.
How to get the sub to run correctly, not regarding wether it was called by a context menu entry or keyboard shortcut?
I'm not exactly sure what the cause of this behavior is, but I suspect that macros called via keyboard shortcuts or context menus are actually passed through Application.Run or something else that can reset the execution state internally.
The simple work-around seems to be to pass execution through a "wrapper" sub:
Public Sub bar()
foo
End Sub
Public Sub foo()
Dim bar As Workbook
Set bar = Workbooks.Open("C:\Book1.xls", ReadOnly:=True)
MsgBox "foo"
End Sub
Launching foo by a keyboard shortcut will not display the message box, but calling bar will.
I've found the answer to my problem by myself: stackoverflow.com/questions/17409524/
Apparently, excel can't handle the "Workbooks.Open()"-method if the sub is called through a keyboard shortcut, which includes the [SHIFT]-key. Solution: Use "Workbooks.Add()" instead.

Word VBA: Sharing variables between documents

I feel like this should be obvious, I'm just not finding the answer anywhere.
I have a Word document with several Public variables declared and defined in a variety of procedures. One procedure opens another Word document, which has a form that loads on open. For the life of me I cannot get that form in the second document to use values from the original document's variables. Am I misunderstanding the nature of Public variables? Everything I've found seems to indicate that those values should be visible to the newly opened document.
So to open the second document, I'm using the code below (some of it is declared and set elsewhere, but I think this is the relevant stuff:
Public iMarker as boolean
Sub OpenDoc()
If check_ExA.Value = True Then 'a checkbox on a userform
docName = docsPath & "/" & "seconddocumentpath.docm"
iMarker = True
formAddDocs.Hide
Set addDoc = Documents.Open(docName)
End Sub
from there, the new document has a form that shows on Open, and in the initialization, I want it to be able to see if the iMarker variable is true, among some other strings, etc.
Private Sub UserForm_Initialize()
If iMarker = True Then
'do some other stuff
End If
End Sub
I tried changing that Initialize sub to public and that did nothing. It won't see that iMarker is true when the second document opens. Any suggestions?
To make a public variable of doc01 ("source doc") available to doc02 ("target doc") document, go like follows:
open the "source doc"
open the "target doc"
click Tools-> References
from Available References listbox of the References dialog box click the "Project" of the "source doc"
You can recognize it from the path appearing near the dialog box bottom
Otherwise
close Reference dialog box
go to "source doc" and rename its project (Tools->project properties, edit "project name" textbox and click "OK") with a meaningful name (say "MainProject")
go back to "target doc" project
open References dialog box and now from Available References listbox click the "MainProject" reference
Save and close target doc

How to add handwritten signature using Excel's Ink Tools?

I want to add a handwritten digital signature to some of my company's forms.
The goal is to, select a document, add a signature (through the use of a drawing pad, which can be done with Excel's Ink Tools) and store the file in the server as PDF. This would cut out the necessity of printing and then scanning the form back in to obtain a signature.
I'm using Excel for the main interface for file manipulation and search. I've not found any references/libraries for the use of Excel - Ink Tools through VBA.
How do I start Ink Tools Objects in VBA? Would I have to use a different software to get the signature?
Update:
After #Macro Man pointed me in the right direction I found some material that helped get the eSignature up and running.
I've found some material on MSDN Digital Ink Signatures - Concepts and Technologies and InkPicture Class that talk about the Ink collection on VB.net and C# through a PictureBox/Userform , this coupled with the InkEdit Control in another Stackoverflow response in which I realised that VBAs tool box had a InkPicture Control additional control that could be utilized to collect the handwritten eSignature through User form.
Please find below step by step:
In VBAs toolbox on additional control under Tools > Additional Controls there is the InkPicture Control which allows you to create a signature Userform.
Once Added InkPicture can be used as any other control on the toolbox.
Then its a case of initialising the UserForm for the Signature request. I'm using a drawing pad, but other hardware should work as well.
And storing or utilising the resultant image at need, in my case saving a temp version in the server to then resize and add to a Word document.
Edit:
After answering a similar question in here, on how to use Userform InkPicture to input image signature into a worksheet/specific cell, I thought I'd edit this answer for those interested.
The below code will allow you to, open the userform so the user can sign the ink field, save the image temperately, add the InkPicture to your worksheet and kill the temp image.
Set up your UserForm (mine is set up like this, with a couple extra options) the UserForm is named Signature_pad, the essential option you need is Private Sub Use_Click().
This is the code inside the Userform:
Private Sub Use_Click()
'dim object type and byte array to save from binary
Dim objInk As MSINKAUTLib.InkPicture
Dim bytArr() As Byte
Dim File1 As String
'get temp file path as $user\Temp\[file name]
FilePath = Environ$("temp") & "\" & "Signature.png"
' set objInk as image/strokes of InkPicture control form object
Set objInk = Me.SignPicture
'if object is not empty
If objInk.Ink.Strokes.Count > 0 Then
'get bytes from object save
bytArr = objInk.Ink.Save(2)
'create file for output
Open FilePath For Binary As #1
'output/write bytArr into #1/created (empty)file
Put #1, , bytArr
Close #1
End If
'set public File as file path to be used later on main sub
Signature.File = FilePath
Unload Me
End Sub
Private Sub Cancel_Click()
End
End Sub
Private Sub ClearPad_Click()
'delete strokes/lines of signature
Me.SignPicture.Ink.DeleteStrokes
'refresh form
Me.Repaint
End Sub
Below is the Main sub (Module called Signature) to call the userform and handle the signature, you can call this Sub with a button or form another Sub.
'public temp file path
Public File
Sub collect_signature()
'Dim and call userform
Dim myUserForm As Signature_pad
Set myUserForm = New Signature_pad
myUserForm.Show
Set myUserForm = Nothing
'insert image/signature from temp file into application active sheet
Set SignatureImage = Application.ActiveSheet.Shapes.AddPicture(File, False, True, 1, 1, 1, 1)
'scale image/signature
SignatureImage.ScaleHeight 1, True
SignatureImage.ScaleWidth 1, True
'image/signature position
SignatureImage.Top = Range("A1").Top
SignatureImage.Left = Range("A1").Left
'delete temp file
Kill File
End Sub
Be sure to rename either the Userform Name and Buttons Name Or the code to match the names of you buttons.
Is it the InkEdit Control you're after?
This is one of the standard libraries that you can find in Tools->References