Merging several workbook sheets into target worksheet - excel

Using MS-Excel 2007, I noticed that in this code, I noticed that when run the first row of the target is always empty. Why is that? Thanks.

Instead of
Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial
you can use something like that
Dim LastUsedCell As Range
Set LastUsedCell = Range("A" & Rows.Count).End(xlUp)
If IsEmpty(LastUsedCell) Then
LastUsedCell.PasteSpecial
Else
LastUsedCell.Offset(1, 0).PasteSpecial
End If
to start with row 1 on an empty sheet.

Please consider this option.
https://www.rondebruin.nl/win/addins/rdbmerge.htm
Post back if you have additional questions.

Related

Select and Copy Value Range Sheet1 and Special Paste Last Row Sheet2

The intent is to:
On Sheet(Master), update a Cell which triggers other cells to update a specific range.
On Sheet(Master), select updated range and copy that range.
On Sheet(Paste), paste the values and formatting of the copied data below the last row of data.
The script below functions properly, except for the paste special portion: PasteSpecial Paste:=xlPasteValues.
Private Sub CommandButton1_Click()
'/ I am trying to Add Data From Sheet("Master") To Sheet("Paste") as a "PasteSpecial Paste:=xlPasteValues"
Dim Lastrow As Long
Sheets("Master").Range("N3") = Sheets("Master").Range("N3") - Sheets("Master").Range("N4")
Lastrow = Sheets("Paste").Range("A65536").End(xlUp).Row + 1
Sheets("Master").Range("L13:AO17").Copy Destination:=Sheets("Paste").Range("A" & Lastrow)
End Sub
I have attempted to add the PasteSpecial Paste:=xlPasteValues portion as in the examples below:
Example One.
Lastrow = Sheets("Paste").Range("A65536").End(xlUp).Row.PasteSpecial Paste:=xlPasteValues
Example Two.
Sheets("Master").Range("L13:AO17").Copy Destination:=Sheets("Paste").Range("A" & Lastrow).PasteSpecial Paste:=xlPasteValues
Those are the only two types of options that I have attempted based on online research.
After reworking it a few times, the following solution worked.
Range("N3") = Range("N3") - Range("N4")
Range("L13:AO17").Copy
Sheets("Paste").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
I decided to step away from using the Lastrow var, when I realized that it was not needed. Once that was eliminated, I then focused on cleaning the script and used the offset function instead of row. This then allowed for me to add the PasteSpecial function properly.

VBA Selection.Copy copies a completely different range when running my code

