Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

run-time error 424 Object required

Status
Not open for further replies.

Tiburon

IS-IT--Management
Mar 6, 2015
11
US
Hi folks...pulling my hair out for hours on this seemingly simple task... trying to save a template as a docx file to a specific location and file name based on some text fields in the document.

In a MS Word template file, I have a text box control labeled LName. There's also a button named SaveTo with a Click script. Every time I try to get the text value from Lname using Lname.text I get:

"run-time error 424 Object required."

Here is my code: (under Template Project - Microsoft Word Object - ThisDocument)

Private Sub SaveTo_Click()

ActiveDocument.SaveAs FileName:="c:\scripts\invoice\file created" & " " & Format(Date, "mm-dd-yy")
' use msgbox to debug this thing
MsgBox (Lname.Text)

End Sub
 
WHat happens if you do:

Code:
MsgBox (Lname)[green]
'or[/green]
MsgBox (Lname.Value)




Have fun.

---- Andy

A bus station is where a bus stops. A train station is where a train stops. On my desk, I have a work station.
 
@Andrzejek
The first gives a blank msgbox.
The second gives the same runtime error.
 
You will need something along the lines of:

ActiveDocument.Fields("Lname").Text

That is almost certainly the incorrect syntax, but should serve as a push in the right direction.
 
@mintjulep, With your line I get "Method or Data member not found."
.Text is not valid
ALmost any valid one I select gives a type mismatch error.

...more hair lost.
 
... also the Watch window in VBA, when I specify to watch LName it says <Expression not defined in context>
It's on the document, but apparently that isn't "defined" ?
 
When you type your code and have:
[tt]ActiveDocument.[/tt]
do you get the 'intelisense' with some options/parameters/properties to choose from, and is one of them: [tt]Fields[/tt]?

Have fun.

---- Andy

A bus station is where a bus stops. A train station is where a train stops. On my desk, I have a work station.
 
