Simple loop does not paste ranges correctly - excel

I have a simple loop that should copy ranges form three sheets and stack them on top of each other in another sheet. I define the ranges of each of the three sheets via a cell that counts rows in the Control Sheet.
I do not get an error message, however only the range of the first sheets gets pasted. I troubleshooted already to see if the loop is running until end and indeed it does. I cannot wrap my head around why only the range from the first sheets gets pasted in the final sheet.
Sub Loop()
Dim ws_Sheet As Worksheet, ws As Worksheet
Dim lng_LastRow As Long, lng_LastColumn As Long, lng_LastRowSheet As Long
Dim rng_WorkRange As Range
Dim arrSht, i
Dim counter As Integer
arrSht = Array("a", "b", "c")
Set ws_Sheet = Worksheets("d")
ws_Sheet.Cells.ClearContents
counter = 1
For i = 0 To 2
Set ws = Worksheets(arrSht(i))
lng_LastRow = Worksheets("Control").Range("E" & counter).Value + 1
lng_LastColumn = ws.Cells(1, Columns.Count).End(xlToLeft).Column
lng_LastRowSheet = ws_Sheet.Cells(Rows.Count, 1).End(xlUp).Row
Set rng_WorkRange = ws.Range(ws.Cells(1, 1), ws.Cells(lng_LastRow, lng_LastColumn))
rng_WorkRange.Copy ws_Sheet.Range("A" & lng_LastRowSheet)
counter = counter + 1
Next i
End Sub

The issue is
lng_LastRowSheet = ws_Sheet.Cells(Rows.Count, 1).End(xlUp).Row
is the last used row (the last row that has data).
And then you use that to start pasting
rng_WorkRange.Copy ws_Sheet.Range("A" & lng_LastRowSheet)
so you overwrite the last row of data!
The next free row is lng_LastRowSheet + 1 so you should paste there:
rng_WorkRange.Copy ws_Sheet.Range("A" & (lng_LastRowSheet + 1))
You can also see that in the debug data:
a $A$1:$B$338 to A1
b $A$1:$B$91 to A338
c $A$1:$B$356 to A428
a goes from A1:B338 but you start pasting b in A338 so it overwrites the last row of a.
I gave it a test:
Created worksheet Control with data like
Then created worksheets a, b and c like
with data until row 500 so there is enough.
Then created an empty worksheet d for the output.
And used the following code. Note I have optimized it so it uses meaningful variable names, which is much easier to read, understand and debug.
Option Explicit
Public Sub CopyData()
Dim SheetNames() As Variant
SheetNames = Array("a", "b", "c")
Dim wsDestination As Worksheet
Set wsDestination = ThisWorkbook.Worksheets("d")
wsDestination.Cells.ClearContents
Dim i As Long
For i = 0 To 2
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.Worksheets(SheetNames(i))
Dim SourceLastRow As Long
SourceLastRow = ThisWorkbook.Worksheets("Control").Range("E" & i + 1).Value + 1
Dim SourceLastColumn As Long
SourceLastColumn = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
Dim DestinationFreeRow As Long
DestinationFreeRow = wsDestination.Cells(wsDestination.Rows.Count, 1).End(xlUp).Row + 1 ' Last used row +1
Dim SourceRange As Range
Set SourceRange = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(SourceLastRow, SourceLastColumn))
SourceRange.Copy wsDestination.Range("A" & DestinationFreeRow)
Next i
End Sub
And I get a perfect output like:
Note that in the output I have hidden some rows so you can see eveything is there. This code perfectly does what it is supposed to.

