Change "Total Editing Time" in microsoft word using VBA - vba

complete novice here.
I have tried a few different ways to change a ms word document property but I can't seem to get it to work. I'm trying to re-make one of my documents that I was working on but it became corrupt - manually adding back all the different properties etc.
I tried this among some others I already forgot.
Sub test_getProperties()
updateThisDocument.BuiltInDocumentProperties "Total Editing Time", "34500", msoPropertyTypeNumber
End Sub
and
Sub setproperties()
BuiltInDocumentProperties("Total Editing Time").Value = 34500
End Sub
and
Sub WriteDocumentProperties()
Dim objBuiltDocProp As Object
Set objBuiltDocProp = ThisWorkbook.BuiltInDocumentProperties
objBuiltDocProp("Total Editing Time") = 35000
End Sub
Which just keep giving me '424' - being a novice I don't know how to fix it, help pls

Simple rule of thumb: if a property can't be edited in the UI, it can't be edited in VBA either.
However, you can directly edit the xml. If you have 7-Zip installed you can use it to open the document archive. The file you need is app.xml which is in the docProps folder. You'll find a property called TotalTime the value for which is in minutes.

Related

Variables in VBA for Word 2010

I have this code in VBA for Word 2010:
Public LastBodyPage
Sub tryit()
Selection.GoTo What:=wdGoToBookmark, Name:="AppendixStart"
LastBodyPage = Selection.Information(wdActiveEndPageNumber)
End Sub
Sub vardel()
MsgBox Variables.item("LastBodyPage").Value
MsgBox LastBodyPage
End Sub
When the vardel procedure is run, the first message box displays "53" and the second time it displays "50".
Why am I getting different values??
You're looking at two different things:
The first message box displays something called Variables.item (your code does not compile, what is Variables.item?).
Anyway, the second message box displays something completely different, it displays LastBodyPage which you presumably set using tryit.
It looks like Variables.Items is part of the document variables that you can set up and assign values to.
LastBodyPage in your tryit procedure looks at the bookmark AppendixStart which I assume you also set up.
So...
AppendixStart is bookmarked on page 50
The code ThisDocument.Variables.Add ("LastBodyPage"), 53 is used to add the document variable somewhere in your code. This persists between opening & closing the document - so may have been added ages ago.
Your code uses ThisDocument.Variables.... rather than just Variables....
With those condition I got the same result as you.

VB.Net equivalent for (CustomizationContext) in VBA

I'm busy with some word automation and have run into an issue whereby a context menu within a document has items in, that I wish to remove.
Once the document is open, through vba I can remove these items by running the following code;
[VBA]
Dim oContextMenu As CommandBar
Dim oContextMenuItem As CommandBarControl
'Make changes to the ActiceDocument only (this is needed to make any changes to this document).
CustomizationContext = ActiveDocument
For Each oContextMenu In ActiveDocument.CommandBars
If oContextMenu.Type = MsoBarType.msoBarTypePopup Then 'Loop through all the context menus of type (msoBarTypePopup)
For Each oContextMenuItem In oContextMenu.Controls
If (InStr(oContextMenuItem.Caption, "Smokeball")) Then
oContextMenuItem.Delete
End If
Next
End If
Next
If I execute this code and check the document, all contextMenu sub items that contain the text "smokeball" are removed.
When I try move this code to my VB.NET solution (I have no choice of language, so VB it is), I get errors on the CustomizationContext = ActiveDocument line (this line has to be there for it to affect the current document).
The error I get is CustomizationContext' is not a by reference property.
Does anyone know how to get just that ONE line equivalent for vb.net?
Thanks in advance.
EDIT: In case you need to see the vb.net sub:
Private Sub RemoveUnwantedContextMenuItems()
Dim oContextMenu As CommandBar
Dim oContextMenuItem As CommandBarControl
'Make changes to the ActiceDocument only (this is needed to make any changes to this document).
WordApplication.CustomizationContext = WordApplication.ActiveDocument 'This is the error.
For Each oContextMenu In WordApplication.CommandBars
If oContextMenu.Type = MsoBarType.msoBarTypePopup Then 'Loop through all the context menus of type (msoBarTypePopup)
For Each oContextMenuItem In oContextMenu.Controls
If (InStr(oContextMenuItem.Caption, "Smokeball")) Then
oContextMenuItem.Delete()
End If
Next
End If
Next
End Sub
PS - I have also already tried using the .AttachedTemplate as well as .Normal / .NormalTemplate
Jules pointed me in the right direction with his sample code.
After lots of playing around I noticed that somewhere in the solution, the [TYPE] of WordApplication was getting changed to a dynamic type of sorts, hence, it couldn't use CustomizationContext.
My solution was this:
I changed this line;
WordApplication.CustomizationContext = WordApplication.ActiveDocument
To this:
CType(WordApplication, Microsoft.Office.Interop.Word.Application).CustomizationContext = WordApplication.ActiveDocument
Forcing the types to be correct.
Simple solution but took some time.
Thanks to Jules for pointing me in the right direction.
(Points should go to you).