I have spent the day trying to understand what is going on with my excel.. I am running some code which worked fine before, I modified part of it early up (but which still works fine), and now a Selection.Copy later on in the code has stopped working. Here it is :
Range("AE3").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
I used break points to find the problem. After the first two lines of code, it is the data in column AE which is selected. When I move on to the last line (Selection.Copy), it is not the data in AE which is selected but the columns AA and AB. I have tried literally everything I can think of to try and fix this but can't find anything..
If I run the code up to this point of the code and do the selection and copying manually, it also copies the wrong cells (it copies AA and AB like when it's done with vba)
I would post screenshots of it but you can't put photos here it seems.
Thanks for your help!
Resolved:
I went through the code step by step and noticed that previously in the code I copied the data from columns AA and AB to lower columns. To do so I had selected the columns and then copied them. I changed that so that I selected only the data in the columns and not the columns themselves and copied the data. This change has made my code work. I'm not sure why this was effecting the later Selection.Copy, but it was in some way. Thank you everyone for their help!
As I've suggested in my comment, avoid using .Select & Selection, is usually bad practice and almost everything can be done in VBA without the need to use them. I understand those are a result of the recorder (which is a good place to start learning how to do certain things in VBA), just need to learn as well how to use the code generated by the recorder.
See if this helps (see comments in code as well):
Sub copyRange()
Dim ws As Worksheet
Set ws = ActiveWorkbook.Sheets("Sheet1") 'use a variable for the sheet you want to use
Dim lRow As Long
lRow = ws.Cells(Rows.Count, "AE").End(xlUp).Row 'get the last row at the desired column
With ws
.Range("AE3:AE" & lRow).Copy _
Destination:=.Range("AE3:AE" & lRow).Offset(0, -10) 'destination offset 10 columns to the left
'or alternatively specify the destination
'Destination:=.Range("U3:U" & lRow)
End With
'ALTERNATIVE to the above - copy values only
With ws.Range("AE3:AE" & lRow)
.Offset(0, -10).Value = .Value 'destination offset 10 columns to the left
'or alternatively specify the destination
'ws.Range("U3:U" & lRow).Value = .Value
End With
'2nd ALTERNATIVE to the above - copy values only
With ws.Range(ws.Cells(3, 31), ws.Cells(lRow, 31))
.Offset(0, -10).Value = .Value 'destination offset 10 columns to the left
'or alternatively specify the destination
ws.Range(ws.Cells(3, 21), ws.Cells(lRow, 21)).Value = .Value
End With
End Sub
Note the use of With statement, .Range(...) is not the same as Range(...).
In case you want to copy all in column AE try this:
Range("EA3:EA" & Range("EA" & Rows.Count).End(xlUp).Row)).Copy
And to paste you could use:
Range("U3").PasteSpecial (xlPasteValues)
Also, I strongly suggest you to read:
How to avoid using Select in Excel VBA
You could try:
Option Explicit
Sub test()
Dim LastRow As Long
'Create a with statement refer to the sheet where your data are
With ThisWorkbook.Worksheets("Sheet1")
'Find the LastRow of column AE
LastRow = .Cells(.Rows.Count, "AE").End(xlUp).Row
'Refer to the range starting from AE3 and ends at Lastrow
.Range("AE3" & ":AE" & LastRow).Copy
End With
End Sub
Results:

VBA copy paste range every 7th row, 7 times

Good afternoon,
After too many hours of researching the proper code for what I am trying to do, I am finally having to ask the experts here. I am terribly new to VBA (but now hooked on conquering it!).
I am trying to copy a range of 3 cells of data I enter daily (I enter the data into columns J:L), then paste it 7 times, every 7th row below (so, I am copy/pasting Monday data to the next 7 Mondays, in their respective rows below). Each day changes, and so will the paste location (Tuesday data will be copied, then pasted to the next 7 Tuesday rows below, etc.). The data I enter will always be columns J:L.
Then, once the data is pasted, I have a button in place that uses that data, and clears it. So, columns J:L are always clear, until I add the data to the next row of 3 cells.
Any help is appreciated, as I am simply stumped. I tried several variations of "lastrow", but haven't found the proper coding that works for me (from piecing together info from here, but failing to make it work).
I tried to add a snapshot here, but apparently, I'm too noob for that even :/
The idea seems simple, so hopefully there will be a simple solution.
Thank you for your awesomeness!
Edited (sorry for making my first run at this site so difficult :/ )
Sub CopyPaste()
'
' CopyPaste Macro
' copies and pastes range for 8 total weeks
'
Dim lastrow As Long
lastrow = Range("J" & Rows.Count).End(xlUp).Row
'
Selection.Copy
Range("J27").Select
ActiveSheet.Paste
Range("J34").Select
ActiveSheet.Paste
Range("J41").Select
ActiveSheet.Paste
Range("J48").Select
ActiveSheet.Paste
Range("J55").Select
ActiveSheet.Paste
Range("J62").Select
ActiveSheet.Paste
Range("J69").Select
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub
See if this helps. I foresee a problem though in that once you have copied values down the worksheet for say Monday, the last used row will be row 70 or something like that.
Sub x()
Dim i As Long, lastrow As Long
lastrow = Range("J" & Rows.Count).End(xlUp).Row
For i = 1 To 7
Cells(lastrow, "J").Resize(, 3).Offset(7 * i).Value = Cells(lastrow, "J").Resize(, 3).Value
Next i
End Sub

