runtime error 4159 - file not found

I am using the code:
   
Sub CopyStyles()
   
        Dim oStyle As Word.Style
        Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)
     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
        Next oStyle
   
        For nLoop = 0 To UBound(a_szStyleNames()) - 1
            Application.OrganizerCopy oSourceDoc.Path, oTargetDoc, _
                                                    strStyleNames(nLoop), wdOrganizerObjectStyles
        Next nLoop
   
    End Sub

The template now opens and stays open though along with the active document  but i get runtime error 4149 File not found
and it stops on this line :

Application.OrganizerCopy oSourceDoc.Path, oTargetDoc, _
                                                    a_szStyleNames(nLoop), wdOrganizerObjectStyles

matt_swinburneAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Guy Hengel [angelIII / a3]Billing EngineerCommented:
Destination parameter needs to be the full path also, thus:

Application.OrganizerCopy oSourceDoc.Path, oTargetDoc.Path, _
                                                    strStyleNames(nLoop), wdOrganizerObjectStyles

matt_swinburneAuthor Commented:
I had that problem before and get the error sub or function not defined with that coding.

Any more ideas because im gettin pressure from my boss
Guy Hengel [angelIII / a3]Billing EngineerCommented:
The Target Document (ActiveDocument) needs to be saved at least once before the Path property evaluates to a good value...
Your Guide to Achieving IT Business Success

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

matt_swinburneAuthor Commented:
Sorry my knowledge on the subject is VERY basic! :-)

what does that mean?

Thanks for the quick reply
Guy Hengel [angelIII / a3]Billing EngineerCommented:
If you create a new word document without saving it, the Word.Document object's PATH property returns nothing, as the document is not yet saved, so no filename and foldername information are defined...
which would makes the function OrganizerCopy fail ...
matt_swinburneAuthor Commented:
So the document that the module is inserted into needs to be saved?  I have inserted the module into a document called CopyStyles 1st attempt and is saved to my HD.  Am I understanding correctly?
matt_swinburneAuthor Commented:
No more ideas?/
PSSUserCommented:
Try putting a watch on ActiveDocument.
You do this by selecting the word while stepping through the code. Then right-click it and choose Add Watch. You will only need to watch the value (you don't need to stop on change or anything).

View the watch window and expand the information for the ActiveDocument object. Take a look at the value of it's path property and check to see if any of the other values look strange.
RonaldBiemansCommented:
Ok I've worked out this, If tested it and it seems to work

Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open("c:\test2.doc")

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close
       
     
       For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        "c:\test2.doc" _
        , Destination:=oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub


you have to explicitly set the name of the source, using oSourceDoc or oSourceDoc.path doesn't seem to work
matt_swinburneAuthor Commented:
Hi Ronald - Sorry I was on lunch

So what is it that I have to specify?

 Set oSourceDoc = Documents.Open("c:\test2.doc")

Apoligies if I am being dim!
RonaldBiemansCommented:
no you can just do what you did

Set oSourceDoc = Documents.Open(c_szTemplateFile)

mine was just my test document I used

so probably also

For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop

if indeed c_szTemplateFile actually holds the complete path to the template file

matt_swinburneAuthor Commented:
So i dont need this bottom loop at all?

   For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        "c:\test2.doc" _
        , Destination:=oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
RonaldBiemansCommented:
Yes of course you do, that actually copies it,

just use this complete  sub

Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close
       
     
      For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub
matt_swinburneAuthor Commented:
lol  Thank you.  I have run the macro and no errors!  But what styles is this changing because mine all appear to stay the same (font size etc.)
RonaldBiemansCommented:
It copies the styles that where in use in the .dot to your destination file. It works here perfectly.
matt_swinburneAuthor Commented:
really? including font and font size?
RonaldBiemansCommented:
Yep, it alter everything automatically, I assume it doesn't were you are ?

I don't use 2003 but 2000 but that shouldn't make a difference, Could you send me your template in 2000 fileformat, so I can test it with that :-), I'm at a client right now (ronald at strategus dot be)
matt_swinburneAuthor Commented:
cant thank you enough Ronald :-)  

Unfortunatley I cant see why?  because all I did was change the file it was pointing to to a doc (because that was the only difference in code i could see I am back to the same error!

Using this code now;

Private Const c_szTemplateFile As String = "C:\commercial.dot"
Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close
       
     
      For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub


Not sure if this is the exact formating they need but it will be near enough and if i can get the font size and style to change it will be enough.  I am sending the file to you now.
matt_swinburneAuthor Commented:
Unfortunatley I cant see why? (i have this error again)
RonaldBiemansCommented:
But I can :-), the problem is the oTargetDoc, this doesn't specify the complete path