Programming VBA in an Outlook form

I created my own Outlook form to use it as standard surface to enter certain orders instead of the normal message form. The creation, editing and sending works perfectly fine and in the next step I want to insert some code via VBA.
My problem is that I can´t access the objects of my form in the VBA editor. E.g. I want to show a message box when a certain checkbox is checked. According code would be:
Sub example()
If CheckBox1.Value = True Then
MsgBox("Checkbox 1 is checked.")
End If
End Sub
When I run the code I get the error that the object could not be found. The same goes for every other object, like textboxes or labels etc.
I guess the solution is pretty simple, like putting Item. or sth. like that in front of each object. But so far I wasn't able to find the solution.
I´m using Outlook 2010.
I know this is a year too late but you'll want to do something like this example below. It's kinda a work around but you can get whatever value was selected.
Sub ComboBox1_Click()
Set objPage = Item.GetInspector.ModifiedFormPages("Message")
Set Control = objPage.Controls("ComboBox1")
MsgBox "The value in the " & Control.Name & _
"control has changed to " & Control.Value & "."
End Sub
You should be able to get the value, just get a handle on the object you want using the Inspector
The following is an excerpt from here
When you use a custom form, Outlook only supports the Click event for
controls. This is a natural choice for buttons but not optimal for
controls like the combo box. You write the code by inserting it into a
form’s VBScript editor. You need to have the Outlook form open in the
Form Designer and click the View Code button found in the Form group
of the Developer tab.
Sub CheckBox1_Click()
msgbox "Hello World"
End Sub
The code page is fairly minimal with no syntax highlighting. I just tried this now and it does work. Dont forget to Publish your form to pick up the new changes.
I know this is almost 6 years late but, in VB and VBA, simply start with the form name. (And if that doesn't work, just keep going up a parent object and you'll get there.) So, your code becomes:
Sub example()
If MYFORMNAME.CheckBox1.Value = True Then
MsgBox("Checkbox 1 is checked.")
End If
End Sub
Of course, after typing "MYFORMNAME." you'll know if it will work because typomatic will kick in when the system recognizes "MYFORMNAME" after you hit the period.

"Sub or Function not defined" when trying to run a VBA script in Outlook

