1

I am trying to copy data from a "Data" worksheet into a already created worksheet called "DateData". I want the user to be able to enter in a Start Date ("L15") and End Date ("L16") in a separate worksheet called "No Entry". On a button click...Then the data in "Data" worksheet is pulled into the "DateData" Worksheet, only including records between those dates (including the start and entry date). I hope that makes sense haha

I have tried the below but keep getting errors. The first being a "Sort method of Range class failed 1004". The code below also doesn't use the preset worksheet to copy data but creates a sheet at the end of all worksheets (which I don't want).

The "Data" worksheet has titles all in row 1 and data starts from A2 onwards...It has 19 columns of titles (so data filled) and the date that I want it looking for is in column G..G1=Title, G2 = Date starts. Date format = dd/mm/yyyy

How would I go about doing this? Any help would be so grateful. Thank you

Private Sub CommandButton2_Click()

Application.ScreenUpdating = False

Dim StartDate, EndDate As Date
Dim MainWorksheet As Worksheet

StartDate = Sheets("NoEntry").Range("L15").Value
EndDate = Sheets("NoEntry").Range("L16").Value

Set MainWorksheet = Worksheets("Data")

MainWorksheet.Activate

Range("G1").CurrentRegion.Sort key1:=Range("G1"), order1:=xlAscending, Header:=xlYes

Range("G1").CurrentRegion.AutoFilter Field:=7, Criteria1:=">=" & StartDate, Operator:=xlAnd,        
Criteria2:="<=" & EndDate

ActiveSheet.AutoFilter.Range.Copy

Worksheets.Add after:=Worksheets(Worksheets.Count)

ActiveSheet.Paste

Selection.Columns.AutoFit

Range("G1").Select

MainWorksheet.Activate

Selection.AutoFilter

Sheets("NoEntry").Activate

End Sub

"DateData"

"Data"

So as you can see from the "Data" worksheet I have sorted the data but because it has blanks they are at the bottom (as in there are no dates in the G column for it). This was before validation so this happened

And what copies over onto the "DateData" worksheet is only the records with blank dates.

Sorry for the black filled records as they are private information. I hope that makes sense.

Donald
  • 17
  • 5
  • 1
    `Dim StartDate as Date, EndDate as Date`. You have to assign each variable type individually (common mistake :) – urdearboy Sep 30 '19 at 14:27
  • What column should be filtered? You are looking to filter 7 columns out from `G` – urdearboy Sep 30 '19 at 14:30
  • @urdearboy Thanks will change that, Sorry I want all column G filtered. I was experimenting with the field 7 I thought it would be the 7th column...clearly that's wrong? Please note I am not sure if above is the best way - if any other way can be done please show :) – Donald Sep 30 '19 at 14:35
  • The field option depends on where your current range starts. The first column in range will be the first field. So it looks like you want to change that 7 to a 1 (same logic that is used for your sort option where `key = 1` – urdearboy Sep 30 '19 at 14:37
  • @urdearboy Cheers lad, I've changed that but still receiving the same error – Donald Sep 30 '19 at 14:41
  • 1
    The reason why it is adding a new worksheet is because of `Worksheets.Add`.... – Dean Sep 30 '19 at 15:36

2 Answers2

0

First, see How to avoid using Select in Excel VBA to learn how to avoid using select in your code. There is almost no necessary case in using it.

See below notes for the code I provide (now tested!).

1) You are having an issue where a worksheet is being added and you are not aware how/ why and you are uncertain of your destination for your data. To overcome this, it is a common practice to explicitly define your worksheet objects. This makes it easier for you to understand, while also allowing for less scope for error. I have qualified the worksheets as wsData for “Data worksheet”, wsDate for “DateData worksheet” and wsNoEntry for “No Entry worksheet”. Do you see how easy it is to understand now?

2) Make sure that the dates in your data set are stored as “Date” type values. You can do this under the number formatting ribbon.

3) I have chosen to use an array to loop through. Depending on how big your data set is, this will be a much faster way to loop through to get the start and end date

4) This approach assumes your data is sorted by the Date column (G)

Sub CopyDataUsingDateRange()

    Application.ScreenUpdating = False

    Dim wsData As Worksheet, wsDate As Worksheet, wsNoEntry As Worksheet
    Dim dSDate As Date, dEDate As Date
    Dim lRowStart As Long, lRowEnd As Long
    Dim aData() As Variant
    Dim i As Long


    'set the worksheet objects
    Set wsData = ThisWorkbook.Sheets("Data")
    Set wsDate = ThisWorkbook.Sheets("DateData")
    Set wsNoEntry = ThisWorkbook.Sheets("No Entry")

    'required variables
    dSDate = wsNoEntry.Range("L15").Value
    dEDate = wsNoEntry.Range("L16").Value

    'set the array - you can make this dynamic!
    aData = wsData.Range("A1:Z1000").Value

    'for loop to find start
    For i = 1 To 1000
        If aData(i, 7) = dSDate Then
            lRowStart = i
            Debug.Print "Start row = " & lRowStart
            Exit For
        End If
    Next i

    'now loop backwards to find end date
    For i = 1000 To 1 Step -1
        If aData(i, 7) = dEDate Then
            lRowEnd = i
            Debug.Print "End row = " & lRowEnd
            Exit For
        End If
    Next i

    'now we have start and end dates
    'going to use copy/ paste for simplicity
    wsData.Range("A" & lRowStart, "Z" & lRowEnd).Copy
    'paste in date sheet
    wsDate.Range("A1").PasteSpecial Paste:=xlPasteValues
    'clear clipboard
    Application.CutCopyMode = False

    Application.ScreenUpdating = True