Stack Ranges (Vertically) From Multiple Worksheets
Sub StackRanges()
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Source
Dim sWorksheetNames() As Variant: sWorksheetNames = VBA.Array("a", "b", "c")
' Lookup (Source Last Row)?
Dim lws As Worksheet: Set lws = wb.Worksheets("Control")
Dim llrCell As Range: Set llrCell = lws.Range("E1")
' Destination
Dim dws As Worksheet: Set dws = wb.Worksheets("d")
dws.UsedRange.ClearContents
Dim dfCell As Range: Set dfCell = dws.Range("A1")
Dim sws As Worksheet
Dim srg As Range
Dim slRow As Long
Dim slColumn As Long
Dim i As Long
' Loop.
For i = 0 To UBound(sWorksheetNames)
Set sws = wb.Worksheets(sWorksheetNames(i))
slRow = llrCell.Value + 1
slColumn = sws.Cells(1, sws.Columns.Count).End(xlToLeft).Column
Set srg = sws.Range("A1", sws.Cells(slRow, slColumn))
srg.Copy dfCell
' If you only need to copy values (since you're using '.ClearContents'),
' instead, use the most efficient:
'dfCell.Resize(srg.Rows.Count, srg.Columns.Count).Value = srg.Value
Set llrCell = llrCell.Offset(1) ' next source last row lookup cell
Set dfCell = dfCell.Offset(srg.Rows.Count) ' next first dest. cell
Next i
End Sub

The counter and the lng_lastRow variable is too messy.
I repaleced some code as follow:
Sub newLoop()
Dim ws_Sheet As Worksheet, ws As Worksheet
Dim lng_LastRow As Long, lng_LastColumn As Long, lng_LastRowSheet As Long
Dim rng_WorkRange As Range, rng_lastRange As Range
Dim arrSht, i
Dim counter As Integer
arrSht = Array("a", "b", "c")
Set ws_Sheet = Worksheets("Control")
ws_Sheet.Cells.ClearContents
For i = 0 To 2
Set ws = Worksheets(arrSht(i))
Set rng_lastRange = ws_Sheet.Cells(Rows.Count, 1).End(xlUp)
lng_LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lng_LastColumn = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set rng_WorkRange = ws.Range(ws.Cells(1, 1), ws.Cells(lng_LastRow, lng_LastColumn))
rng_WorkRange.Copy rng_lastRange.Offset(1, 0)
Next i
End Sub

Related

Copy every second value of a row and paste into a column in another sheet