As a first step in creating a VBA script to resize a currently selected image to 100% x 100%, I'm trying to reproduce the example in http://msdn.microsoft.com/en-us/library/ee814736(v=office.14).aspx. The macro is very simple:
Sub Test()
MsgBox ("Hello world")
End Sub
The VBA script was simply created in "Project1" which opens by default when one presses Alt+F11. However, I keep getting the error "Sub or Function not defined" when trying to run the VBA script (Figures 1 and 2).
How can I make the VBA script 'accessible' to Outlook?
Figure 1 Running the "Test" macro in Microsoft Outlook
Figure 2 "Sub or Function not defined" error, with module tree in the background
I solved the problem by following the instructions on msdn.microsoft.com more closely. There, it is stated that one must create the new macro by selecting Developer -> Macros, typing a new macro name, and clicking "Create". Creating the macro in this way, I was able to run it (see message box below).
I had a similar situation with this issue. In this case it would have looked like this
Sub Test()
MsqBox ("Hello world")
End Sub
The problem was, that I had a lot more code there and couldn't recognize, that there was a misspelling in "MsqBox" (q instead of g) and therefore I had an error, it was really misleading, but since you can get on this error like that, maybe someone else will notice that it was cause by a misspelling like this...
This error “Sub or Function not defined”, will come every time when there is some compile error in script, so please check syntax again of your script.
I guess that is why when you used msqbox instead of msgbox it throws the error.
This probably does not answer your question, but I had the same question and it answered mine.
I changed Private Function to Public Function and it worked.
I need to add that, if the Module name and the sub name is the same you have such issue.
Consider change the Module name to mod_Test instead of "Test" which is the same as the sub.
I think you need to update your libraries so that your VBA code works, your using ms outlook

Profiling VBA code for microsoft word

I have some legacy code that uses VBA to parse a word document and build some XML output;
Needless to say it runs like a dog but I was interested in profiling it to see where it's breaking down and maybe if there are some options to make it faster.
I don't want to try anything until I can start measuring my results so profiling is a must - I've done a little searching around but can't find anything that would do this job easily. There was one tool by brentwood? that requires modifying your code but it didn't work and I ran outa time.
Anyone know anything simple that works?
Update: The code base is about 20 or so files, each with at least 100 methods - manually adding in start/end calls for each method just isn't appropriate - especially removing them all afterwards - I was actually thinking about doing some form of REGEX to solve this issue and another to remove them all after but its just a little too intrusive but may be the only solution. I've found some nice timing code on here earlier so the timing part of it isn't an issue.
Using a class and #if would make that "adding code to each method" a little easier...
Profiler Class Module::
#If PROFILE = 1 Then
Private m_locationName As String
Private Sub Class_Initialize()
m_locationName = "unknown"
End Sub
Public Sub Start(locationName As String)
m_locationName = locationName
MsgBox m_locationName
End Sub
Private Sub Class_Terminate()
MsgBox m_locationName & " end"
End Sub
#Else
Public Sub Start(locationName As String)
'no op
End Sub
#End If
some other code module:
' helper "factory" since VBA classes don't have ctor params (or do they?)
Private Function start_profile(location As String) As Profiler
Set start_profile = New Profiler
start_profile.Start location
End Function
Private Sub test()
Set p = start_profile("test")
MsgBox "do work"
subroutine
End Sub
Private Sub subroutine()
Set p = start_profile("subroutine")
End Sub
In Project Properties set Conditional Compilation Arguments to:
PROFILE = 1
Remove the line for normal, non-profiled versions.
Adding the lines is a pain, I don't know of any way to automatically get the current method name which would make adding the profiling line to each function easy. You could use the VBE object model to inject the code for you - but I wonder is doing this manually would be ultimately faster.
It may be possible to use a template to add a line to each procedure:
http://msdn.microsoft.com/en-us/library/aa191135(office.10).aspx
Error handler templates usually include an ExitHere label of some description.. The first line after the label could be the timer print.
It is also possible to modify code through code: "Example: Add some lines required for DAO" is an Access example, but something similar could be done with Word.
This would, hopefully, narrow down the area to search for problems. The line could then be commented out, or you could revert to back-ups.
Insert a bunch of
Debug.Print "before/after foo", Now
before and after snippets that you think might run for long terms, then just compare them and voila there you are.
My suggestion would be to divide and conquer, by inserting some timing lines in a few key places to try to isolate the problem, and then drill down on that area.
If the problem is more diffused and not obvious, I'd suggest simplifying by progressively disabling whole chunks of code one at a time, as far as is possible without breaking the process. This is the analogy of finding speed bumps in an Excel workbook by progressively hard coding sheets or parts of sheets until the speed problem disappears.
About that "Now" function (above, svinto) ...
I've used the "Timer" function (in Excel VBA), which returns a Single.
It seems to work just fine. Larry