I was just wondering if is there any way of comparing two excels spreadsheets using macro. I have a piece of macro that basically does the work but it checks column by column. So say in case I have a value defined in A(1,1) in sheet1 and if the same value is not present in A(1,1) in sheet2 but the value present in any row of the column then it won't raise a complaint.
'compare Sheet
Sub CompareTable()
Dim tem, tem1 As String
Dim text1, text2 As String
Dim i As Integer, hang1 As Long, hang2 As Long, lie As Long, maxhang As Long, maxlie As Long
Sheets("Sheet1").Select
Columns("A:A").Select
With Selection.Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Range("A1").Select
Sheets("Sheet2").Select
Dim lastRow As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Rows("1:" & lastRow).Select
With Selection.Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Range("A1").Select
maxhang = lastRow ' number of the last row containg data
MaxRow = lastRow
Dim LastCol As Integer
With ActiveSheet
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
MaxColumn = LastCol
For col = 1 To MaxColumn
For hang1 = 2 To maxhang
Dim a As Integer
a = 0
tem = Sheets(1).Cells(hang1, col)
For hang2 = 1 To maxhang
tem1 = Sheets(2).Cells(hang2, col)
If tem1 = tem Then
a = 1
Sheets(2).Cells(hang2, col).Interior.ColorIndex = 6
For lie = 1 To maxlie
text1 = Sheets(1).Cells(hang1, lie)
text2 = Sheets(2).Cells(hang2, lie)
If text1 <> text2 Then
Sheets(2).Cells(hang2, lie).Interior.ColorIndex = 8
End If
Next
End If
Next
If a = 0 Then
Sheets(1).Cells(hang1, 1).Interior.ColorIndex = 5
End If
Next
Next
End Sub
Note : I'm looking for any solution that could give me a row match, so if any value of the given row is not matched with the sheet2 then it should highlight it.
I'm open to have any other alternative as well. Any help or suggestion would be much appreciated.
Thanks for your time !
Im not sure if this is what you are expecting. Please see my below code
Sub CompareTable()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim table1 As Range
Dim table2 As Range
Dim table1Rows As Integer
Dim table1Cols As Integer
Set ws1 = Worksheets("sheet1")
Set ws2 = Worksheets("sheet2")
Set table1 = ws1.Cells
Set table2 = ws2.Cells
table1Rows = ws1.UsedRange.Rows.Count
table1Cols = ws1.UsedRange.Columns.Count
For i = 1 To table1Rows
For j = 1 To table1Cols
If table1(i, j).Value = table2(i, j).Value Then
Else
ws1.Cells(i, j).Interior.Color = vbYellow
End If
Next
Next
End Sub
Sheet1 table
Sheet2 table
After Running the code tgisis my result
Related
I am currently new to macro VBA and I have been trying to copy a column if the values of a specific rows are the same then paste it on another sheet until all columns are copied and pasted. The purpose of this is to consolidate team members of a team (the team is the value that im trying to look for). It only stops when the next cell to the right is already blank. And I will only find the team members' team on the first row of the sheet only. I placed a code that I found on the Internet and modified it but it only copies the last DATA team it finds. Thank you.
Dim ws As Worksheet
Dim aCell As Range, Rng As Range
Dim col As Long, lRow As Long
Dim colName As String
Set ws = ThisWorkbook.Sheets("Values")
With ws
Set aCell = .Range("A1:XFD1").Find(What:="DATA", LookIn:=xlValues, LookAt:=xlWhole, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
aCell.EntireColumn.Cut
Sheets("Team").Columns("D:W").Insert Shift:=xlToRight
Else
MsgBox "Team not found"
End If
End With
You can try this.
Option Explicit
Sub CopyCols()
Dim ArrTeams() As String, Team As String
Dim TeamCounter As Long, LastCol As Long, FirstCol As Long, i As Long, LastColDest As Long
Dim SrcWs As Worksheet
Dim Wb As Workbook
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set Wb = ThisWorkbook
Set SrcWs = Wb.Sheets("Sheet1")
ReDim ArrTeams(1 To 1)
With Wb
With SrcWs
'find last column with team
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
TeamCounter = 1
FirstCol = 1 'or whatever your first column with teams is
'loop all columns in row 1
For i = FirstCol To LastCol
If .Cells(1, i) <> "" Then
Team = .Cells(1, i)
If Not IsInArray(Team, ArrTeams) Then 'take only unique team names
ReDim Preserve ArrTeams(1 To TeamCounter)
ArrTeams(TeamCounter) = Team
TeamCounter = TeamCounter + 1
End If
End If
Next i
End With
'create new sheet for each team
For i = 1 To UBound(ArrTeams)
.Sheets.Add after:=.Sheets(.Sheets.Count)
.Sheets.Item(.Sheets.Count).Name = ArrTeams(i)
Next i
With SrcWs
'loop all columns in row 1
For i = FirstCol To LastCol
If .Cells(1, i) <> "" Then
Team = .Cells(1, i)
With Wb.Sheets(Team)
'find last non empty column on destination sheet
LastColDest = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
.Cells(1, i).EntireColumn.Copy
Wb.Sheets(Team).Cells(1, LastColDest + 1).PasteSpecial
End If
Next i
End With
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Public Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = Not IsError(Application.Match(stringToBeFound, arr, 0))
End Function
It should loop all columns on "Sheet1" starting in FirstCol and ending in LastCol, take unique team names from first row. Create new sheet for each unique team name. Copy entire column for each unique team name to coresponding sheet.
Just remember that it will allways add new sheets so if you want to run it multiple times then there should be check if sheet with specific name already exists.
EDIT
Add
Dim LastRow As Long, j As Long
And
Dim TargetWs As Worksheet
in declaration part at begining
Change loop for adding new sheets to
For i = 1 To UBound(ArrTeams)
.Sheets.Add after:=.Sheets(.Sheets.Count)
.Sheets.Item(.Sheets.Count).Name = ArrTeams(i)
.Sheets(ArrTeams(i)).Range("A2:A1000").FormulaR1C1 = _
"=SUM(RC[2]:RC[" & .Sheets(ArrTeams(i)).Columns.Count - 1 & "])"
Next i
at the end add
For i = LBound(ArrTeams) To UBound(ArrTeams)
Team = ArrTeams(i) 'team name and also sheet name
Set TargetWs = .Sheets(Team)
With TargetWs
.Calculate 'calculate SUM formula on each sheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 'last row with data in column "A"
For j = LastRow To 2 Step -1 'assuming that in row 1 there is some header
If .Cells(j, "A") = 0 Then
.Cells(j, "A").EntireRow.Delete
End If
Next j
End With
Next i
This should do the trick as long as you don't have more than 1000 rows of data. If so you can adjust SUM formula to cover more rows or find last row with data on each "Team" sheet and adjust formula in loop.
Hi #Sphinx this is what I have so far. And I modified the code you have given and added something to it. The syntax that I do not have is on how to delete a row when a specific cell on column C has 0 value. And it should work on all ArrTeams(i) sheets only. Thank you for you help.
https://i.stack.imgur.com/M8NS8.png
Option Explicit
Sub CopyCols()
Dim ArrTeams() As String, Team As String
Dim TeamCounter As Long, LastCol As Long, FirstCol As Long, i As Long, LastColDest As Long
Dim SrcWs As Worksheet
Dim Wb As Workbook
Dim LastRowColumnD As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set Wb = ThisWorkbook
Set SrcWs = Wb.Sheets("Values")
ReDim ArrTeams(1 To 1)
With Wb
With SrcWs
'find last column with team
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
TeamCounter = 1
FirstCol = 1 'or whatever your first column with teams is
'loop all columns in row 1
For i = FirstCol To LastCol
If .Cells(1, i) <> "" Then
Team = .Cells(1, i)
If Not IsInArray(Team, ArrTeams) Then 'take only unique team names
ReDim Preserve ArrTeams(1 To TeamCounter)
ArrTeams(TeamCounter) = Team
TeamCounter = TeamCounter + 1
End If
End If
Next i
End With
'create new sheet for each team
For i = 1 To UBound(ArrTeams)
.Sheets.Add After:=.Sheets(.Sheets.Count)
.Sheets.Item(.Sheets.Count).Name = ArrTeams(i)
Sheets("Values").Columns("A:C").Copy
ActiveSheet.Paste Destination:=Worksheets(ArrTeams(i)).Range("A1:C1")
Range("A1").Value = " "
Range("B1").Value = " "
Range("C1").Value = " "
Range("A2").Value = "Team:"
Range("B2").Value = ArrTeams(i)
Range("C2").Value = " "
Range("B2").HorizontalAlignment = xlCenter
Range("B2").VerticalAlignment = xlCenter
Range("A2").HorizontalAlignment = xlCenter
Range("A2").VerticalAlignment = xlCenter
LastRowColumnD = Cells(Rows.Count, 1).End(xlUp).Row
Range("C4:C" & LastRowColumnD).Formula = "=sum(D4:XFD4)"
Next i
With SrcWs
'loop all columns in row 1
For i = FirstCol To LastCol
If .Cells(1, i) <> "" Then
Team = .Cells(1, i)
With Wb.Sheets(Team)
'find last non empty column on destination sheet
LastColDest = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
.Cells(1, i).EntireColumn.Copy
Wb.Sheets(Team).Cells(1, LastColDest + 1).PasteSpecial
End If
Next i
End With
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Public Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = Not IsError(Application.Match(stringToBeFound, arr, 0))
End Function
I have two similar macros I've written, and for efficiency's sake I'd like to consolidate them into one. The first macro adds 4 blank rows on another tab underneath a specific row, where column C matches certain criteria. The second macro copies 4 rows of data from an existing tab over to the new tab, and pastes that data into the 4 newly created blank rows. Any help would be greatly appreciated! Thank you
Conceptual screenshots attached:
Screenshot 1: Initial State
Screenshot 2: MACRO 1 inserts 4 rows if criteria in column C is met (in this case value = "Part A"
Screenshot 3: MACRO 2 pulls in row data from another sheet and pastes it into the new blank rows on this sheet
FIRST MACRO:
Sub RowAdder_01()
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Dim PN_01 As Range
Set PN_01 = Range("M17")
Col = "C"
StartRow = 1
BlankRows = 1
LastRow = Cells(Rows.Count, Col).End(xlUp).Row
Application.ScreenUpdating = False
With Worksheets("NEW SHEET")
For R = LastRow To StartRow + 1 Step -1
If .Cells(R, Col) = PN_01 Then
.Cells(R + 1, Col).EntireRow.Insert Shift:=xlDown
.Cells(R + 1, Col).EntireRow.Insert Shift:=xlDown
.Cells(R + 1, Col).EntireRow.Insert Shift:=xlDown
.Cells(R + 1, Col).EntireRow.Insert Shift:=xlDown
End If
Next R
End With
Application.ScreenUpdating = True
End Sub
SECOND MACRO:
Sub PasteRowData_01()
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Dim PN_01 As Range
Set PN_01 = Range("M17")
Col = "C"
Drop = "A"
StartRow = 1
BlankRows = 1
LastRow = Cells(Rows.Count, Col).End(xlUp).Row
Application.ScreenUpdating = False
Sheets("OLD SHEET").Rows("54:57").SpecialCells(xlCellTypeVisible).Select
Selection.Copy
With Worksheets("NEW SHEET")
For R = LastRow To StartRow + 1 Step -1
If .Cells(R, Col) = PN_01 Then
Sheets(NEW SHEET).Select
.Cells(R + 1, Drop).Select
Selection.PasteSpecial
End If
Next R
End With
Application.ScreenUpdating = True
End Sub
Please try this code.
Option Explicit
Sub AddAndPaste()
Dim Ws As Worksheet
Dim Arr As Variant
Dim PN_01 As Variant
Dim Last As Long ' column or row
Dim R As Long
' copy from source
Set Ws = Worksheets("Old Sheet")
With Ws
With .UsedRange
Last = .Columns.Count + .Column - 1
End With
Arr = Range(.Cells(54, 1), .Cells(57, Last)).SpecialCells(xlCellTypeVisible).Value
End With
Application.ScreenUpdating = False
' paste to destination
Set Ws = Worksheets("New Sheet")
With Ws
PN_01 = .Cells(7, "M").Value
Last = .Cells(.Rows.Count, "C").End(xlUp).Row
For R = Last To 1 Step -1
If .Cells(R, "C").Value = PN_01 Then
With .Cells(R, "A")
.Resize(4, 1).EntireRow.Insert Shift:=xlDown
.Offset(-4).Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr
End With
Exit For ' don't exit if you need to continue looping
End If
Next R
End With
Application.ScreenUpdating = True
End Sub
Your problem is caused by inserting a line. We recommend using an array.
Sub test()
Dim Ws As Worksheet, newWs As Worksheet, Temp As Worksheet
Dim vDB, vSp, vR()
Dim i As Long, r As Long, n As Long, k As Integer, cnt As Integer
Dim PN_01 As Range
Set newWs = Sheets("New Sheet")
Set oldWs = Sheets("OLD SHEET")
Set Temp = Sheets.Add
oldWs.Range("a54:d57").SpecialCells(xlCellTypeVisible).Copy Temp.Range("a1")
vSp = Temp.UsedRange
Application.DisplayAlerts = False
Temp.Delete
Application.DisplayAlerts = True
With newWs
vDB = .Range("a1", "d" & .Range("a" & Rows.Count).End(xlUp).Row)
Set PN_01 = .Range("M17")
End With
cnt = UBound(vSp, 1)
r = UBound(vDB, 1)
For i = 1 To r
n = n + 1
ReDim Preserve vR(1 To 4, 1 To n)
For j = 1 To 4
vR(j, n) = vDB(i, j)
Next j
If vDB(i, 3) = PN_01 Then
For k = 1 To cnt
n = n + 1
ReDim Preserve vR(1 To 4, 1 To n)
For j = 1 To 4
vR(j, n) = vSp(k, j)
Next j
Next k
End If
Next i
newWs.Range("a1").Resize(n, 4) = WorksheetFunction.Transpose(vR)
newWs.Activate
End Sub
i have a code like this :
Dim lastRow As Long
Dim i As Integer
Dim inrange As Range
lRow = Sheet12.Cells.SpecialCells(xlLastCell).Row
Do While Application.CountA(Sheet12.Rows(lRow)) = 0 And lRow <> 1
lRow = lRow - 1
Loop
lastRow = lRow + 1
For l = 1 To 31
inrange = Range("A" & lastRow & " , E" & lastRow)** 'when i tried this code error
Sheet12.Cells(lastRow, l).Interior.Color = RGB(255, 255, 0)
inrange.Borders(xlEdgeLeft).LineStyle = xlContinuous
inrange.Borders(xlEdgeTop).LineStyle = xlContinuous
inrange.Borders(xlEdgeRight).LineStyle = xlContinuous
inrange.Borders(xlEdgeBottom).LineStyle = xlContinuous
Next
the error message is "object variable or with block variable not set", so what should i do. thank's for help.
You need to use the keyword set when assigning a range to a variable. Also I modified your code a little bit I think this is what you are trying to accomplish.
Sub Test()
Dim inrange As Range
Dim lastRow As Long
Dim i As Long
With Sheet12
' Get the last row.
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 1 To 31
' Use the keywprd Set before asigning to an object variable
' like a range, worksheet, workbook.
Set inrange = .Range("A" & lastRow & " , E" & lastRow) 'when i tried this code error
inrange.Interior.Color = RGB(255, 255, 0)
inrange.BorderAround xlContinuous
lastRow = lastRow + 1
Next
End With
End Sub
Thanks, I hope this helps :)
I have been trying to create a macro for copying the header and insert above all the subtotal groups. So all the subtotal groups will have a heading. I tried the below macro but it is not working.
Sub header()
Rows("1:1").Select
Selection.Copy
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Col = "P"
StartRow = 1
BlankRows = 1
LastRow = Cells(Rows.Count, Col).End(xlUp).Row
Application.ScreenUpdating = False
With ActiveSheet
For R = LastRow To StartRow + 1 Step -1
If .Cells(R, Col) = "Total" Then
.Cells(R+1, Col).EntireRow.Insert Shift:=xlDown
End If
Next R
End With
Application.ScreenUpdating = True
End Sub
Try the following. There are several tweaks:
1) I fixed the indenting. A matter of taste perhaps, but I find code hard to read if not logically indented.
2) I replaced the first two lines by Rows(1).Copy. There is no reason to select something in order to copy it (and 1 as an index is more idiomatic than "1:1")
3) The act of inserting the row completes the copy-paste operation. I thus recopied the header row after the insert operation. This fixes your actual problem
4) The final copy in the loop leaves Excel still looking for somewhere to paste the header row. Application.CutCopyMode = False addresses that.
Sub header()
Rows(1).Copy
Dim s As Range
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Col = "P"
StartRow = 1
BlankRows = 1
LastRow = Cells(Rows.Count, Col).End(xlUp).Row
Application.ScreenUpdating = False
With ActiveSheet
For R = LastRow To StartRow + 1 Step -1
If .Cells(R, Col) = "Total" Then
.Cells(R + 1, Col).EntireRow.Insert Shift:=xlDown
Rows(1).Copy
End If
Next R
End With
Application.ScreenUpdating = True
Application.CutCopyMode = False
End Sub
I've been trying to find an easier way to return the amount of coloured cells per column. My code so far:
Sub errors()
Dim Sheet1 As String
Dim mycell As Range
Dim datecol As Long
Dim col As Long
Sheet1 = "different"
For Each mycell In ActiveWorkbook.Worksheets(shtSheet1).Range("B:B")
If mycell.Interior.Color = vbRed Then
datecol = datecol + 1
End If
Next mycell
Debug.Print datecol
End Sub
If I have 40 columns this is pretty tedious and slow, is there a better way to do this (pretty new in learning vba) hence I am repeating several For each loops and specifying the column. I need help improving the code or a new method for returning the amount of coloured cells per column.
Your way is fine, but it can be refined -
Sub test()
Dim lastrow As Integer
lastrow = Cells(Rows.Count, "A").End(xlUp).Row
Dim cntclr As Integer
cntclr = 0
For i = 1 To lastrow
If Cells(i, 1).Interior.Color = vbRed Then
cntclr = cntclr + 1
End If
Next
MsgBox (cntclr)
End Sub
If you want to do it for each column, this will do it and print the results, just change the range where the array populates
Sub test()
Dim lastrow As Integer
lastrow = Cells(Rows.Count, "A").End(xlUp).Row
Dim lastcol As Integer
lastcol = Cells(1, Columns.Count).End(xlToLeft).Column
Dim arr() As String
ReDim arr(1 To lastcol, 1)
Dim cntClr As Integer
Dim strCol As String
Dim strCnt As String
For j = 1 To lastcol
cntClr = 0
For i = 1 To lastrow
If Cells(i, j).Interior.Color = vbRed Then
cntClr = cntClr + 1
End If
Next
strCol = "Col " & Chr(64 + j)
strCnt = Str(cntClr)
arr(j, 0) = strCol
arr(j, 1) = cntClr
Next
Range("D1:E" & lastcol) = arr()
End Sub
Use
Sub errors()
Dim Sheet1 As String
Dim mycell As Range
Dim datecol As Long
Dim col As Long
Sheet1 = "different"
Dim ws As Worksheet, lastrow As Long
Dim myrng as Range
Set ws = ActiveWorkbook.Sheets(Sheet1)
lastrow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
' If you think you may have colored cells with no data
' Set myrng = ws.UsedRange.Rows
' lastrow = myrng(myrng.Count).Row
Set myrng = ws.Range("B1:B" & lastrow)
For Each mycell In myrng
If mycell.Interior.Color = vbRed Then
datecol = datecol + 1
End If
Next mycell
Debug.Print datecol
End Sub