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
Related
I am trying to copy data from workbook1 and pasting to workbook2 as per there valves if the valve is not same as previous than create a new sheet in the workbook and start pasting valve in the new sheet and do until did not find blank row in workbook1.
Sub icopy()
Dim LastRow As Long, Limit2 As Long, c As Long, d As Long, erow As Long
Dim sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet, wb As Workbook,
wb1 As Workbook
If Is_WorkBook_Open("test.xlsx") Then
Set wb = Workbooks("test.xlsx")
Else
Set wb = Workbooks.Open("D:\Data\test.xlsx")
End If
Set sh1 = wb.Sheets("Sheet1")
LastRow = sh1.Cells(Rows.Count, 1).End(xlUp).Row
'wb.Close
MsgBox LastRow
For i = 2 To LastRow
If sh1.Cells(i, 1) = sh1.Cells(i + 1, 1) Then
If (i = 2) Then
Set wb1 = Workbooks.Open("D:\Data\Data1.xlsx")
Sheets.Add(After:=Sheets(Sheets.Count)).Name = sh1.Cells(2, 1)
Set sh2 = wb1.ActiveSheet.Name
End If
sh1.Range(Cells(i, 1), Cells(i, 3)).Copy
erow = sh2.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
'sh2.Cells(erow, 1).Select
sh2.Cells(erow, 3).Paste
sh2.Paste
ActiveWorkbook.Save
Else
MsgBox i
Sheets.Add(After:=Sheets(Sheets.Count)).Name = sh1.Cells(i + 1, 1)
End If
Next i
'erow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
'ActiveSheet.Cells(erow, 1).Select
' ActiveSheet.Paste
'ActiveWorkbook.Save
'ActiveWorkbook.Close
'Application.CutCopyMode = False
End Sub
Function Is_WorkBook_Open(ByVal strWorkbookName As String) As Boolean
Dim wb As Workbook
On Error Resume Next
Set wb = Workbooks(strWorkbookName)
If Err Then
Is_WorkBook_Open = False
Else
Is_WorkBook_Open = True
End If
End Function
since I understand your valve data are adjacent (i.e. all same valve data are within one block of adjacent rows), you could consider the following:
Option Explicit
Sub icopy()
Dim sh1 As Worksheet, sh2 As Worksheet, wb1 As Workbook
Dim iRow As Long
If Is_WorkBook_Open("test.xlsx") Then
Set sh1 = Workbooks("test.xlsx").Sheets("Sheet1")
Else
Set sh1 = Workbooks.Open("D:\Data\test.xlsx").Sheets("Sheet1")
End If
Set wb1 = Workbooks.Open("D:\Data\Data1.xlsx") ' open your target workbook
With sh1
iRow = 2
With .Range("A1", .Cells(.Rows.Count, 1).End(xlUp))
Do While iRow <= .Rows.Count
.AutoFilter field:=1, Criteria1:=.Cells(iRow, 1).Value
wb1.Sheets.Add(After:=wb1.Sheets(wb1.Sheets.Count)).name = .Cells(iRow, 1).Text
With .Resize(, 3).SpecialCells(xlCellTypeVisible)
.copy Destination:=wb1.Sheets(.Cells(iRow, 1).Text).Range("a1")
iRow = .Areas(.Areas.Count).Rows(.Areas(.Areas.Count).Rows.Count).row + 1
End With
Loop
End With
.AutoFilterMode = False
End With
End Sub
I have to find the last column of a row in a sheet. I am able to find the last column in the sheet, but for a particular row, I need to find the last column which will vary for every sheet in the excel, and it will vary at every run. To find the last column, I have used the below code, with reference from the question Finding last column across multiple sheets in a function:
For Each ws In ThisWorkbook.Sheets
lc = ws.Cells.Find("*", SearchOrder:=xlByColumns,
SearchDirection:=xlPrevious).Column
Debug.Print ws.Name, lc
MsgBox lc
Next ws
Updated:
Trying to use the below code, but its showing error code 91. Function is :
Function lastColumn(Optional sheetName As String, Optional
rowToCheck As Long = 1) As Long
Dim ws As Worksheet
If sheetName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(sheetName)
End If
lastColumn = ws.Cells(rowToCheck, ws.Columns.Count).End(xlToLeft).Column
End Function
Calling it in the code as:
For Each ws In ThisWorkbook.Worksheets
i = ws.Columns(2).Find("Total").Row (error code as 91)
Debug.Print lastColumn(ws.Name, i)
Next ws
Sub Test()
For Each ws In ThisWorkbook.Sheets
lc = ws.Cells(i, ws.Columns.Count).End(xlToLeft).Column
Debug.Print ws.Name, lc
MsgBox lc
Next ws
End Sub
Just replace i with the row number.
This is the function that I am using for lastColumn per specific row:
Function lastColumn(Optional sheetName As String, Optional rowToCheck As Long = 1) As Long
Dim ws As Worksheet
If sheetName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(sheetName)
End If
lastColumn = ws.Cells(rowToCheck, ws.Columns.Count).End(xlToLeft).Column
End Function
It takes optional arguments sheetName and rowToCheck. This is a way to run it for your case:
Public Sub TestMe()
Dim ws As Worksheet
Dim lc As Long
lc = 8
For Each ws In ThisWorkbook.Worksheets
Debug.Print lastColumn(ws.Name, lc)
Next ws
End Sub
Try this :
With Worksheets(set_sheet_name)
LastCol = .Cells(5, .Columns.Count).End(xlToLeft).Column
End With
this will get you nr. of columns from the line "5", if you want another line just change the 5 with whatever line you need.
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
I would to copy paste the first cell of a sheet trough the last row for all sheets in a workbook and my code is not working, the code is done on the active sheet only.
Sub Macro5()
'
' Macro5
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
Range("A2").Copy Destination:=Range("A3:A" & Cells(Rows.Count, "B").End(xlUp).Row)
Next ws
End Sub
Thanks for your help
Looping the worksheets does not make them active. You want something like this.
Dim WS As Excel.Worksheet
Dim iIndex As Integer
For iIndex = 1 To ActiveWorkbook.Worksheets.count
Set WS = Worksheets(iIndex)
With WS
'Do something here.
.Range("A2").Copy Destination:=.Range("A3:A" & .Cells(.Rows.Count, "B").End(xlUp).Row)
End With
Next iIndex
You could use the ws in your loop, but I always set the object.
For Each ws In ActiveWorkbook.Worksheets
ws.Range("A2").Copy Destination:=ws.Range("A3:A" & Cells(Rows.Count, "B").End(xlUp).Row)
Next ws
I want to delete rows over multiple worksheets (only specific ones within the workbook) if a cell value is blank. Note, the rest of the fields in the row do contain data. So far I have the below however unsure how to specify the worksheets. Can anyone help?
Sub sbDelete_rows_if_cell_blank()
Dim lRow As Long
Dim iCntr As Long
lRow = 2000
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 1).Value = "" Then
Rows(iCntr).Delete
End If
Next
End Sub
Putting your code inside this loop will loop through all the worksheets in the Workbook that this code is inside and run your code in each.
Sub sbDelete_rows_if_cell_blank()
Dim lRow As Long
Dim iCntr As Long
Dim ws as Worksheet
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
If ws.name<>"Sheet1" and ws.name <> "Sheet2" then ' change this line to the sheet names you want to leave out.
If IsEmpty(ws.Cells(iCntr, 1)) Or Trim(ws.Cells(iCntr, 1).Value) = "" Then
ws.Rows(iCntr).Delete
End If
end if
Next iCntr
Next ws
End Sub
Updated with D_Bester's suggestion for if condition
Update 2: See Comments
This will do what I think you want to achieve
Sub Combine()
Dim nws, ws As Worksheet
Dim rng As Range
' Add New Sheet
On Error Resume Next
Set nws = ThisWorkbook.Sheets("Combined")
If nws Is Nothing Then
With ThisWorkbook.Sheets
Set nws = .Add(After:=Sheets(.Count))
nws.Name = "Combined"
End With
End If
On Error GoTo 0
For Each ws In ThisWorkbook.Sheets
If Not ws.Name = nws.Name Then
With ws
Set rng = Range(.Cells(1, 1), .Cells(.UsedRange.Rows.Count, .UsedRange.Columns.Count))
rng.Copy Destination:=nws.Cells(nws.Cells(nws.Rows.Count, "A").End(xlUp).Row + 1, 1)
End With
End If
Next ws
End Sub
You can loop through the sheets, then use specialcells to delete the blanks.
Yoi can also set the loop so it doesn't delete the blanks in "Sheet1"(in this example)
Sub DeleteBlnkRows()
Dim sh As Worksheet
For Each sh In Sheets
If sh.Name <> "Sheet1" Then
sh.Columns("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End If
Next sh
End Sub