excelvba

Can't solve "method range of object _Worksheet failed"


The last 2 weeks I have immersed myself in VBA. It's great but since last week I have been struggling with the following error: "VBA method 'range of object' _Worksheet failed" with this line of code:

wsSource.Range(Cells(7, ColumnNr), Cells(lrowSource, ColumnNr)).Copy

I can't find the solution.

This is the entire VBA-code:

Sub CopyColums()
Application.ScreenUpdating = False

cPath = "H:\2017\"
ChDrive cPath
ChDir cPath

cFile = Application.GetOpenFilename("Excel files (*.xls*), *.xls*")
Workbooks.Open cFile, UpdateLinks:=3, ReadOnly:=False, Notify:=False, Password:="****"

Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim lrowSource As Integer

Sheets.Add(After:=Sheets(Sheets.Count)).Name = "import"

Set wsSource = Sheets(1)
Set wsTarget = Sheets("import")

wsTarget.Range("A1").Value = "header 1"
wsTarget.Range("B1").Value = "header 2"
wsTarget.Range("C1").Value = "header 3"
wsTarget.Range("D1").Value = "header 4"
wsTarget.Range("E1").Value = "header 5"
wsTarget.Range("F1").Value = "header 6"
wsTarget.Range("G1").Value = "header 7"
wsTarget.Range("H1").Value = "header 8"
wsTarget.Range("I1").Value = "header 9"
wsTarget.Range("J1").Value = "header 10"
wsTarget.Range("K1").Value = "header 11"
wsTarget.Range("L1").Value = "header 12"
wsTarget.Range("M1").Value = "header 13"
wsTarget.Range("N1").Value = "header 14"

lrowSource = wsSource.Cells(Rows.Count, "A").End(xlUp).Row

'A to A
wsTarget.Range("A2:A" & lrowSource - 5).NumberFormat = "d-m-yy;@" 
wsSource.Range("A7:A" & lrowSource).Copy
wsTarget.Range("A2").PasteSpecial xlPasteValues

'E to B
wsSource.Range("E7:E" & lrowSource).Copy
wsTarget.Range("B2").PasteSpecial xlPasteValues

'F to C
wsSource.Range("F7:F" & lrowSource).Copy
wsTarget.Range("C2").PasteSpecial xlPasteValues

'O to D
wsSource.Range("O7:O" & lrowSource).Copy
wsTarget.Range("D2").PasteSpecial xlPasteValues

'Look for column and copy to I
ColumnNr = Application.Match("Total partner", Sheets(1).Rows(6), 0)
wsSource.Range(Cells(7, ColumnNr), Cells(lrowSource, ColumnNr)).Copy
wsTarget.Range("I2").PasteSpecial xlPasteValues

Application.CutCopyMode = False

'Save as CSV
NameImportFile= Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5) 'to remove .xlsx
Filepath = cPath & NameImportFile& ".csv"
ActiveWorkbook.SaveAs Filename:=Filepath, FileFormat:=xlCSV, CreateBackup:=False, Local:=True

End Sub

Can somebody please help me?

Kind regards, Richard


Solution

  • I'm guessing that Sheets(1) isn't active when that line executes.

    If that is the case then wsSource is pointing at Sheets(1) while Cells isn't qualifying the sheet it's using, so it's using the currently active sheet.

    Try using:
    wsSource.Range(wsSource.Cells(7, ColumnNr), wsSource.Cells(lrowSource, ColumnNr)).Copy.

    As an edit (after answer accepted) I'd probably rewrite the procedure:

    Option Explicit
    
    Public Sub CopyColumns()
    
        Dim cPath As String
        Dim cFile As String
        Dim wrkBk As Workbook
        Dim wsSource As Worksheet
        Dim wsTarget As Worksheet
        Dim lRowSource As Long
        Dim ColumnNr As Long
    
        cFile = GetFile("H:\2017\")
    
        'Continue if a file was selected.
        If cFile <> "" Then
            Set wrkBk = Workbooks.Open(cFile)
            Set wsSource = wrkBk.Worksheets(1)
    
            'Set a reference to worksheet when it's created.
            Set wsTarget = wrkBk.Worksheets.Add
            With wsTarget
                .Name = "Import"
                .Move After:=wrkBk.Sheets(wrkBk.Sheets.Count)
    
                'Can use autofill for headers as they're numbered.
                wsTarget.Range("A1") = "Header 1"
                wsTarget.Range("A1").AutoFill Destination:=Range("A1:N1"), Type:=xlFillDefault
                'Could also use
                'wsTarget.Range("A1:N1") = array("Header 1", "Header 2", "Header 3", etc....)
    
            End With
    
            'Can use letter or number designation for column in Cells.
            lRowSource = wsSource.Cells(Rows.Count, 1).End(xlUp).Row
    
            With wsSource
                'This will fail if the lRowSource is 5 or less... lRowSource-5 = 0.
                wsTarget.Range(wsTarget.Cells(2, 1), wsTarget.Cells(lRowSource - 5, 1)).NumberFormat = "d-m-yy;@"
                ColumnNr = Application.Match("Total partner", wsSource.Rows(6), 0)
                'Use UNION to copy columns A,E:F,O & ColumnNr
                Union(.Range(.Cells(7, 1), .Cells(lRowSource, 1)), _
                      .Range(.Cells(7, 5), .Cells(lRowSource, 6)), _
                      .Range(.Cells(7, 15), .Cells(lRowSource, 15)), _
                      .Range(.Cells(7, ColumnNr), .Cells(lRowSource, ColumnNr))).Copy
    
                wsTarget.Cells(2, 1).PasteSpecial xlPasteValues
    
            End With
    
            wsTarget.Copy
            With wrkBk
                'Save with workbook name as CSV.
                ActiveWorkbook.SaveAs .Path & Application.PathSeparator & _
                    Left(wrkBk.Name, InStrRev(wrkBk.Name, ".")) & "csv", 6
    
                'Save with worksheet name as CSV.
                'ActiveWorkbook.SaveAs .Path & Application.PathSeparator & _
                   wsTarget.Name & ".csv", 6
    
            End With
    
        End If
    
    End Sub
    
    Function GetFile(Optional startFolder As Variant = -1) As Variant
        Dim fle As FileDialog
        Dim vItem As Variant
        Set fle = Application.FileDialog(msoFileDialogFilePicker)
        With fle
            .Title = "Select a File"
            .AllowMultiSelect = False
            .Filters.Add "File to copy columns from", "*.xls*", 1
            If startFolder = -1 Then
                .InitialFileName = Application.DefaultFilePath
            Else
                If Right(startFolder, 1) <> "\" Then
                    .InitialFileName = startFolder & "\"
                Else
                    .InitialFileName = startFolder
                End If
            End If
            If .Show <> -1 Then GoTo NextCode
            vItem = .SelectedItems(1)
        End With
    NextCode:
        GetFile = vItem
        Set fle = Nothing
    End Function