try this

For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetdoc.path & "\" & oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop

RonaldBiemansCommented:
and did it work ?,  it did here :-)
matt_swinburneAuthor Commented:
sorry I have to sort something for  a user :-(  I will try in about 5 - 10 :-)
matt_swinburneAuthor Commented:
awwww the font and font size STIILLLL stay the same :-(

How come it works from your end?!  I cant see that the version makes a difference...
RonaldBiemansCommented:
Very strange, I'm going home now but I will try it there with the file you send me.

We'll get it working :-)
matt_swinburneAuthor Commented:
Thanks!  Enjoy your night, speak to you tommorow :-)
RonaldBiemansCommented:
Hi matt, I'm home now and I tested it with your file and it works.

Could you explain what you expect it to do, that it doesn't ?
matt_swinburneAuthor Commented:
I would just like it to change the font size and the actual font to match the template
matt_swinburneAuthor Commented:
also the style format but i will have to double-check tommorow exactly what my boss wants because I was asked to have a go about a month ago and I cant really remember...
RonaldBiemansCommented:
That does not happen unless your document uses styles in one of the formats you defined in the template,
I'll try to explain in my bad English :-),

if you have set the default style "Header 1" with font "Arial" size 20 in your template,
and you have used the style "Header 1" in your document with "Garamond" size 10

if you now run your program, the document will have replaced the Header 1 style of the document with the one in the template
and all sentences in your document where you have used this style will have changed font and size, That is what it does the default font and size is NOT a style
matt_swinburneAuthor Commented:
No I think you did a good job explaining.....
So for example if the template has Style; Coversheet Title in with the font size as 10 and Ariel,  And i run my macro on an active document also with the stytle Coversheet title but the font size 20 and Times New Roman and I run the macro the font and size will change then.
RonaldBiemansCommented:
Yes,  I tested that and that works perfectly
RonaldBiemansCommented:
Try it and you will see :-)
matt_swinburneAuthor Commented:
:-(    emmm i tried.....  and it doesnt happen for me.  I will try with a document as the template as oppose to an actual template
RonaldBiemansCommented:
this is what I used (your file, your template)

Private Const c_szTemplateFile As String = "C:\commercial.dot"
Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close
       
     
      For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc.Path & "\" & oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RonaldBiemansCommented:
I'll send you both the files I used so you can try it :-)
matt_swinburneAuthor Commented:
Think I got it to work copy styles from a doc rather than a template!

One thing though is that they want rather more than just the font size changing.. Not sure how much you will be able to help or if it is even possible...  He is in meeting at the moment but I will find out as soon as possible and maybe you can tell me if it is possible :-)
RonaldBiemansCommented:
And did it work ?
RonaldBiemansCommented:
you can change the default style aswell, meaning if you just use that style everthing should change that didn'tt have a specific style attached :-)
matt_swinburneAuthor Commented:
Yeah it worked.  Basically I am not sure how to use the styles on this new verison of word.  If you went Format>>Styles>>Organiser>>and then imported styles from the template there is loads (i cant speak to the guy to see what he wants till this afternoon , but i spoke with his secetary and she gave me an idea).  They open this document that they download regulaly and they need the button to format that to Ariel, the font size (we got that :-)) and things like indentations.  

Hopefully you will be able to help with that or maybe it already works but until I speak to the guy to find the document I will have trouble.  I might go speak with secetary again and see if she knows the document and what changes need applying)

Thanks for your patience

Matt
RonaldBiemansCommented:
Ok, I'll be hearing from you then :-)
matt_swinburneAuthor Commented:
Hi Ronald!  OK the macro currently does most of the changes - double line spacing etc.  

I have spoke to him and he does want one thing though.  Not sure if it is possible - i really dont know.

Eg, if the document is formated thus;

