0

.................................................................................................................................................................. Late-breaking news... P.P.S. I just read that FileSystem.FileCopy is better than just FileCopy. That's what I'm going to try. But I really would like to know how to use FileCopy inside a loop, meaning, "How do I close files used in FileCopy?" For the big picture made clear, read on. ..................................................................................................................................................................

(Using Windows 10 Pro, Word 365 Pro)

The online Help for FileCopy Src, Dest says that it ... Copies a file from Src to Dest [but] does not work on a currently open file. Both ... files must be closed [by] the Close statement.

But the online help for Close, from link supplied on that page connects to help for Close for the Open statement, which says that it "Closes the file(s) previously opened with the" Open statement, not the FileCopy statement.

So it is that I'm stumped on what to do with this code, which will copy the first code module in the Document to a backup location, but not the second.

Pic#1: Info about what's supposedly going to be copied

enter image description here

Pic#2: Original error message without On Error

enter image description here

(I have no clue why all these blank lines. They're NOT in my Body.)

Please ignore all the OnError stuff for now.

When the second code module should have been copied, execution halted with error "File not found".

Sub BackupModules()
    Dim prj As VBProject
    Dim comp As VBComponent
    Dim code As CodeModule
    Set prj = ThisDocument.VBProject
    Dim k As Integer, n As Integer
    Dim Destination As String, Prefix As String
    Prefix = "junk"
    k = 0: n = 0
On Error GoTo x
    For Each comp In prj.VBComponents
On Error GoTo x
        k = k + 1
        If comp.Type = vbext_ct_StdModule Then
          n = n + 1
          Destination = Prefix & n
          MsgBox "Copying Standard module " & n & " of " & k & " components encountered: <" & comp.Name & "> to " _
                 & Destination & "; # lines: " & comp.CodeModule.CountOfLines
On Error GoTo x
          FileCopy comp.Name, Destination
          MsgBox "Success"
          Close
        Else

x: If Err.Number <> 0 Then: _
msg = "Error # " & Str(Err.Number) & " was generated by " _
& Err.Source & Chr(13) & Err.Description: _
MsgBox msg, , "Error", Err.HelpFile, Err.HelpContext: On Error GoTo 0: Close:

       End If
    Next

End Sub

Then I began experimenting (a LOT as you can see) with On Error Goto x being placed at various places (one at a time and then all, as shown) and the nasty-looking but syntactically and logically correct line that starts x: If Err... placed inside the Else block.

Pic#3: Error msg after using On Error

enter image description here

(FWIW, I just spotted Normal in the Err.Source part of the error message above. Online help says, "When an unexpected error occurs in your code, the Source property is automatically filled in. For errors in a standard module, Source contains the project name. For errors in a class module, Source contains a name with the project.class form." Indeed, the code is in a Module within the Normal Project.)

Pic#4: Line causing error that On Error did NOT trap enter image description here

So what's wrong? I've tried everything I can think of. The only help I could find for Close did NOT mention its use with FileCopy. My Close usages caused no error but did Close close both the source and the destination file? Surely not. First use of FileCopy worked, files (probably) not closed, thus second use of FileCopy failed. Docs say using FileCopy on an open file will cause error.

On Error Goto x or to 0 is neither here nor there. That's why I said to ignore them at first.

The question is apparently "How do I close both files mentioned in FileCopy?"

P.S. Per opening blurb, I'm NOT gonna do this. I suppose I could use Open ... For Input As File#1 and specify the Module's name, if it's readily available to code, and also Open ... For Output As File#2 for the destination, use a For loop to copy the number of lines, if available, and then Close both. But I hope I get a solution to my problem before I try that since SURELY FileCopy should work within a loop (and doesn't because of improper close).

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • A code module is not a file, so it's unclear how you expect to use FileCopy here? Did you mean to first export the code module to a file (in which case you could just export it to the final location)? https://eileenslounge.com/viewtopic.php?f=26&t=14146 – Tim Williams Feb 01 '20 at 22:46
  • @TimWilliams--Ah. Yes. `Module <> File`. Didn't know about `Export`. I'll give that sufficient thought to expect it to help. The Link uses it but no clue how it would `Export` modules in `Normal.dotm`. It shows two folders that contain no templates, so I backed up the tree and chose the `Templates` folder that contains `Normal.dotm`, which contains the modules that I need to back up. It found ONE `VBComponent`--`ThisDocument`--and Exported it to the `Templates` folder, but no Modules were copied. The one output file, `ThisDocument.txt` is useless. I guess you've used the link. How do I use it? – DSlomer64 Feb 02 '20 at 13:49
  • @TimWilliams--Geez. THANKS for the tip about `Export`. I hadn't used File System Object before and overlooked `Export` while looking carelessly around. REALLY simplified matters. – DSlomer64 Feb 02 '20 at 17:22
  • @TimWilliams---- HEY -- Submit your `Export` comment as an Answer and I'll make it THE Answer. – DSlomer64 Feb 02 '20 at 17:31
  • No need for me to post - you can accept your own answer – Tim Williams Feb 02 '20 at 17:46
  • NAW! YOU the MAN, not me! ... Oh, but with 102K++ rep... I gotcha... ;^} – DSlomer64 Feb 02 '20 at 23:25

1 Answers1

0

Thanks to @TimWilliams, who tipped me off to Export, my final "Backup all modules" routine is quite simple.

Sub BackupModules()
    Dim comp As VBComponent
    Dim prj As VBProject:     Set prj = ThisDocument.VBProject
    Dim fso As Object:        Set fso = CreateObject("Scripting.FileSystemObject")
    Dim destPrefix As String: destPrefix = "C:\Users\Dov\Google Drive\Word\Modules\"
    Dim destFilePath As String

    For Each comp In prj.VBComponents
        If comp.Type = vbext_ct_StdModule Then
            destFilePath = destPrefix & comp.Name & " " & Year(Now) & " " & Month(Now) & " " & Day(Now)
            Debug.Print "Copying Standard module <" & comp.Name & "> to <" & destFilePath & ">"
            comp.Export (destFilePath)
        Else
            Debug.Print "Skipping component # " & k & ", <" & comp.Name & ">, type " & comp.Type
       End If
    Next
End Sub
DSlomer64
  • 4,234
  • 4
  • 53
  • 88