ActiveSheet.Paste gives error...but only sometimes? Alternative to it's use?

I recorded a macro, it filters a sheet, copies the filtered data and pastes it into another workbook. It worked the first few times I used it, now it gives me an error:
Run-time 1004 - We can't Paste because the Copy area and Paste area
aren't the same size.
Nothing changed, it just now flags the error on the "ActiveSheet.Paste" line. Can anyone explain why it does this out of nowhere randomly? I know tomorrow when I try again it will work fine for a few uses then do this again. I looked online it seems to be a common issue, I haven't found a solution that has worked for me yet, does anyone have an idea? Or is there another way to do this maybe so I can just avoid it?
The code:
Sub Macro201()
ActiveSheet.Range("$A$6:$H$55").AutoFilter Field:=8, Criteria1:="99"
Range("A7:B7").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Windows("invoiceTEST.xls").Activate
Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveSheet.Paste
Range("C" & Rows.Count).End(xlUp).Offset(1).Select
End Sub
First of all, you don't need to select anything. For example, Range("A7:B7") is a range. Selection is also a range (in this context). So, you assign the range to a Selection.Range and then use the Selection.Range. Why not use the Range you defined at the outset?
Next, you do have to specify the Worksheet you are working on, especially the one in the target workbook.
Finally, you must clearly identify the last rows you use. Your formula picks the last row in the sheets you work with, not the last used row. So you are throwing around millions of blank cells.
Put all of the above together and you arrive a code like the following.
Sub CopyData()
' 01 May 2017
Dim Rng As Range
With ActiveSheet
Set Rng = .Range("$A$6:$H$55")
Rng.AutoFilter Field:=8, Criteria1:="99"
If Application.WorksheetFunction.Subtotal(3, Rng) = 0 Then Exit Sub
.Range("A7:B" & .Cells(.Rows.Count, "A").End(xlUp).Row).Copy
End With
With Workbooks("invoiceTEST.xls").Sheets(1)
.Cells(.Rows.Count, "A").End(xlUp).Offset(1).PasteSpecial
End With
End Sub
Note that the code will fail if the target workbook isn't open when you attempt to run it.

Excel resetting "UsedRange"

