Switch between Workbooks, Loop through sheets and copy ranges - vba

I need help one last time, code below works fine; it copies values (A1) from sheets that is in array to a new created sheet in org file. The last modyfication I want to make here, is that in this NOT_ORG file I want to copy range of values, rather than 1 value. This range always starts from A7, but the number of cols and rows might change. I want to copy this range dynamically and paste in in range(a1) in newly created sheet. I know that I should calculate lastRow & lastCol, but not sure where to put this code, and how to modify this last copy line to achieve this result.
Tagging #faneduru as he helped me initially.
Sub Test1()
Dim lastRow As Long
Dim WshtNames As Variant
Dim WshtNameCrnt As Variant
Dim WB1 As Workbook
Dim WB2 As Workbook
Set WB1 = ActiveWorkbook
Set WB2 = Workbooks.Open("C:\NOT_ORG.xlsx")
WshtNames = Array("2", "3")
For Each WshtNameCrnt In WshtNames
WB1.Sheets.Add.Name = WshtNameCrnt & "_new"
WB2.Worksheets(WshtNameCrnt).Range("A1").Copy ActiveSheet.Range("A1")
Next WshtNameCrnt
End Sub
Thanks in advance.
eM

Please, test the next code:
Sub Test1()
Dim lastRow As Long, lastCol As Long, WshtNames, WshtNameCrnt
Dim WB1 As Workbook, WB2 As Workbook, ws As Worksheet
Set WB1 = ActiveWorkbook
Set WB2 = Workbooks.Open("C:\NOT_ORG.xlsx")
WshtNames = Array("2", "3")
For Each WshtNameCrnt In WshtNames
WB1.Sheets.Add.Name = WshtNameCrnt & "_new"
Set ws = WB2.Worksheets(WshtNameCrnt)
lastRow = ws.Range("A" & ws.rows.count).End(xlUp).row
lastCol = ws.cells(7, ws.Columns.count).End(xlToLeft).Column
ws.Range(ws.Range("A" & 7), ws.cells(lastRow, lastCol)).Copy ActiveSheet.Range("A1")
Next WshtNameCrnt
End Sub
And a faster version, using an array:
Sub Test1Array()
Dim lastRow As Long, lastCol As Long, WshtNames, WshtNameCrnt
Dim WB1 As Workbook, WB2 As Workbook, ws As Worksheet, arr
Set WB1 = ActiveWorkbook
Set WB2 = Workbooks.Open("C:\NOT_ORG.xlsx")
WshtNames = Array("2", "3")
For Each WshtNameCrnt In WshtNames
WB1.Sheets.Add.Name = WshtNameCrnt & "_new"
Set ws = WB2.Worksheets(WshtNameCrnt)
lastRow = ws.Range("A" & ws.rows.count).End(xlUp).row
lastCol = ws.cells(7, ws.Columns.count).End(xlToLeft).Column
arr = ws.Range(ws.Range("A" & 7), ws.cells(lastRow, lastCol)).value
ActiveSheet.Range("A1").Resize(UBound(arr), UBound(arr, 2)).value = arr
Next WshtNameCrnt
End Sub

Related

VBA - Remove Duplicates Across Multiple Sheets in Workbook