End Sub

Hope this helps, mostly with understanding so you can leverage for future use!

Dean
  • 2,326
  • 3
  • 13
  • 32
  • Hi Dean, it works great! As in all data transfers to the correct worksheets. However, because I have blank pieces of data for some reason only those blank ones copy into the "DateData" worksheet and nothing else (That's if I filter column G by date oldest to new, like you said) - If I don't filter, I don't get the correct dates copied over - not within and including the boundaries (start and end date) – Donald Sep 30 '19 at 16:24
  • Hi @Donald I am not sure what you mean by the above. Please upload a screenshot to your original post so I can visually see what you mean. – Dean Sep 30 '19 at 19:39
  • Hi, I have added pictures and explanation in question, I hope that makes it more clear. – Donald Sep 30 '19 at 22:42
  • @Donald please try run the above code again. I have added in two `Debug.Print` statements. Let me know what they print out to the immediate window. – Dean Oct 01 '19 at 05:00
  • And what are the dates you have entered in `No Entry` – Dean Oct 01 '19 at 05:40
  • And also, looking at your screenshot, some of your dates are stored in US and some in UK format. Make sure all are consistent and **sort** by Date (column G). – Dean Oct 01 '19 at 05:42
  • So when running the code again I still get the same output - no message or print statement. The dates I have entered start= 26/08/2019 and end = 01/10/2019. I have also ensured column G is only date format UK dd/mm/yyyy – Donald Oct 01 '19 at 08:31
  • Perfect. Now what is important is the fact that you are not getting a print statement. What does this mean? It means that the date variables (`dSDate` and `dEDate`) are being stored as the incorrect type because they are failing to match the values in your array. As such changing the storage types to `String` type should solve the issue. I have updated the code above. – Dean Oct 01 '19 at 08:37
  • It is also worth mentioning that as I have just edited I found a fundamental error. In the second loop I had failed to check for `aData(i,7) = sEDate`. That could have been causing the error too. Let me know what happens now after the above ammends. – Dean Oct 01 '19 at 08:39
  • Thanks bud for all your help, but I'm still getting the same output. I am not too sure why. – Donald Oct 01 '19 at 08:52
  • Okay, last attempt at debugging to get important information. Move the `Debug.Print` statements to the line before the `.Copy` and let me know what they print please. – Dean Oct 01 '19 at 08:54
  • Right @Donald I think I have found the problem. I was using the incorrect worksheet object for the `sSDate` and the `sEDate` variables, and I presume they were returning values from `"L15"` and `"L16"` on `DateData` and *not* `"No Entry"`. I have updated above. – Dean Oct 01 '19 at 08:57
  • Hmm, I have done that but no message printing - still same output. Confirming I put both debug prints just above : 'wsData.Range("A" & lRowStart, "Z" & lRowEnd).Copy' – Donald Oct 01 '19 at 08:59
  • code above I have received a error message: method range of object _worksheet failed.. for the line: wsData.Range("A" & lRowStart, "Z" & lRowEnd).Copy – Donald Oct 01 '19 at 09:02
  • You may have to change the date variables back to `Date` as the underlying issue was the incorrect worksheet object. – Dean Oct 01 '19 at 09:04
  • You receive that error because `lRowStart` and `lRowEnd` are 0 because it is failing to match the dates. – Dean Oct 01 '19 at 09:05
  • Dim sSDate As Date, sEDate As Date - Changed the variable back to date but still same error message which is quite odd – Donald Oct 01 '19 at 09:14
  • @Donald I have just tested the above and works as required. I have updated the code to what I have tested. Copy this code into your module and should be working bud. – Dean Oct 01 '19 at 09:46
  • No lad I don't understand why it isn't working - Clearly there is something on mine I haven't explained perhaps that's causing the error. The range of columns in date is from A-S1000 (prefer finite) - G is the date - I have some blank records and those blank records were the ones that was only copying over. I have ensured I have formatted dates by UK dd/mm/yyyy. Now I am getting that error still row on wsData.Range("A" & lRowStart, "Z" & lRowEnd).Copy – Donald Oct 01 '19 at 14:09
  • Thanks for trying bud, really appreciate it. – Donald Oct 01 '19 at 14:09
0

Consider avoiding the use of constant .Select and .Activate. Instead, manage processes with Set variables or in a With context. Additionally, the filter copy method needs to be handled differently namely on visible and non-blank cell results of filtered worksheet.

Dim StartDate As Date, EndDate As Date
Dim MainWorksheet As Worksheet, NewWorkSheet As Worksheet

StartDate = Sheets("NoEntry").Range("L15").Value
EndDate = Sheets("NoEntry").Range("L16").Value

Set MainWorksheet = Worksheets("Data")

With MainWorksheet
    ' SORT RANGE
    .Range("G1").CurrentRegion.Sort key1:=.Range("F1"), order1:=xlAscending, Header:=xlYes

    Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
    With .Range("$A:$G")
        ' SORT RANGE 
        .AutoFilter Field:=7, Criteria1:=">=" & StartDate, Operator:=xlAnd, _
                              Criteria2:="<=" & EndDate
        ' COPY VISIBLE AND NON-BLANK CELLS TO NEW WORKSHEET     
         Application.Intersect(.SpecialCells(xlCellTypeVisible), _
                               .SpecialCells(xlCellTypeConstants)).Copy _
                               Destination:=NewWorkSheet.Range("A1")
    End With        
    ' REMOVE FILTER
    .Cells.AutoFilter
End With

Sheets("NoEntry").Activate
Set MainWorksheet = Nothing: Set NewWorkSheet = Nothing
Parfait
  • 104,375
  • 17
  • 94
  • 125