Don't know what I'm missing, but the examples I see posted do not appear to work.
I import data from a web query. I set the query to clear unused cells when it re-queries.
I used this imported data to generate a report of variable length.
However if the user (as they need to do in my case) insert rows then the ActiveSheet.UsedRange is expanded. This means I cannot any longer just do a "Ctrl-End" to find the last row in the data set when a new query is performed.
I can easily clear any data with ActiveSheet.UsedRange.Clear. However if the previous query generated a 2 or 3 page report any subsequent query will also be that long even when there is less data because the "UsedRange" still points to that last row way down there.
The examples shown like
ActiveSheet.UsedRange
ActiveSheet.UsedRange.Clear
a = ActiveSheet.UsedRange.Rows.Count
do not reset the range.
MS defines UsedRange as a readOnly property.
It appears what needs to happen is a "File Save" in order to complete the action.
ActiveWorkbook.Save
One post noted that in older versions of Excel you also had to close the workbook and reopen it to complete the action.
I would like to know
1. What is the version cutoff where this behavior changed?
2. Is there some other method using a VBA macro which will reset the range?
I only needed to use Worksheets("Sheet1").UsedRange.Calculate
after deleting rows to reset the range.
Best code that worked for me:
Sub DeleteUnused()
Dim myLastRow As Long
Dim myLastCol As Long
Dim dummyRng As Range
Dim AnyMerged As Variant
'http://www.contextures.on.ca/xlfaqApp.html#Unused
'Helps to reset the usedrange by deleting rows and columns AFTER your true used range
'Check for merged cells
AnyMerged = ActiveSheet.UsedRange.MergeCells
If AnyMerged = True Or IsNull(AnyMerged) Then
MsgBox "There are merged cells on this sheet." & vbCrLf & _
"The macro will not work with merged cells.", vbOKOnly + vbCritical, "Macro will be Stopped"
Exit Sub
End If
With ActiveSheet
myLastRow = 0
myLastCol = 0
Set dummyRng = .UsedRange
On Error Resume Next
myLastRow = _
.Cells.Find("*", after:=.Cells(1), _
LookIn:=xlFormulas, lookat:=xlWhole, _
searchdirection:=xlPrevious, _
searchorder:=xlByRows).Row
myLastCol = _
.Cells.Find("*", after:=.Cells(1), _
LookIn:=xlFormulas, lookat:=xlWhole, _
searchdirection:=xlPrevious, _
searchorder:=xlByColumns).Column
On Error GoTo 0
If myLastRow * myLastCol = 0 Then
.Columns.Delete
Else
.Range(.Cells(myLastRow + 1, 1), _
.Cells(.Rows.Count, 1)).EntireRow.Delete
.Range(.Cells(1, myLastCol + 1), _
.Cells(1, .Columns.Count)).EntireColumn.Delete
End If
End With
End Sub
I've used Jeeped solution and worked for me when i add .Activate, so:
With Worksheets("Sheet1")
Debug.Print .UsedRange.Address(0, 0)
.UsedRange.Clear
.UsedRange
.Activate
Debug.Print .UsedRange.Address(0, 0)
End With
I'm using Excel2013
select cell 1,1 in any sheets you want to reset the UsedRange property
Calculate all worksheets in all open workbooks,
regardless of whether they changed since last calculation
(To Calculate Fully Ctrl+Alt+F9)
Save the workbook
Works for me on all versions of excel
This is what ended up working for me. I feel there has to be a better way but no others worked for me.
Sub ClearRangeData()
Dim S1 As Worksheet
Set S1 = Sheets("Your Sheet Name") 'Define what sheets we are using
'------- Remove all the old data -----
S1.Activate
With ActiveSheet
S1_rows = S1.UsedRange.Rows.Count
For I = S1_rows To 1 Step -1
Cells(I, 1).EntireRow.Delete
Next
End With
End Sub
If you call the Worksheet.UsedRange property by itself, it will reset.
With Worksheets("Sheet1")
Debug.Print .UsedRange.Address(0, 0)
.UsedRange.Clear
.UsedRange '<~~ called by itself will reset it
Debug.Print .UsedRange.Address(0, 0)
End With
This extra step is unnecessary in xl2010 and above with all appropriate service packs installed.
Here is how I inserted your code.
Sheets("Edit Data").Select
' Range("A6").Select
' Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select
' Selection.Delete Shift:=xlUp
' ActiveWorkbook.Save
With Worksheets("Edit Data")
Debug.Print .UsedRange.Address(0, 0)
.UsedRange.Clear
.UsedRange '<~~ called by itself will reset it
Debug.Print .UsedRange.Address(0, 0)
End With
Here is the full used range with data
Here is the used range after your code executed
The end of range should be i7 instead it is still i26
However the code which I commented out does reset range to i7
From what you are saying just to confirm. My commented out code will only work for Excel 2010 and newer. We have some 2007 versions hanging around. For those the workbook will actually have to be closed and reopened for the range to reset?
Note- the code examples were executed on version 2016
This may or may not suit your data needs, but if your data is all in one contiguous block, you can use CurrentRegion instead of UsedRange, like this:
With Cells(1, 1).CurrentRegion
MsgBox "I have " & .Rows.Count & " rows and " & .Columns.Count & " columns of data."
End With
Of course, if the region you care about does not start at cell A1, or if your sheet contains multiple contiguous regions that you care about, this option will not work. Depending on how predictable your data is, you can usually find at least one cell in each block of data, and once you have that, CurrentRegion will give you the range of the entire block.
Thanks to Claus for having the correct answer, but it is incomplete, and he completed it with a comment on the main post. I'll answer here to combine the useful bits into a single working solution.
Note: I have not tried variations to see which steps are necessary, but these steps work to clear unnecessary used range.
Sub ResetUsedRange()
dim rngToDelete as range
set rngToDelete = 'Whatever you want
rngToDelete.EntireRow.Clear
rngToDelete.EntireRow.Select
Selection.Delete Shift:=xlUp
ActiveWorkbook.Save 'This step has been stated to be necessary for the range to reset.
End Sub
This is the solution I used.
Sub CorrectUsedRange()
Dim values
Dim usedRangeAddress As String
Dim r As Range
'Get UsedRange Address prior to deleting Range
usedRangeAddress = ActiveSheet.UsedRange.Address
'Store values of cells to array.
values = ActiveSheet.UsedRange
'Delete all cells in the sheet
ActiveSheet.Cells.Delete
'Restore values to their initial locations
Range(usedRangeAddress) = values
End Sub
My Excel VBA program imports data from access database by a given date range.
Whenever a new set of data is populated, the worksheet UsedRange does not shrink to reflect only rows with data but instead stays the same even when there are blank rows after the last row with data.
This creates difficulty scrolling down the worksheet to view data.
So to reset UsedRange in order to just reflect rows with data, see below code.
I hope it helps someone.
Sub ResetUsedRange(ByVal oSht As Excel.Worksheet)
' ________________________________________________________________
' Resetting UsedRange to reset vertical scroll bar on Worksheet,
' to reflect ONLY rows with data. This can reset UsedRange on any
' Worksheet. Just pass the worksheet object to this sub.
' ================================================================
Dim iRow1 As Long ' This will get the last row with data
Dim iRow2 As Long ' This will get the number of rows in UsedRange
With oSht
' Format cells to remove wrap text option
' Importing from Access makes some cells with wrap text
.UsedRange.Cells.WrapText = False
' Find last row with data on worksheet
iRow1 = .Cells(.Rows.count, 1).End(xlUp).Row
' Get number of rows in UsedRange
iRow2 = .UsedRange.Rows.count
' If UsedRange rows exceeds the last row with data
' then delete the rows which obviously are blank
If iRow2 > iRow1 Then
.Range(.Cells(iRow1 + 1, 1), .Cells(iRow2, 1)).EntireRow.Delete
End If
' following code forces UsedRange to recalculate and resets
' to reflect ONLY rows with data if blank rows in the UsedRange
' were deleted making the vertical scroll bar to reset itself.
.UsedRange.Calculate
End With
End Sub
I just wanted to put my 2 cents in here since I was also having this problem until I realized the problem.
If you have a UsedRange that is A1:H20 and you delete the row by saying ActiveSheet.Range("A2:H2).Delete you'll find that your UsedRange hasn't updated, it will still show A1:H20. However, if you either say ActiveSheet.Rows(2).Delete or ActiveSheet.Range("A2:H2).EntireRow.Delete You'll find that the UsedRange does update. For some reason you have to delete entire rows or columns (depending your condition) to get that UsedRange to update.
Hope this helps someone!
This worked for me:
Worksheets("Sheet1").UsedRange.Clear
Worksheets("Sheet1").UsedRange = ""
It appears that inserting a value into the UsedRange resets it. After this action I can go
MyCurrentRow = Worksheets("Sheet1").Range("A:A").SpecialCells(xlCellTypeLastCell).Row
MyCurrentRow comes now back as 1, and I can just count from there. When I did not assign a value into UsedRange, that LastCell value did not reset. No Save required.
This works for me in Excel 2010:
Worksheets("Sheet1").UsedRange.Clear
Worksheets("Sheet1").UsedRange.Calculate
I double checked to make sure all the latests patches and service packs have been installed and they were.
I'm running
Windows 10 and
Excel 2016 version 16.0.6568.2034
I found that the range would only reset with the
ActiveSheet.UsedRange.Clear
And most importantly
ActiveWorkbook.Save
without the save command the range is not reset

Resources