I have multiple sheets in a particular workbook, and n each sheet there are Employee Numbers. The sheets have already been sorted in a way that Column A is always the Employee Number.
So what I need to do is loop through all the sheets and apply the RemoveDuplicates function to delete all duplicate Employee Numbers found in Column A.
Note - I am not trying to have the Employee Number appear on only one sheet; I am trying to have the Employee Number appear only once on each sheet.
I have it working for when I name a specific sheet, but cannot get it to work in a loop.
Test1:
Sub deleteDuplicate()
Dim ws As Worksheet
Dim wkbk1 As Workbook
Dim w As Long
Dim lRow As Long
Dim iCntr As Long
Set wkbk1 = Workbooks("3rd Party.xlsm")
wkbk1.Activate
For Each ws In ThisWorkbook.Worksheets
' Find last row in column A
lRow = ws.Range("A" & ws.Rows.count).End(xlUp).Row
For iCntr = lRow To 1 Step -1
ws.lRow.RemoveDuplicates Columns:=1, Header:=xlYes
Next iCntr
Next ws
End Sub
Test2:
Sub deleteDuplicate()
Dim ws As Worksheet
Dim wkbk1 As Workbook
Dim w As Long
Dim lRow As Long
Dim iCntr As Long
Set wkbk1 = Workbooks("3rd Party.xlsm")
wkbk1.Activate
With wkbk1
For w = 1 To .Worksheets.count
With Worksheets(w)
.UsedRange.RemoveDuplicates Columns:=1, Header:=xlYes
End With
Next w
End With
End Sub
The issue in both tests
Set wkbk1 = Workbooks("3rd Party.xlsm") - it implies the code is not in ThisWorkbook, yet
Test 1 uses ThisWorkbook - explicitly (For Each ws In ThisWorkbook.Worksheets)
Test 2 uses ThisWorkbook - implicitly (With Worksheets(w))
For this to work the file "3rd Party.xlsm" must be open at the same time
Try the versions bellow, and if the code is not running in ThisWorkbook, update wb accordingly
(ThisWorkbook is the file where the VBA code is executed from)
.
Version 1 - determine last row and last column
Option Explicit
Public Sub DeleteDuplicates1()
Dim wb As Workbook, ws As Worksheet, lr As Long, lc As Long, ur As Range
On Error Resume Next 'Expected error: wb not found
Set wb = ThisWorkbook 'Workbooks("3rd Party.xlsm")
If Not wb Is Nothing Then
Application.ScreenUpdating = False
For Each ws In wb.Worksheets
lr = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lc = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Set ur = ws.Range("A1", ws.Cells(lr, lc))
ur.RemoveDuplicates Columns:=Array(1), Header:=xlYes
Next
Application.ScreenUpdating = True
End If
End Sub
.
Version 2 - UsedRange
Public Sub DeleteDuplicates2()
Dim wb As Workbook, ws As Worksheet
On Error Resume Next 'Expected error: wb not found
Set wb = ThisWorkbook 'Workbooks("3rd Party.xlsm")
If Not wb Is Nothing Then
Application.ScreenUpdating = False
For Each ws In wb.Worksheets
ws.UsedRange.RemoveDuplicates Columns:=Array(1), Header:=xlYes
Next
Application.ScreenUpdating = True
End If
End Sub
If nothing happens when you run either of these versions, the file "3rd Party.xlsm" doesn't exist.
Either it's not open currently, or the name is different - maybe "3rd Party.xlsx" (with an x)
.
If you still have errors for Version 2, .UsedRange may not be what you expect
Try cleaning extra rows and columns with this Sub
Public Sub RemoveEmptyRowsAndColumns()
Dim wb As Workbook, ws As Worksheet, lr As Long, lc As Long, er As Range, ec As Range
On Error Resume Next 'Expected error: wb not found
Set wb = ThisWorkbook 'Workbooks("3rd Party.xlsm")
If Not wb Is Nothing Then
Application.ScreenUpdating = False
For Each ws In wb.Worksheets
lr = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lc = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
If lr > 1 And lc > 1 Then
Set er = ws.Range(ws.Cells(lr + 1, "A"), ws.Cells(ws.Rows.Count, "A"))
Set ec = ws.Range(ws.Cells(1, lc + 1), ws.Cells(1, ws.Columns.Count))
er.EntireRow.Delete 'Shift:=xlUp
ec.EntireColumn.Delete 'Shift:=xlToLeft
End If
Next
Application.ScreenUpdating = True
End If
End Sub

Excel VBA - Copy mutiple column not in sequence order