3.      [EXCLUSION OF SECURITY OF TENURE
3.1      The parties confirm that:
(a)      the Landlord served a notice on the Tenant, as required by section 38A(3)(a) of the 1954 Act and which applies to the tenancy to be created by the Lease, [not less than 14 days] before this agreement was entered into (a certified copy of which notice is annexed to this agreement); and
(b)      [the Tenant] [[NAME OF DECLARANT], who was duly authorised by the Tenant to do so], made a [statutory] declaration dated [DATE] in accordance with the requirements of section 38A(3)(b) of the 1954 Act (a certified copy of which [statutory] declaration is annexed to this agreement).


Would like it;


3.      [EXCLUSION OF SECURITY OF TENURE
      3.1      The parties confirm that:
      the Landlord served a notice on the Tenant, as required by section 38A(3)(a) of the 1954 Act and which applies  to the tenancy to be created by the Lease, [not less than 14 days] before this agreement was entered into (a certified copy of which notice is annexed to this agreement); and
      3.2     [the Tenant] [[NAME OF DECLARANT], who was duly authorised by the Tenant to do so], made a [statutory]     declaration dated [DATE] in accordance with the requirements of section 38A(3)(b) of the 1954 Act (a certified copy of which [statutory] declaration is annexed to this agreement).


As I say I am not sure if this is possible but if it is I would be sooo happy :-)  

Thanks Ronald (No immediate rush for today if you are busy...)

Have a nice weekend.

Matt
RonaldBiemansCommented:
No, I don't think you can do that, that would require a lot of intelligence from Word which it doesn't have :-),
You could maybe write a program that does that using some pretty complicated regular expressions, But even there I'm not sure if it will work
matt_swinburneAuthor Commented:
No i didnt think that it would be workable.  He will have to be disapointed.  I guess we have finished for now!  I will award the points as I know you will help if i need anymore.

Thanks Ronald.
matt_swinburneAuthor Commented:
I have a slight problem Ronald.  The macro works fine on a saved document (which for the majoirity is how it works as it is automatically set to the correct formating when a new document is opened.)  However when you open a brand-new document i get the same errror.  4149 The file is not found.  Is there a way around this?
RonaldBiemansCommented:
No, a brand new document needs to be saved first before you can use the copy command, you could save the file in code automatically to a generic default name first ofcourse.
matt_swinburneAuthor Commented:
emmm that sounds good.  The users are bound to try it and I dont want an error to come up.  That way sounds good although even a message saying to save document before u run macro would be good.  Ideallly though the 1st idea sounds better although they wouldnt know it had been saved?  and would it automatically overwrite when for example another new document was created (it wouldnt carry on creating them would it and then have lots and lots of temp documents?
RonaldBiemansCommented:
That is very easy to do and the user will never notice if the file is called document1 or _document1 for instance :-)
matt_swinburneAuthor Commented:
sounds excellent!  could you help me with the coding?
RonaldBiemansCommented:
Yep, just a second :-)
RonaldBiemansCommented:
try this

Private Const c_szTemplateFile As String = "C:\commercial.dot"
Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close

' ***** TRY THIS

If oTargetDoc.Path = "" Then
    oTargetDoc.SaveAs ("c:\_document1.doc")
End If

' ********

      For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc.Path & "\" & oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub

You probably don't want to save it in the c:\, so choose a more appropriate directory to save the temp file (maybe the temp directory :-))

matt_swinburneAuthor Commented:
But doesnt this mean that it will just stay there until the temp file emptys itself?  I dont think that this emptys itself that regulaly and wont this mount up?  doesnt really matter but just wondering.  Isnt there coding or something that sounds a bit like this;
environ"$temp$"
to specify the tempoary folder as it is user specific?
RonaldBiemansCommented:
But it is only one file, so I don't understand what you mean by mount up ? it is overwritten everytime you use a new file.
matt_swinburneAuthor Commented:
oh yeah! haha just realised/
matt_swinburneAuthor Commented:
I just thought though.  If we do that then when the user edits the document and goes to close it acts as if it has already been saved, and when the user selects yes to save it will just close.  Sorry to waste your time but it would probably be better for when the macro is run it prompts the user to save the document?
RonaldBiemansCommented:
Yes, good point, I think that is the way go.
matt_swinburneAuthor Commented:
:-)
matt_swinburneAuthor Commented:
Any chance of the coding?  or are you working on it?  becos i am a little lost.....
matt_swinburneAuthor Commented:
I have this so far;

If ActiveDocument.Saved = False Then
     
      MsgBox "Need to Save Document"
     Dim savdlg As Dialog
     Set savdlg = Dialogs(wdDialogFileSaveAs)
     savdlg.Display
         
End If

(And it skips straight through the if statement as if it has been saved)
RonaldBiemansCommented:
better to use