Yes.
activedocument.fields. gives options of methods
activedocument.fields( gives options of Index (long)

Msgbox(activedocument.fields.count) says just 1 (one) which the command button not the 3 "fields" text boxes I places on the document.

Msgbox(activedocument.fields(1)) gives CONTROL Forms.CommandButton.1

MsgBox (ActiveDocument.ContentControls.Count) give 3 which is the number of items on the doc (two text boxes, one date control).


 
[highlight #EF2929]That is almost certainly the incorrect syntax, but should serve as a push in the right direction.
[/highlight]

Or maybe not.

You'll need to better define what you have. "some text fields" "text box control labeled LName"

If you can't tell us what it is, tell us how you inserted it.

 
Ah, ok. Content controls.

Getting the text out of them is somewhat obtuse.

Code:
Public Function GetContent(DocObject As Document, ContentControlTitle As String) As String
On Error Resume Next
Dim ContentObject As ContentControl
Set ContentObject = DocObject.SelectContentControlsByTitle(ContentControlTitle).Item(1)
GetContent = DocObject.ContentControls(ContentObject.ID).Range.Text
End Function
 
I inserted 2 Plain text content conrols and one Date control from the Developer - Controls menu bar.

Then I added a Command button from the Controls - ActiveX controls menu

 
Thanks, obtuse is a nice word for it!
With this code I get a blank MsgBox.. am I passing args ok?

Private Sub SaveTo_Click()

'ActiveDocument.SaveAs FileName:="c:\scripts\invoice\filex" & " " & Format(Date, "mm-dd-yy")
'MsgBox (ActiveDocument.ContentControls.Count)
'MsgBox (ActiveDocument.Fields.Count)
MsgBox (GetContent(ThisDocument, "Lname"))
End Sub

Public Function GetContent(DocObject As Document, ContentControlTitle As String) As String
On Error Resume Next
Dim ContentObject As ContentControl

Set ContentObject = DocObject.SelectContentControlsByTitle(ContentControlTitle).Item(1)
GetContent = DocObject.ContentControls(ContentObject.ID).Range.Text
End Function
 
Maybe I should also ask... is there a better, less obtuse way to do this?

I want the users to fill several fields on a form (template) and click a button to saveas a DOCX to a specific location with a file name based on values in some of the fields.
 
You could get away with:

Code:
ActiveDocument.SaveAs FileName:="c:\scripts\invoice\filex" & " " & Format(Date, "mm-dd-yy")
'MsgBox (ActiveDocument.ContentControls.Count)
'MsgBox (ActiveDocument.Fields.Count)
MsgBox (GetContent(ActiveDocument, "Lname"))
End Sub

A bit better would be:

Code:
Dim MyDoc as Document
Set MyDoc = ActiveDocument.SaveAs FileName:="c:\scripts\invoice\filex" & " " & Format(Date, "mm-dd-yy")
'MsgBox (ActiveDocument.ContentControls.Count)
'MsgBox (ActiveDocument.Fields.Count)
MsgBox (GetContent(MyDoc, "Lname"))
End Sub
 
From what I read you are just using text content controls as text input fields and want to get the value(s) from them.

If your content control is 'labeled' - in other words your text "Lname" appears above it beside the three dots - then "Lname" is its Title (by default the Tag may be the same but let's ignore that for the moment).

In theory, and likely in some circumstances where you may be using xml mappings, there could be several content controls with the same title, so VBA will return a collection rather than a single element. Presuming you only have one content control with the title,you can access it as the first member of the collection ...

Code:
[blue]Dim MyCC as Word.ContentControl
Set MyCC = ActiveDocument.SelectContentControlsByTitle("Lname")(1)[/blue]
[green]' Do note that "Lname" is case-sensitive[/green]

When you have the content control, you want the text from its [tt][blue]Range[/blue][/tt] ...

Code:
[blue]Dim LName as String
LName = MyCC.Range.Text[/blue]

You now have a VBA variable containing the text from the content control and can do as you want with it.


Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
@TonyJollans
Thanks! That helped me get beyond the Content Control issue. The MyCC.Range.Text even worked for a Date control.

The SaveAs doc seems to remain open after this, so how to close it? ActiveDocument.close closes the template that has this code in it.

Private Sub SaveTo_Click()

Dim MyCC As Word.ContentControl
Dim docFname, docLname, docSaveAs As String
Dim docDate As Date

Set MyCC = ActiveDocument.SelectContentControlsByTitle("FName")(1)
docFname = MyCC.Range.Text

Set MyCC = ActiveDocument.SelectContentControlsByTitle("LName")(1)
docLname = MyCC.Range.Text

Set MyCC = ActiveDocument.SelectContentControlsByTitle("Date")(1)
docDate = MyCC.Range.Text

docSaveAs = "c:\testdocs\" & docLname & "," & docFname & " " & Format(docDate, "yy-mm-dd")
ActiveDocument.SaveAs FileName:=docSaveAs

' the SaveAs doc seems to remain open after this how to close it?

End Sub
 
What happens with VBA code is the same as what happens when you do things manually through the UI - that is, Save As (or Save) saves the current document and leaves it open. Also, closing a document closes the template it is based on (unless you also have other documents based on the same template open). In other words that behaviour is expected.

Once the document is closed there will be nothing visible to the user, and nothing left for the user to interact with, so why is it a problem? By the time you want to close the document, you should be all done. Do whatever else it is you need to do first, and close the document as the final act - from the user's perspective, it's all over and the sequence of automated actions behind the scenes is of no consequence.



Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
You make a logical point. I was hoping the user could "camp" in the document template and keep saving new ones after they change the names and date on the form but it's not a requirement.

I am going to use a docm file instead of dotm to start with and just protect the docm file to make it a fillable form.
But in the line,

ActiveDocument.SaveAs FileName:=docSaveAs

How do I specify that I want to save it as a docx file so that the saveto button is not functional in the saved docx file??

They syntax editor has some ActiveDocument.SaveAs2([FileName],[FileFormat]...) function but it doesn't work.
 
Word just isn't designed to work that way, and doesn't have an equivalent of the Excel [tt][blue]SaveCopyAs[/blue][/tt]. You'll end up in a mess if you go down that route!

I would suggest adding another button (or perhaps a checkbox or other way for the user to make a choice) to your template so you can have something like "Save and Quit" and "Save and New Form" or something along those lines. For "Save and New", create a new document (based on your template) before closing the old one - that way the template and the new document will stay open after you close the old one - and all the user should experience is being presented with a blank form, having saved the current one.

Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
Well here's what I ended up doing and it seems to work fine...
The SaveTo_Click is the code on the button. It calls SpecialClose to delete the button from the saved-as document.
Not pretty but it works. All the tektips are greatly appreciated folks!!

Code:
Private Sub SaveTo_Click()
Dim docFname, docLname, docDateofvisit, docSaveAs As String

'get form fields and build the file name
docFname = ActiveDocument.FormFields("clientfname").Result
docLname = ActiveDocument.FormFields("clientlname").Result
docDateofvisit = ActiveDocument.FormFields("dateofvisit").Result
docSaveAs = "S:\MedicalDirectors\H-P\_test_" & docLname & "," & docFname & " " & docDateofvisit

'notify and save the document
MsgBox ("The document will be saved to: " & docSaveAs)
Call SpecialClose(docSaveAs)


End Sub

'-----

Private Sub SpecialClose(docSaveAs As String)
Dim shape As InlineShape

'save the document in docx format
'Note: it becomes the ActiveDocument!
ActiveDocument.SaveAs FileName:=docSaveAs, FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False

'unprotect it and remove the command button shape
ActiveDocument.Unprotect

For Each shape In ActiveDocument.InlineShapes
    If shape.OLEFormat.Object.Name = "SaveTo" Then
        'MsgBox ("shape will be deleted")
        shape.Delete
        Exit For
    End If
Next

're-protect, save and close
ActiveDocument.Protect (wdAllowOnlyReading)
ActiveDocument.Save
ActiveDocument.Close

End Sub
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top