I want to copy from one sheet into another. The macro should recognize the worksheet via name:
Dim Wb1 As Workbook, wb2 As Workbook, wB As Workbook
Dim rngToCopy As Range
Dim NewEnd As Long
Dim NewEnd2 As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Sheets("CALC").Select
Worksheets("CALC").Range("B5:J25000").ClearContents
For Each wB In Application.Workbooks
If Left(wB.Name, 4) = "15B2" Then
Set Wb1 = wB
Exit For
End If
Next
If Not Wb1 Is Nothing Then
Set wb2 = ThisWorkbook
With Wb1.Sheets("Data")
Set rngToCopy = .Range("F7, H7, N7", .Cells(.rows.Count, "F").End(xlUp))
End With
wb2.Sheets("CALC").Range("B5:D5").Resize(rngToCopy.rows.Count).Value = rngToCopy.Value
End If
This line gives me an error:
Set rngToCopy = .Range("F7, H7, N7", .Cells(.Rows.Count, "F").End(xlUp))
How can I copy mutiple columns in this case?
You can use Union to merge multiple columns to 1 Range.
Dim LastRow As Long
LastRow = .Cells(.Rows.Count, "F").End(xlUp).Row ' get last row with data from column "F"
Set rngToCopy = Application.Union(.Range("F7:F" & LastRow), .Range("H7:H" & LastRow), .Range("N7:N" & LastRow))
rngToCopy.Copy
wb2.Sheets("CALC").Range("B5").PasteSpecial xlPasteValues

Loop extracting a median

This code does what I want per entry in the txtKB textbox:
Dim ws1 As Worksheet
Dim lastrow As Long
Dim clipboardObj As New MSForms.DataObject
Dim wstest As Worksheet
Dim clipboardTxt As String
Set ws1 = Sheets("Sheet6")
Set wstest = Sheets("Sheet8")
lastrow = ws1.Range("A" & Rows.Count).End(xlUp).Row
ws1.Range("M1:A" & lastrow).AutoFilter field:=13, Criteria1:=txtKB
ws1.Range("B" & Rows.Count).End(xlUp).Offset(1).Select
txtmedian = WorksheetFunction.Aggregate(12, 5, Columns(2))
clipboardTxt = txtmedian.Text
clipboardObj.SetText clipboardTxt
clipboardObj.PutInClipboard
wstest.Range("A" & Rows.Count).End(xlUp).Offset(1) = txtmedian
but I want to improve it (so that I will not need to manually input the ID in textbox txtKB criteria anymore, and automate everything with just one click of a button) to take an entry in ws2 Column A (like an ID), look it up in ws1 then perform the median extraction, paste the median in wstest then move to the next ID in ws2 until it goes through all IDs in ws2.
Note: ws2 is not yet in the code.
I need to place a loop somewhere I just don't know where.
You could try something like:
Dim ws as worksheet
Dim wb as workbook
set wb = ThisWorkbook
For Each ws in wb.Worksheets
' Do what you want here
next ws
This will loop through all worksheets in the workbook
To work it into your code
Dim wb as workbook
Dim ws As Worksheet
Dim lastrow As Long
Dim clipboardObj As New MSForms.DataObject
Dim wstest As Worksheet
Dim clipboardTxt As String
set wb = ThisWorkbook
Set wstest = Sheets("Sheet8")
For Each ws in wb.Worksheets ' Loop through all sheets in workbook
if not ws.name = wstest.name then ' Avoid sheet you're copying too (ammend as needed)
With ws
lastrow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("M1:A" & lastrow).AutoFilter field:=13, Criteria1:=txtKB
.Range("B" & Rows.Count).End(xlUp).Offset(1).Select
End With
txtmedian = WorksheetFunction.Aggregate(12, 5, Columns(2))
clipboardTxt = txtmedian.Text
clipboardObj.SetText clipboardTxt
clipboardObj.PutInClipboard
wstest.Range("A" & Rows.Count).End(xlUp).Offset(1) = txtmedian 'You will need to change your code to paste into different locations I would have assumed, I'll leave that up to you though
End if
Next ws

Copy range between workbooks

