I need to make an application that opens a template made by customer, with special names/titles/tags, whatever we will agree upon, and then fill it from the database based on the customer's search.
However, if the customer made a template like this one
Now we have two ContentControls (wdContentControlRichText & wdContentControlPicture)
Questions are:
1- How to make multiple pages in the same document from the same chosen template.
2- (Most Important) How to set the PictureContentControl Image from vb code.
Notes:
I tried my best to search and look for similar questions, yet no one seems to solve my problem. What I have reached is that I can loop through the content controls, but I can't cast the PictureContentControl from Microsoft.Office.Interop.Word Object to Microsoft.Office.Tools Object.
Also all solutions I found on the net, includes "Globals.Factory" which doesn't seem to ever be valid for my code, as my Globals doesn't contain the Factory Object.
I'm using the references:
Microsoft.Office.Core
Microsoft.Office.Interop.Word
Microsoft.Office.Tools
Microsoft.Office.Common
Microsoft.Office.Common.v4.0.Utilities
Microsoft.Office.Tools.Word
Microsoft.Office.Tools.Word.v4.0.Utilities
Microsoft.VisualStudio.Tools.Applications.Runtime
Related
I'm new to .NET from an extensive VBA background. I'm building an Excel add-in and have been struggling to find any guidance on line about control of code structure and layout in visual studio.
Comparing to the VBA environment, what I want to do is have different modules for the different components (e.g. one module with all the calculation subs, one module with all the formatting subs, one module with all the custom charting subs, etc.) but cannot find any guidance on how to set this up.
I've put the skeleton of the ribbon tab in, with some icons etc. and VS has automatically created tabs as follows:
Ribbon1.Designer.vb, which appears to house setup code - adding groups and buttons etc.
Ribbon1.vb, which now contains a few subs I've written in 'Public Class Ribbon 1'. This is the bit I want to "modularise".
I have tried creating another public class which didn't work, and a few other things. I also saw mention of "sub classes" though could not find any instructions/examples and couldn't get this going myself (or if I need to specify inheritance from one to another?).
From a user friendliness perspective for me, one tab in VS per category of subs would be the ideal but I'm amateur so definitely open to learning how to structure it all properly. Yes, I wish I had software engineering training!
Screenshot
A Microsoft Word 2013 document at work has the Document Information Panel (DIP) displayed by default, with what is listed as "Document Properties - Server".
I'm trying to make a VB Macro that will involve editing these custom properties. However they don't seem to exist in ActiveDocument.CustomDocumentProperties, or ActiveDocument.BuiltInDocumentProperties. I know this because I ran through the list, displaying them one by one, as well as searching them by name.
The first property on the DIP called 'Title' showed up (in the latter list), but none of the other properties. It's worth noting that some are dropdowns, and one is a date with a calendar feature. I should also mention that I get a Run-time error near the end of the list of BuiltInDocumentProperties.
Is there another list where I can access these server properties, or some other issue that I'm overlooking? Any help would be appreciated.
I was able to find them. They are listed in ActiveDocument.ContentTypeProperties
I have a Normal.dotm file that contains an AutoNew macro.
This macro is automatically executed each time a new document is created using any other template.
Is there any way I can prevent this automatic behavior for a specific template?
I have a Word VSTO add-in running, so I can hook into Word's events, but so far I havn't found a way to prevent this.
I do know that I can prevent macro execution when using templates programmatically, for example like this:
' Disable auto-macros before opening document
wordApplication.WordBasic.DisableAutoMacros(1)
' Open document
newWordDocument = wordApplication.Documents.Open(template.FullName, ConfirmConversions:=False, [ReadOnly]:=True, AddToRecentFiles:=False, Revert:=True)
' Re-enable auto-macros
wordApplication.WordBasic.DisableAutoMacros(0)
But this solution doesn't work when the user uses a Word template from Windows explorer or the Open-dialog in Word, since in those cases I can't execute code before it's too late already.
Or can I?
I hope someone has a trick for me :-)
-
Edit: While trying different solutions, I discovered something that might help others in similar situations, though unfortunately it doesn't help me.
It seems that if a template contains a module containing an AutoNew (or AutoOpen for that matter), that local macro is executed instead of the one in Normal.dotm.
Example:
Normal.dotm contains the following macro:
Sub AutoNew()
MsgBox "Normal.dotm"
End Sub
Test.dotm contains the following macro:
Sub AutoNew()
MsgBox "Test.dotm"
End Sub
When executing Test.dotm the message "Test.dotm" is displayed, while the message "Normal.dotm" is not displayed.
If the AutoNew macro is removed from the Test.dotm template, the message "Normal.dotm" is indeed displayed.
So it is possible to easily override the auto-macros.
The local versions of AutoNew and AutoOpen can even be empty subs that do nothing. It still works.
This is not possible in my case though, since the template I use is generated by code, and cannot contain macros (because adding macros to templates programmatically requires the user to manually activate the option "Trust access to the VBA project object model", and that's something I cannot ask my customers to do for all users. It's also a security risk.)
Based on the workaround described in the "Edit" part of the question - providing a template with "empty" Auto-macros - it's possible to use the Open XML SDK to create a template and add the VBA project to it in order to provide this functionality. This approach avoids the user needing to allow access to the VBA project on his installation. The only "macro security" that could be triggered is that for not allowing macros to run. But since the client uses macros, anyway, this should not be a major obstacle.
The simplest method is to create as much of the basic template as possible in the Word UI and use this as a starting point.
Since you're unfamiliar with the Open XML SDK, the next step would be to create one (or more) templates in the Word UI using the basic template as the starting point, saving under a different file name.
You can then use Open XML SDK Productivity Tool to see the code required to generate any one of these files, as well as, using the Compare tool, the code for converting the basic template to the derived version. This should give you a decent start with the SDK and it's object model. Once you get a feel for how the Open XML SDK works, if you're familiar with Word's object model, using that provided by the SDK is relatively straight-forward as an effort was made to make it correspond as closely as possible to the "COM" object model.
The VBA project can be added later, but you can also include it in the basic template. That would be the simplest approach.
Include this "starting point" basic template as part of your solution, installing it as part of the solution.
Within the AutoNew macro you can check the AttachedTemplate property. Only if it is a template where you want to apply the cleaning you can execute the respective macros.
Sub AutoNew()
If ActiveDocument.AttachedTemplate <> "Normal.dotm" Then
Exit Sub
End If
' rest of the macro
End Sub
If you don't control the Normal.dotm you can put an empty AutoNew macro in your own templates. As Word only executes the auto macro in the closest context, the macro in the Normal.dotm file would not be executed.
If you don't control the other templates either, you can tell your users to hold down the SHIFT key while creating a document. This prevents the execution of the auto macro.
Probably it is best, however, if you ask the owner of the other system to find another solution that does not rely on polluting the Normal.dotm file.
I'm new to VBA. Some tutorials tell me to use enumeration constants such as wdOrientLandscape and wdRowHeightExactly (to change page orientation and make row height 'exact' respectively). However, when debugging, I can see that the value of these constants is Empty and they don't 'work' as expected.
Do I need to do something special to access these constants e.g. add a reference or something?
I'm creating a Word document from an Excel macro.
Thanks in advance
Within Excel (or any automation client) the enumerations belonging to the Word object model are not exposed if you use Late Binding (CreateObject("Word.Application")).
If you early bind by adding a reference they become visible.
If you add Option Explicit to the top of you code modules (or select Require Variable Declarations from the VBA editor options) you will receive a compile time warning if you attempt to use something that's not declared/unavailable
In your particular case, you would want to add the Microsoft Word Object Library to your references. If you choose to early bind. This can be done by going to Tools>>References and checking the appropriate box.
I have some code that is auto-filling a PDF form based on some properties. Initially, the errors I get when running the code pertain to the fields not being found on the mapping object, but once I change them to the correct property names, the errors all show up the same, as if the fields had all been renamed to 'topmostSubform':
An error has occured when filling the PDF Form [14. New OLTL Employer CLE Address-Phone
Change Form_v_1.1]. DataBinding: 'PPLPortalCommon.Consumer' does not contain a property with
the name 'topmostSubform'.
I made the edits using Adobe Livecycle Designer, so it seems something in there corrupted the field names. Has anyone come across this issue? Seems like a pretty simple task to change the field names.
Thanks
The forms appears to have a binding issue. I believe the answer to your questions requires more questions.
Are you using an XSD for the data-binding ?
Do you have a subform named "topmostSubform" in your form template or the XSD ?
A reference is being made in the field ( either by the form template, the schema or the data-binding reference if you are not using a schema) and needs to be resolved in the template.
Unfortunately since there is no template attached to this question, I wont be able to provide any further assistance with the knowledge in hand.
Thanks,
Armaghan.