pls help, I need a excel vba code, which copies every second value of a row
and paste that into a column in another sheet
.
I tried it like this
Sub Test()
Worksheets("Sheet1").Activate
Dim x As Integer
For x = 5 To 196 Step 2
Worksheets("Tabelle1").Activate
Cells(x, 2).Value = Sheets("Sheets1").Range("E2:GN2")
Next x
End Sub
Sub test()
Dim WkSource As Worksheet
Dim WkDestiny As Worksheet
Dim i As Long
Dim j As Long
Dim LR As Long
Dim k As Long
Set WkSource = ThisWorkbook.Worksheets("Hoja1")
Set WkDestiny = ThisWorkbook.Worksheets("Hoja2")
With WkSource
LR = .Range("E" & .Rows.Count).End(xlUp).Row
k = 2 'starting row where you want to paste data in destiny sheet
For i = 2 To LR Step 1
For j = 5 To 12 Step 2 'j=5 to 12 because my data goes from column E to L (5 to 12)
WkDestiny.Range("D" & k).Value = .Cells(i, j).Value
k = k + 1
Next j
Next i
End With
Set WkSource = Nothing
Set WkDestiny = Nothing
End Sub
The code loop trough each row and each column (notice step 2 to skip columns)
Output I get:
you can start from something like this:
Option Explicit
Private Sub dataCp()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = wb.Sheets("Tabelle1")
Dim lrow As Long, lcol As Long, i As Long
Dim rng As Range, c As Range
lcol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
For i = 5 To lcol
lrow = (ws2.Cells(ws2.Rows.Count, "D").End(xlUp).Row) + 1
ws2.Range("D" & lrow).Value = ws.Cells(2, i).Value
i = i + 1
Next
End Sub
Transpose Data
It will transpose all rows of a range in a worksheet to consecutive columns on another worksheet.
Since scStep is 2, in this case, only every other cell in each source row will be copied.
Adjust (play with) the values in the constants section.
Option Explicit
Sub TransposeData()
' Source
Const sName As String = "Sheet1"
Const sFirstRowAddress As String = "E2:GN2"
Const scStep As Long = 2
' Destination
Const dName As String = "Tabelle1"
Const dFirstCellAddress As String = "D2"
' Both
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Write the values from the source range to the source array.
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sData As Variant
Dim srCount As Long
With sws.Range(sFirstRowAddress)
' Populate data.
' With .Resize(20)
' .Formula = "=RANDBETWEEN(1,100)"
' .Value = .Value
' End With
Dim lCell As Range: Set lCell = .Resize(sws.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Sub ' no data in data range
srCount = lCell.Row - .Row + 1
sData = .Resize(srCount).Value
End With
' Define the destination array.
Dim scCount As Long: scCount = UBound(sData, 2)
Dim drCount As Long
drCount = Int(scCount / scStep) - CLng(scCount Mod scStep > 0)
Dim dData As Variant: ReDim dData(1 To drCount, 1 To srCount)
' Write the data from the source array to the destination array.
Dim r As Long, c As Long
For c = 1 To srCount
For r = 1 To drCount
dData(r, c) = sData(c, (r - 1) * scStep + 1)
Next r
Next c
' Write the values from the destination array to the destination range.
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
With dws.Range(dFirstCellAddress).Resize(, srCount) ' first row range
' Write data.
.Resize(drCount).Value = dData
' Clear below.
.Resize(dws.Rows.Count - .Row - drCount + 1).Offset(drCount).Clear
' Apply some formatting.
'.EntireColumn.AutoFit
End With
' Inform.
MsgBox "Data transposed.", vbInformation
End Sub

How to paste the data in a range where the starting row and column of the range is defined in a cell?

I have two sheets in my excel file:
Input Sheet: Sheet1
Target Sheet: Sheet2
What I want to achieve is to paste the value start from the column that I defined in cell C5 and also start from the row that I defined in cell C6. If the range defined by cell C5 and C6 already have data, then it will find the next empty row based on the column in cell C5 and paste the data in that empty row.
For example in the screenshot above, the starting column & row defined in cell C5 & C6 is B8, so the copied value will be pasted starting from cell B8 until E8. However, if the row already have data, then it will find the next empty row based on column B (which is B9) and paste it there.
I'm not sure how to modified my current script:
Public Sub CopyData()
Dim InputSheet As Worksheet ' set data input sheet
Set InputSheet = ThisWorkbook.Worksheets("Sheet1")
Dim InputRange As Range ' define input range
Set InputRange = InputSheet.Range("G6:J106")
Dim TargetSheet As Worksheet
Set TargetSheet = ThisWorkbook.Worksheets("Sheet2")
Const TargetStartCol As Long = 2 ' start pasting in this column in target sheet
Const PrimaryKeyCol As Long = 1 ' this is the unique primary key in the input range (means first column of B6:G6 is primary key)
Dim InsertRow As Long
InsertRow = TargetSheet.Cells(TargetSheet.Rows.Count, TargetStartCol + PrimaryKeyCol - 1).End(xlUp).Row + 1
' copy values to target row
TargetSheet.Cells(InsertRow, TargetStartCol).Resize(ColumnSize:=InputRange.Columns.Count).Value = InputRange.Value
End Sub
Any help or advice will be greatly appreciated!
Testing Scenario 1
Output of Testing Scenario 1
Please, try the next code:
Public Sub CopyData_()
Dim InputSheet As Worksheet: Set InputSheet = ThisWorkbook.Worksheets("Sheet1")
Dim InputRange As Range: Set InputRange = InputSheet.Range("G6:J106")
Dim arr: arr = InputRange.Value
Dim TargetSheet As Worksheet: Set TargetSheet = ThisWorkbook.Worksheets("Sheet2")
Dim TargetStartCol As String, PrimaryKeyRow As Long
TargetStartCol = TargetSheet.Range("C5").Value ' start pasting in this column in target sheet
PrimaryKeyRow = TargetSheet.Range("C6").Value ' this is the row after the result to be copied
Dim InsertRow As Long
InsertRow = TargetSheet.cells(TargetSheet.rows.Count, TargetStartCol).End(xlUp).row + 1
If InsertRow < PrimaryKeyRow Then InsertRow = PrimaryKeyRow + 1 'in case of no entry after PrimaryKeyRow (neither the label you show: "Row")
' copy values to target row
TargetSheet.cells(InsertRow, TargetStartCol).Resize(UBound(arr), UBound(arr, 2)).Value = arr
End Sub
Not tested, but if should work, I think. If something not clear or going wrong, please do not hesitate to mention the error, what it does/doesn't against you need or anything else, necessary to correct it.
Copy Data to Another Worksheet
Option Explicit
Sub CopyData()
Const sName As String = "Sheet1"
Const rgAddress As String = "G6:J106"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(sName)
Dim rg As Range: Set rg = ws.Range(rgAddress)
WriteCopyData rg
' or just:
'WriteCopyData ThisWorkbook.Worksheets("Sheet1").Range("G6:J106")
End Sub
Sub WriteCopyData(ByVal SourceRange As Range)
Const dName As String = "Sheet2"
Const dRowAddress As String = "C6"
Const dColumnAddress As String = "C5"
Dim rCount As Long: rCount = SourceRange.Rows.Count
Dim cCount As Long: cCount = SourceRange.Columns.Count
Dim dws As Worksheet
Set dws = SourceRange.Worksheet.Parent.Worksheets(dName)
Dim dRow As Long: dRow = dws.Range(dRowAddress).Value
Dim dCol As String: dCol = dws.Range(dColumnAddress).Value
Dim dfrrg As Range: Set dfrrg = dws.Cells(dRow, dCol).Resize(1, cCount)
Dim dlCell As Range
Set dlCell = dfrrg.Resize(dws.Rows.Count - dRow + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If Not dlCell Is Nothing Then
Set dfrrg = dfrrg.Offset(dlCell.Row - dRow + 1)
End If
Dim drg As Range: Set drg = dfrrg.Resize(rCount)
drg.Value = SourceRange.Value
End Sub

How do you paste filtered values only in the cells that were affected by such filter using vba?

I'm currently working on a Macro that its currently filtering a table based on a value and then it copies the data under a column after the filters have been applied (got that to work). However, I can't figure out how to paste those values in the same table overwriting the data under the visible cells within a different column. Values highlighted in red (picture) are being copied, now I need to paste them over only in the cells highlighted yellow. Thank you!
Public Sub DxcDateUpdate()
Application.ScreenUpdating = False
Dim Mwb As Workbook
Dim ws As Worksheet
Set Mwb = ThisWorkbook
Set ws = Mwb.Worksheets("Commission")
Set ws2 = Mwb.Worksheets("test")
lr = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ws.Range("A1").AutoFilter Field:=31, Criteria1:="DXC/TPV.com Enrollment"
ws.Range("AG2:AG" & lr).SpecialCells(xlCellTypeVisible).Copy Destination:=ws.Range '''here is where idk what to do?'''
Application.ScreenUpdating = True
End Sub
You cannot paste a discontinuous range as discontinuous. You should iterate between each range cell and copy it using offset, or building the range to Paste using c.row. Please, try the next adapted code:
Sub DxcDateUpdate()
Dim Mwb As Workbook, ws As Worksheet, rngVis As Range, c As Range, LR As Long
Set Mwb = ThisWorkbook
Set ws = Mwb.Worksheets("Commission")
Set ws2 = Mwb.Worksheets("test")
LR = ws.cells(ws.rows.Count, 1).End(xlUp).row
ws.Range("A1").AutoFilter field:=31, Criteria1:="DXC/TPV.com Enrollment"
Set rngVis = ws.Range("AG2:AG" & LR).SpecialCells(xlCellTypeVisible)
For Each c In rngVis.cells
c.Offset(0, -28).value = c.value
Next
End Sub
In order to make the code faster, of course, you should use some optimization lines (ScreenUpdating = False, EnableEvents = False, Calculation = xlCalculationManual, followed after by True, True, xlCalculationAutomatic).
Copy 'Filtered' Values Using Arrays
The following will loop through the criteria column to find the criteria (string). When found, in the same row, the value from the source column will be copied to the destination column.
The columns' values are written to arrays to speed up the process (the loop).
Option Explicit
Sub DxcDateUpdate()
Const wsName As String = "Commission"
Const fRow As Long = 2
Const cCol As String = "AE" ' Criteria
Const sCol As String = "AG" ' Source
Const dCol As String = "E" ' Destination
Const Criteria As String = "DXC/TPV.com Enrollment"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim rg As Range: Set rg = ws.Range("A1").CurrentRegion
Dim lRow As Long: lRow = rg.Rows.Count
Dim cData As Variant: cData = rg.Columns(cCol).Value
Dim sData As Variant: sData = rg.Columns(sCol).Value
With rg.Columns(dCol)
Dim dData As Variant: dData = .Value
Dim r As Long
For r = fRow To lRow
If cData(r, 1) = Criteria Then
dData(r, 1) = sData(r, 1)
End If
Next r
.Value = dData
End With
End Sub

How to copy one row of data at a time from one sheet and paste into another sheet

I want to copy one row of data at a time from one sheet and pasting into another sheet. I need to repeat this 100 times. I also need to modify a couple of column values after pasting them.
My data is not pasting into new sheet correctly.
'Get column numbers which need to be modified
PolicyReference = DataWS.Range("A1", DataWS.Range("IV1").End(xlToLeft)).Find("PolicyReference").Column
InsuredCode = DataWS.Range("A1", DataWS.Range("IV1").End(xlToLeft)).Find("InsuredCode").Column
InsuredDescription = DataWS.Range("A1", DataWS.Range("IV1").End(xlToLeft)).Find("InsuredDescription").Column
For j = 1 To 100
'Worksheets(DataWS).Range("A1:A100").Copy Worksheets(DestinationWS).Range("A1")
'1. Find last used row in the copy range based on data in column A
CopyLastRow = DataWS.Cells(DataWS.Rows.count, "A").End(xlUp).Row
'2. Find first blank row in the destination range based on data in column A
DestLastRow = DestinationWS.Cells(DestinationWS.Rows.count, "A").End(xlUp).Offset(1).Row
'3. Copy & Paste Data
DataWS.Rows(j).EntireRow.Copy DestinationWS.Range("A" & DestLastRow)
DataWS.Range("A1:A100").Copy
DestinationWS.Range("A" & Rows.count).End(xlUp).Offset(2).PasteSpecial Paste:=xlPasteValues
Next j
This code will copy all but the first row from DataWs to DestinationWs. If you want to be more selective in what you copy modifications must be made to the code in the loop, at the bottom.
Private Sub Study()
' 244
Dim DataWs As Worksheet
Dim DestinationWs As Worksheet
Dim PolicyReference As Long
Dim InsuredCode As Long
Dim InsuredDescription As Long
Dim Fnd As Range
Dim CopyLastRow As Long
Dim DestLastRow As Long
Dim R As Long ' loop counter: rows
Set DataWs = Worksheets("Sheet1")
Set DestinationWs = Worksheets("Sheet2")
With DestinationWs
DestLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
'Get column numbers which need to be modified
With DataWs
Set Fnd = .Rows(1).Find("PolicyReference") ' spaces between words are permissible
' make sure the column is found before using it in your further code
If Fnd Is Nothing Then Exit Sub
PolicyReference = Fnd.Column
Set Fnd = .Rows(1).Find("InsuredCode")
If Fnd Is Nothing Then Exit Sub ' perhaps give a message before exiting
InsuredCode = Fnd.Column
Set Fnd = .Rows(1).Find("InsuredDescription")
If Fnd Is Nothing Then Exit Sub ' perhaps give a message before exiting
InsuredDescription = Fnd.Column
CopyLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False ' speeds up execution
For R = 2 To CopyLastRow ' start in row 2
DestLastRow = DestLastRow + 1
.Rows(R).Copy DestinationWs.Cells(DestLastRow, "A")
Next R
Application.ScreenUpdating = True
End With
End Sub
Columns and Ranges
I am considering these as two problems. Revealing the connection between them might lead to a more suitable solution.
The first part (including the function) illustrates how you can write the column numbers to an array which can later be used to process the data in those columns.
The second part illustrates how to copy values most efficiently. The loop is ignored.
Option Explicit
Sub ColumnsAndRanges()
Const sName As String = "Sheet1"
Const shRow As Long = 1
Const sHeadersList As String _
= "PolicyReference,InsuredCode,InsuredDescription"
Const sFirst As String = "A1"
Const dName As String = "Sheet2"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
'Part 1: Column Numbers
Dim shrg As Range: Set shrg = sws.Rows(shRow)
' Use the function 'getColumnNumbers'.
Dim sColNums As Variant: sColNums = getColumnNumbers(shrg, sHeadersList)
If IsEmpty(sColNums) Then
MsgBox "Could not find all the headers."
Exit Sub
End If
' Column Numbers Example:
Dim n As Long
For n = 1 To UBound(sColNums)
Debug.Print n, sColNums(n)
Next n
'Part 2: Copy Range Values
' Create a reference to the Source Range.
Dim slCell As Range ' Source Last Cell
Set slCell = sws.Cells(sws.Rows.Count, "A").End(xlUp)
Dim srg As Range
' Note how a cell address (sFirst) or a cell range (slCell) can be used.
Set srg = sws.Range(sFirst, slCell).EntireRow
' Create a reference to the Destination Range.
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range ' Destination First Cell
' When 'EntireRow' is used, only "A" or 1 can be used.
Set dfCell = dws.Cells(dws.Rows.Count, "A").End(xlUp).Offset(1)
Dim drg As Range: Set drg = dfCell.Resize(srg.Rows.Count, srg.Columns.Count)
' Copy by assignment (most efficient when only values are to be copied).
drg.Value = srg.Value
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the column numbers in a one-based array.
' Remarks: The column numbers refer to the columns of the given range,
' not necessarily to the columns of the worksheet.
' If any of the headers cannot be found, 'Empty' is returned.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function getColumnNumbers( _
ByVal RowRange As Range, _
ByVal HeadersList As String, _
Optional ByVal Delimiter As String = ",") _
As Variant
If RowRange Is Nothing Then Exit Function
If Len(HeadersList) = 0 Then Exit Function
Dim Headers() As String: Headers = Split(HeadersList, Delimiter)
Dim ColNums As Variant
ColNums = Application.Match(Headers, RowRange.Rows(1), 0)
If Application.Count(ColNums) = UBound(Headers) + 1 Then
getColumnNumbers = ColNums
End If
End Function
The following one line of code using AdvancedFilter will paste data to the destination sheet.
Sub CopyDataToAnotherSheet()
DataWS.Range("A1").CurrentRegion.AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=DataWS.Range("A1", _
DataWS.Cells(1, DataWS.Columns.Count).End(xlToLeft)), _
CopyToRange:=DestinationWS.Range("A1")
End Sub

Delete old data in table after copy and paste macro

I have developed a working macro in VBA that automatically opens a workbook and then copies the data and pastes it on a table in the workbook I am working on. I perform this task monthly.
The data set varies in rows every month but does not vary in columns.
I am running into issues when the data set in less rows than the previous month and I am forced to manually delete lines that remained in the table because the previous month had more rows.
I was hoping to add to my existing code to automatically delete the old data after pasting the new data.
I perform a manual keystroke of selecting the last row of new data and move down one cell in column A then do a Ctrl+Shift+Down+Right to grab the data and select delete. So essentially that is the task I am trying to replace.
Thanks.
Sub Import_File()
Dim wbSourceData As Workbook
Dim wbDestination As Workbook
Dim wsSourceData As Worksheet
Dim wsDestination As Worksheet
Dim strFName As String
Dim rng As Range
Dim tbl As ListObject
Dim Cl As Long
Dim Rl As Long
Set wbDestination = ThisWorkbook
Set wsDestination = wbDestination.Sheets("DataTab")
strFName = wbDestination.Worksheets("Macros").Range("C2").Value
Set wbSourceData = Workbooks.Open(strFName)
Set wsSourceData = wbSourceData.Worksheets(3)
Set tbl = wsDestination.ListObjects("Data_Report")
tbl.DataBodyRange.ClearContents
With wsSourceData
Cl = .Cells(2, .Columns.Count).End(xlToLeft).Column
Rl = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rng = .Range(.Cells(2, "A"), .Cells(Rl, Cl))
End With
rng.Copy
wsDestination.Range("A4").PasteSpecial xlValues
Application.CutCopyMode = False
wbSourceData.Close SaveChanges:=False
End Sub
Overwrite Data Body Range
It is assumed that only values of the range will be copied.
The Code
Option Explicit
Sub overwriteDataBodyRangeTEST()
Dim rg As Range: Set rg = Range("G2:K11")
Dim tbl As ListObject: Set tbl = DataTab.ListObjects("Data_Report")
overwriteDataBodyRange rg, tbl
End Sub
Sub overwriteDataBodyRange( _
ByVal rg As Range, _
ByVal tbl As ListObject)
With tbl.DataBodyRange
Dim rCount As Long: rCount = rg.Rows.Count
Dim tCount As Long: tCount = .Rows.Count
If rg.Columns.Count = .Columns.Count Then
.Resize(rCount).Value = rg.Value
If rCount < tCount Then
.Resize(tCount - rCount).Offset(rCount).Delete
End If
Else
MsgBox "Different number of columns.", vbCritical, "Fail"
End If
End With
End Sub
EDIT
The following will copy the range to the table overwriting the previous data. If the previous data has more rows, they will be deleted.
Integrated
Option Explicit
Sub Import_File()
' Define Destination Table.
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.Worksheets("DataTab")
Dim tbl As ListObject: Set tbl = dws.ListObjects("Data_Report")
' Define Source Range.
Dim sName As String: sName = dwb.Worksheets("Macros").Range("C2").Value
Dim swb As Workbook: Set swb = Workbooks.Open(sName)
Dim sws As Worksheet: Set sws = swb.Worksheets(3)
Dim rng As Range
Dim LastRow As Long
Dim LastColumn As Long
With sws
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastColumn = .Cells(2, .Columns.Count).End(xlToLeft).Column
Set rng = .Range(.Cells(2, "A"), .Cells(LastRow, LastColumn))
End With
' Copy Source Range to Destination Table.
With tbl.DataBodyRange
Dim tCount As Long: tCount = .Rows.Count
Dim rCount As Long: rCount = rng.Rows.Count
.Resize(rCount).Value = rng.Value ' values only
'rng.Copy .Resize(rCount) ' values, formats, and formulas
If rCount < tCount Then
.Resize(tCount - rCount).Offset(rCount).Delete
End If
End With
' Close Source Workbook (it was just read from).
swb.Close SaveChanges:=False
End Sub

Resources