I am trying to copy a range of cells on a sheet in one workbook to the bottom of a sheet in another workbook. I keep getting "Application-defined or object-defined error" on the copy line.
Dim NewFileName As String
Dim BAHFileName As String
NewFileName = "Filename"
BAHFileName = "Other Filename"
LastRow = Sheets("All").UsedRange.Rows.Count
Workbooks(NewFileName).Sheets("All").Range(Cells(2, 1), Cells(LastRow, 15)).Copy
Windows(BAHFileName & ".xlsx").Activate
LastRow = Workbooks(BAHFileName).Sheets(1).UsedRange.Rows.Count + 1
Workbooks(BAHFileName).Sheets(1).Cells(LastRow, 1).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Talking to yourself?
Practise with this code to avoid using selects.
I am not sure of the situation of your workbooks, so you will have to adjust workbook names and sheet names accordingly.
Sub Button1_Click()
Dim WB As Workbook
Dim bk As Workbook
Dim LastRow As Long
Dim Lrow As Long
Dim rng As Range
Dim ws As Worksheet
Dim sh As Worksheet
Set WB = ThisWorkbook
Set bk = Workbooks("MyWorkbook.xlsx")
Set ws = WB.Sheets("All")
Set sh = bk.Sheets(1)
With ws
LastRow = .UsedRange.Rows.Count
Set rng = .Range(.Cells(2, 1), .Cells(LastRow, 15))
End With
With sh
Lrow = .UsedRange.Rows.Count + 1
rng.Copy .Cells(Lrow, 1)
End With
End Sub
I needed to select the sheet before copying.
Dim NewFileName As String
Dim BAHFileName As String
NewFileName = "Filename"
BAHFileName = "Other Filename"
LastRow = Sheets("All").UsedRange.Rows.Count
Sheets("All").Select
Workbooks(NewFileName).Sheets("All").Range(Cells(2, 1), Cells(LastRow, 15)).Copy
Windows(BAHFileName & ".xlsx").Activate
LastRow = Workbooks(BAHFileName).Sheets(1).UsedRange.Rows.Count + 1
Workbooks(BAHFileName).Sheets(1).Cells(LastRow, 1).Select
ActiveSheet.Paste
Application.CutCopyMode = False

Extract Multiple Columns

Below is the code I have tried with but it only worked for Column A, I want to do the same job with other columns:
Sub ColumnAMaster()
Dim lastRow As Long, lastRowMaster As Long
Dim ws As Worksheet
Dim Master As Worksheet
Application.ScreenUpdating = False
Set Master = Sheets.Add
Master.Name = "Master"
lastRowMaster = 1
For Each ws In ThisWorkbook.Sheets
If ws.Name <> "Master" Then
lastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
ws.Range("A1:A" & lastRow).Copy Destination:=Master.Range("A" & lastRowMaster)
lastRowMaster = Master.Range("A" & Rows.Count).End(xlUp).Row + 1
End If
Next
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
sub Master_data()
'declarations
Dim ws1 as worksheet
Dim ws2 as worksheet
Dim ws3 as worksheet
Dim ws4 as worksheet
Dim i as long
Dim lastrow_sh1 as long
Dim lastrow_sh4 as long
Dim wb as workbook
set wb= application.activeworkbook
set ws1=wb.sheets("sheet1")
set ws2=wb.sheets("sheet2")
set ws3=wb.sheets("sheet3")
set ws4=wb.sheets("sheet4")
lastrow_sh1= ws1.range("A1").end(xlup).row
ws4.cells(1,1)="name"
for i =2 to lastrow_sh1
if ws1.cells(i,1)=ws2.cells(i,1) & ws3.cell(i,1)then
lastrow_sh4=ws4.range(A1).end(xlup).row
ws4.cells(lastrow_sh4+1,1)=ws1.cells(i,1)
ws4.cells(lastrow_sh4+1,2)=ws1.cells(i,2)
ws4.cells(lastrow_sh4+1,3)=ws1.cells(i,3)
ws4.cells(lastrow_sh4+1,4)=ws3.cells(i,4)
endif
next i
end sub