Search code examples
excelvba

Save file with new name if file already exists


I created a UserForm where my team can select the type of report they need, "Condizione di Pericolo" / "Mancato Infortunio" / "Infortunio".
This selection is stored in the variable evento.

After that, I want the file to create and save a copy of the report in a folder based on the report selected.
In SharePoint I have folders "Condizione di Pericolo" / "Mancato Infortunio" / "Infortunio".

The name of the file is standard and based on the date and the name of the user.

There is the possibility that someone makes the same report twice or more in the same day.
I don't want anything to be overwritten, that is why I'm trying to check if in the correct folder there is a file with the same name. If there is, I want the new one to add a suffix like (1) (just like when we make a copy of a file).

Sub SaveReport()

    Const path As String = "https://SharePointPath/Main%20Folder/"
    Dim i As Long
    Dim Saved As Boolean
    
    i = 1
    Saved = False
    evento = "Condizione di Pericolo"   ' Just to test the code

    Sheets("Modulo19").Activate         ' Redondant, now I know!
    ActiveSheet.Copy
    
    If evento = "Condizione di Pericolo" Then
        ' filename = path + nome del file + estensione
        filename = path & "/" & "Condizione%20di%20Pericolo" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & ".xlsx"
        
        ' Check to see if the file exist
        If Len(Dir(filename)) = "" Then
            ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
            Call GeneraReport
            Exit Sub
        Else
        End If
        
        ' If it exist, let's use another name
        Do While Saved = False
            If Len(Dir(filename)) <> "" Then
                filename = path & "/" & "Condizione%20di%20Pericolo" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & "_(" & i & ")" & ".xlsx"
                ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
                Saved = True
                Call GeneraReport
            Else
                i = i + 1
            End If
        Loop
        

    ' From now on is just the same code repeating...

    ElseIf evento = "Mancato Infortunio" Then
        filename = path & "/" & "Mancato%20Infortunio" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & ".xlsx"
        
        If FileExist(filename) = False Then
            ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
            Call GeneraReport
            Exit Sub
        Else
        End If
        
        Do While Saved = False
            If FileExist(filename) = False Then
                filename = path & "/" & "Mancato%20Infortunio" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & "_(" & i & ")" & ".xlsx"
                ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
                Saved = True
                Call GeneraReport
            Else
                i = i + 1
            End If
        Loop

        
    ElseIf evento = "Infortunio" Then
        filename = path & "/" & "Infortunio" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & ".xlsx"
        
        If FileExist(filename) = False Then
            ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
            Call GeneraReport
            Exit Sub
        Else
        End If
        
        Do While Saved = False
            If FileExist(filename) = False Then
                filename = path & "/" & "Infortunio" & "/" & Format(Now(), "dd-mm-yyyy") & "_" & Split(Application.UserName, " ")(1) & "_(" & i & ")" & ".xlsx"
                ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook
                Saved = True
                Call GeneraReport
            Else
                i = i + 1
            End If
        Loop
      
    End If
    
End Sub

The forward slash / is not a problem for the SaveAs command. I use it in other files.

Right now, I have the problem with the Dir command.

I have this error:

Run-time error '52': Bad file name or number

Run-time error '52': Bad file name or number

I also use this Function called FileExist found on the internet.

Function FileExist(FilePath As String) As Boolean
'PURPOSE: Test to see if a file exists or not
'SOURCE: www.TheSpreadsheetGuru.com/The-Code-Vault

Dim TestStr As String

'Test File Path (ie "C:\Users\Chris\Desktop\Test\book1.xlsm")
  On Error Resume Next
    TestStr = Dir(FilePath)
  On Error GoTo 0

'Determine if File exists
  If TestStr = "" Then
    FileExist = False
  Else
    FileExist = True
  End If

End Function

In this case I always get Empty as result, so for the Function I do not have a file with the same name and it overwrites it.


Solution

  • (Previous response from when we were discussing local paths...)

    Here's a simpler version (edit: per FunThomas's answer, forward slashes should be backslashes):

    Sub SalvaReport()
    
        Const path As String = "C:\SharePointDirectory\SharePoint%20Folder\"
        Dim i As Long, fnTemplate As String, fldr As String, fileName As String, evento As String
        
        i = 0
        evento = "Condizione di Pericolo"  ' etc
        fldr = Replace(evento, " ", "%20") 'replace spaces with %20
        
        'File name template: `{tmp}` is a token to be replaced...
        fnTemplate = path & "\" & fldr & "\" & _
                    Format(Now(), "dd-mm-yyyy") & "_" & _
                    Split(Application.UserName, " ")(1) & "{tmp}.xlsx"
                    
        fileName = Replace(fnTemplate, "{tmp}", "") 'start with no counter
        Do While Len(Dir(fileName, vbNormal)) = 0   'file exists?
            i = i + 1
            fileName = Replace(fnTemplate, "{tmp}", "(" & i & ")") 'add counter
        Loop
        
        ThisWorkbook.Worksheets("Modulo19").Copy  ' Copio l'intera sheets "Modulo19"
        ActiveWorkbook.SaveAs fileName, FileFormat:=xlOpenXMLWorkbook
        GeneraReport 'no need for `Call`
             
    End Sub
    

    Added after it was clear you're looking for something to check for files over HTTP[S] (where Dir() won't work)...

    You can use ADO to query a SharePoint List/Library - see example code below. You could use this as a basis for finding if a given filename already exists.

    Sub ListSPLibraryFiles()
        '## Add a VBA project reference to the ADO object library ##
        Const SERVERUrl As String = "https://contoso.sharepoint.com/sites/ABCSite/"
        Const ListName As String = "{f82ace17-b0c2-48b4-aa1c-b5d93ddb0c35}" 'List/Library *GUID*
        
        Dim Conn As New ADODB.Connection, rs As ADODB.Recordset
        Dim sql As String, objWksheet As Worksheet
        
        With Conn
            .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=0;RetrieveIds=Yes;" & _
                                 "DATABASE=" & SERVERUrl & ";" & _
                                 "LIST=" & ListName & ";"
            .Open ' Open the connection
        End With
         
        'query all library records for xlsx docs
        sql = "SELECT * FROM [" & ListName & "] where [Content Type]='Document' and [File Type]='xlsx'"
        Set rs = New ADODB.Recordset
        rs.Open sql, Conn, adOpenStatic
        
        PutToSheet rs, ThisWorkbook.Worksheets("Results") 'display the results
        
        rs.Close
        Conn.Close
    End Sub
    
    'load field names and data from `rs` to worksheet `ws`
    Sub PutToSheet(rs As ADODB.Recordset, ws As Worksheet)
        Dim f As ADODB.Field, i As Long
        With ws
            .Cells.Clear 'clear any previous data
            If Not rs.EOF Then
                For Each f In rs.Fields
                    ws.Range("A1").Offset(0, i).Value = f.Name
                    i = i + 1
                Next f
                ws.Range("A2").CopyFromRecordset rs
            End If
        End With
    End Sub
    

    Check out what shows up on the "results" sheet and figure out how to use that info to confirm a given path.