If oTargetDoc.Path = "" Then
    MsgBox "Need to Save Document"
     Dim savdlg As Dialog
     Set savdlg = Dialogs(wdDialogFileSaveAs)
     savdlg.Display
         
End If
matt_swinburneAuthor Commented:
That works sweet!! Could we get it to save as a doc though.  Automatically it is trying to save commercial.dot  (users will probably not notice this and save as a template) any suggestions?
matt_swinburneAuthor Commented:
And also could you put some error handling so that if the user presses cancel it doesnt hit an error? :-)
RonaldBiemansCommented:
I'll have to search for that because like I said before I'm not that good in VBA :-)
matt_swinburneAuthor Commented:
Also even if i save (as a word doc) it hits the original cannot find file error.
matt_swinburneAuthor Commented:
No problem Ronald, sorry for asking so many questions...
RonaldBiemansCommented:
Sorry it took so long, but I had my own work to do too :-),

Try this


Private Const c_szTemplateFile As String = "C:\commercial.dot"
Sub CopyStyles()
   
        Dim oStyle As Word.Style
       Dim oSourceDoc As Word.Document
        Dim oTargetDoc As Word.Document
        Dim a_szStyleNames() As String
        Dim nLoop As Integer
   
        Set oTargetDoc = ActiveDocument
        Set oSourceDoc = Documents.Open(c_szTemplateFile)

     
        'RETRIEVE STYLE NAMES FROM SOURCE DOCUMENT
        nLoop = 0
        For Each oStyle In oSourceDoc.Styles
            If oStyle.InUse Then
            ReDim Preserve a_szStyleNames(nLoop)
            a_szStyleNames(nLoop) = oStyle.NameLocal
            nLoop = nLoop + 1
            End If
        Next oStyle
        oSourceDoc.Close
       
     If oTargetDoc.Path = "" Then
    MsgBox "Need to Save Document"
 Dim iDlgAnswer As Integer
    Dim savdlg As Dialog
    Set savdlg = Dialogs(wdDialogFileSaveAs)
    savdlg.Format = wdFormatDocument
    iDlgAnswer = savdlg.Show
 'Successful completion returns iDlgAnswer = -1, Cancel = 0, Close box = -2
    If iDlgAnswer <> -1 Then
       Exit Sub
       End If
End If

      For nLoop = 0 To UBound(a_szStyleNames()) - 1
Application.OrganizerCopy Source:= _
        c_szTemplateFile _
        , Destination:=oTargetDoc.Path & "\" & oTargetDoc, Name:=a_szStyleNames(nLoop), Object:=wdOrganizerObjectStyles
 
        Next nLoop
   
    End Sub



matt_swinburneAuthor Commented:
Thanks Ronald!! It Works!! I have been looking myself most of the day.  I cant see any errors either so all is looking good :-)  

RonaldBiemansCommented:
Glad I could help, until the next time :-)
matt_swinburneAuthor Commented:
Is it possible to get the macro, instead of specifying where the macro is specifically, to get it to search inside a folder for a template as the name might change?
RonaldBiemansCommented:
?? I don't quite understand what you mean Matt
matt_swinburneAuthor Commented:
sorry said that wrong, apparently u can specify the workgroup tempate folder and get it through VB, so i where the location is N:\Templates\Styles\Commercial.dot  I would only hard code \Styles\Commercial.dot and use VB to find my workgroup templates.
RonaldBiemansCommented:
So its solved ?
matt_swinburneAuthor Commented:
emmm..no i cant find the command.  So instead of using this line: Private Const c_szTemplateFile As String = "N:\Workgroup Templates\commercial.dot"

I would use something like

Private Const c_szTemplateFile As String = <Command> & "\commercial.dot"

and VBA would pull the workgroup template location from Tools>>Options>>File Locations

Do you know what I mean?
RonaldBiemansCommented:
probably something like

templateDIR = objWord.Options.DefaultFilePath(wdUserTemplatesPath)
RonaldBiemansCommented:
sorry in your case

Sub CopyStyles()
Dim c_szTemplateFile As String
c_szTemplateFile = Options.DefaultFilePath(wdWorkgroupTemplatesPath) & "\commercial.dot"
matt_swinburneAuthor Commented:
That worked brilliantly thank you once again Ronald.  As far as I know it is actually finished!  I am going to demo it to the users later hopefully so maybe changes.....but i doubt it.  

Thanks

Matt
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.