Speed file copy from macro

Hello,

In a personal video database, I would like to be able to transfer a video to another media (eg. external hard drive) just by clicking a dedicated button within a form.

My issue is on the file copy process within the macro. I’ve found 3 different ways to proceed:

  1. FileCopy statement, which is operating very well
  2. File I/O Functions, with opening source and target files, get from source and put to target, then closing file
  3. SimpleAccessFile procedures (see section 8.9.3 in Pitonyak’s book OpenOffice.org Macros Explained) with streams, readBytes() and writeBytes() functions.

All of 3 solutions work. However :

  • Solution 1 is really very very faster (at least in my tries) but as a “single-time” process, it seems that nothing else could be done until the copying is ended
  • Solutions 2 and 3 are very very slow, but as either bits or bundles of bits are copied at a time, it is possible to process another action after each bit/bundle transfer.

Actually, I was looking for such a solution (like Solutions 2 and 3), as I would like to display a progress bar during the transfer, and refresh it with the right percentage/bar advancement. But given the so long time transfer with Solutions 2 and 3, it is not convenient at all (for movie files of several 100 Go…).

So my questions are:

  • is it possible to stop/pause the FileCopy process (in order to actualize the progress bar)?
  • and/or is it possible to speed up (boost) the Solutions 2 or 3?

For information, I provide in the following my Sub code for the above mentioned solutions (it’s the first time I used these processes, so my approach may be not accurate…):

Solution 1:

Sub FileCopyTransfer
    sSource = "/myVideo.mp4"
    sTarget = "/myVideo2.mp4"
    FileCopy(sSource,sTarget)
End Sub

Solution 2:

Sub IOTransfer
    sSource = "/myVideo.mp4"
    sTarget = "/myVideo2.mp4"
    nS = Freefile
    Open sSource For Binary Access Read As nS
    nT = FreeFile
    Open sTarget For Binary As nT
    Dim v as Long
    location = Loc(nS)
    While Not Eof(nS)
        Get nS, location+1, v
        Put nT,,v
        location = Loc(nS)
    Wend
    Close nS
    Close nT
End Sub

Solution 3:

Sub SimpleFileAccessTransfer
    ' SimpleFileAccess service'
    Dim sFileName$ ' Name of file to open'
    Dim oStream	' Stream returned from SimpleFileAccess'
    Dim oMyStream ' Stream service'
    
    sFileSource = "/myVideo.mp4"
    sFileTarget = "/myVideo2.mp4"
    
    ' Create the SimpleFileAccess service'
    oSFASource = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
    oSFATarget = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
    
    ' Create the Specialized source (input)  and target (output) streams'
    oMyStreamSource = CreateUnoService("com.sun.star.io.DataInputStream")
    oMyStreamTarget = CreateUnoService("com.sun.star.io.DataOutputStream")
    
    ' Open the source file for reading and target file for writing'
    oStreamSource = oSFASource.openFileRead(sFileSource)
    oStreamTarget = oSFATarget.openFileWrite(sFileTarget)
    
    ' Connect the source file to input stream and target file to output stream'
    oMyStreamSource.setInputStream(oStreamSource)
    oMyStreamTarget.setOutputStream(oStreamTarget)
    
    ' Define bits block to work with (1/10 of file size) and variable to store them'
    nb = Int(oStreamSource.Length/10)+1
    Dim Bundle() As Long
    
    While oMyStreamSource.InputStream.Position < oStreamSource.Length
            oMyStreamSource.readBytes(Bundle(),nb)
            oMyStreamTarget.writeBytes(Bundle())
    Wend
End Sub

Thanks for any idea!

I understand your desire to visualize the process, but is it worth doing? Isn’t it enough to know that the specified file actually exists in the source location, is not present in the target folder, and the copy process has started? Why not use Shell() with bSync = false? Let the operating system copy files, and you will continue to work with the database.

@JohnSUN,
Thanks for your comment.
I never used Shell(), but sounds interesting.
With it, is it possible to launch a file copy…?

Of course my ‘problem’ is not a big deal, moreover it’s a side-side-project so no much issue. In that way this is a way to learn a bit more with LibreOffice. But if not possible, I can just have a message box telling me that the transfer has been completed correctly.

Any operating system has several commands for copying files. We can say that any operating system is made to manipulate files (Actually - no, it’s just as wrong as saying “any operating system is made to spy on a computer user”). The built-in file copying programs work as efficiently as possible, at least not worse than FileCopy(). Search shell for this resource and you will find several examples of using this function. Shell launches command execution in a separate window. The fact that you see this window on the screen means that the copy command has not finished yet. How can you check if the copy was successful? I don’t know, I didn’t think about it. In most, in the vast majority of cases, the command will execute successfully. Failures are so rare that it doesn’t make sense to specifically handle the situation. What could go wrong? Low on disk space? Your OS should have warned you “Low space” in advance.

Something to consider: python macro starting a different process that copies the file. Like this one: multithreading - Python UNO and Threads - Stack Overflow

@JohnSUN,
Thanks for the indications. I’ve indeed succeeded using Linux cp command from macro. It doesn’t bring any information on progress, however, as you stated your first comment, with the bSync parameter, it allows to not be stopped during the copy-paste process, which is quite useful.
Regarding the check of successful transfer, actually I was just thinking of having a simple message box when the process is done, regardless it has been processed successfully.

@Przemo,
Thanks for the link. It may be a good option, however, even if I have real plans to learn Python soon, I’m not there already… But I keep it in mind for future!

I think I will stay on the Shell() function, and program a progress bar that does not update during a single file transfer, but between two file transfers (so just from 0 to 100% if only one file is transferred.
I’ll edit my post when done.

1 Like