Find matching cell with different strings inside one cell - vba

My goal of my macro:
I have 2 sheets, sheet1 master report and sheet2 import Input.
In column A of both sheets I have several strings in one cell.
I would like to see if there is a match and if there is the match the row from sheet2 (from column B) will be copied and paste in the row corresponding in sheet1.
This part of my code is done.
But now it starts to be tricky: If there is new string in the same cell as the matching string so I would like to add them as well in the cell of the column A sheet1.
For instance:
Sheet1 Column A Cell34:
MDM-9086
Sheet2 Column A Cell1:
MDM-9086,MDM-12345
After the macro it would be like this:
Sheet1 Column A cell34:
MDM-9086,MDM-12345
If there is no match between column A of both sheets so I would like to copy the entire row of the sheet2 and past it in the last free row of the sheet1.
See my code:
Sub MDMNumbers()
Dim LastRw1 As Long, LastRw2 As Long, NxtRw As Long
Dim I As Integer
Dim m As Range
Dim Tb
LastRw1 = Sheets(1).Range("A" & Rows.Count).End(xlUp).Row
LastRw2 = Sheets(2).Range("A" & Rows.Count).End(xlUp).Row
With Worksheets(2)
LastRw2 = .Range("A" & Rows.Count).End(xlUp).Row
For NxtRw = 2 To LastRw2
Tb = Split(.Range("A" & NxtRw), ",")
For I = 0 To UBound(Tb)
With Sheets(1).Range("A2:A" & LastRw1)
Set m = .Find(Trim(Tb(I)), LookAt:=xlPart)
If Not m Is Nothing Then
Sheets(2).Range("B" & NxtRw & ":Q" & NxtRw).Copy _
Sheets(1).Range("B" & m.Row)
Set m = Nothing
End If
End With
Next I
Next NxtRw
End With
End Sub
Example:
Sheet 1, Column A (start row 2)
MDM-123,MDM-27827
MDM-1791728,MDM-124
MDM-125
MDM-126,MDM-28920
MDM-127,MDM-1008
""
Sheet 2, Column A (start row 2)
MDM-123,MDM-27272
MDM-124
MDM-125,MDM-1289
MDM-126
MDM-1008
MDM-127
MDM-172891
Result on Sheet 1, Column A (start row 2):
MDM-123,MDM-27827,MDM-27272
MDM-124,MDM-1791728
MDM-125,MDM-1289
MDM-126,MDM-28920
MDM-127,MDM-1008
MDM-1008
MDM-172891

For your # 2.
Option Explicit
Public Sub MDMNumbers()
Dim LastRw1 As Long, LastRw2 As Long, NxtRw As Long, rng1 As Range, rng2 As Range
Dim i As Long, m As Range, tb() As String, celVal As String, notFound As Boolean
Dim additions1 As String, additions2 As String
LastRw1 = Worksheets(1).Range("A" & Worksheets(1).Rows.Count).End(xlUp).Row + 1
LastRw2 = Worksheets(2).Range("A" & Worksheets(2).Rows.Count).End(xlUp).Row
notFound = True
For NxtRw = 2 To LastRw2
celVal = Worksheets(2).Range("A" & NxtRw).Value2
If Len(celVal) > 0 Then
tb = Split(celVal, ",")
For i = 0 To UBound(tb)
Set m = Worksheets(1).Columns(1).Find(Trim(tb(i)), LookAt:=xlPart)
If Not m Is Nothing And notFound Then
Set rng1 = Worksheets(2).Range("B" & NxtRw & ":Q" & NxtRw)
Set rng2 = Worksheets(1).Range("B" & m.Row & ":Q" & m.Row)
rng1.Copy rng2
With Worksheets(2).Range("A" & NxtRw)
additions1 = Replace(.Value2, "," & tb(i), vbNullString)
additions1 = Replace(additions1, tb(i) & ",", vbNullString)
additions1 = Replace(additions1, tb(i), vbNullString)
End With
With Worksheets(1).Range("A" & m.Row)
additions2 = Replace(.Value2, "," & tb(i), vbNullString)
additions2 = Replace(additions2, tb(i) & ",", vbNullString)
additions2 = Replace(additions2, tb(i), vbNullString)
If Len(additions2) > 0 Then
If Len(additions1) > 0 Then
.Value2 = tb(i) & "," & additions2 & "," & additions1
Else
.Value2 = tb(i) & "," & additions2
End If
Else
.Value2 = tb(i) & "," & additions1
End If
End With
Set m = Nothing
notFound = False
End If
Next
If notFound Then
Set rng1 = Worksheets(2).Range("A" & NxtRw & ":Q" & NxtRw)
Set rng2 = Worksheets(1).Range("A" & LastRw1 & ":Q" & LastRw1)
rng1.Copy rng2
LastRw1 = LastRw1 + 1
End If
notFound = True
End If
Next
End Sub
It should work as expected now
Test data and result:

Why don't you copy the whole row from sheet2 to sheet1 like
For NxtRw = 2 To LastRw2
...
Sheets(2).Range("A" & NxtRw & ":Q" & NxtRw).Copy _
Sheets(1).Range("A" & m.Row)
...
Next NxtRw
? (The rest of the loop should stay the same.)

Related

My reconciliation VBA macro takes too long to run when the data is in the thousands

I have a task that requires me to reconcile two sheets of data. I have reformatted them both to have the same format from Column A to M and use the below code to run the reconciliation
It is fine when the data is small but when it gets to thousands of lines, it took 30 min just to run. Is there a way to optimize this code?
The idea is reconcile 2 worksheets then all the matched data go to the 'Matched' worksheet and the unmatched goes to the unmatched worksheet
Dim report_exLR As Long
Dim report_inLR As Long
Dim report_exrng As Range
Dim report_inrng As Range
Set ws_rexternal = ThisWorkbook.Worksheets("Reformat External")
Set ws_rinternal = ThisWorkbook.Worksheets("Reformat Internal")
Set ws_unmatched = ThisWorkbook.Worksheets("Unmatched")
Set ws_matched = ThisWorkbook.Worksheets("Matched")
ex_LR = ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row
in_LR = ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row
'concatenate all relevant criteria into one column
For a = 2 To ex_LR
ws_rexternal.Range("T" & a) = ws_rexternal.Range("A" & a) & "," & ws_rexternal.Range("B" & a) & "," & ws_rexternal.Range("C" & a) & "," & ws_rexternal.Range("D" & a) & "," & ws_rexternal.Range("E" & a) & "," & ws_rexternal.Range("F" & a) & "," & ws_rexternal.Range("G" & a) & "," & ws_rexternal.Range("H" & a) & "," & ws_rexternal.Range("I" & a) & "," & ws_rexternal.Range("J" & a) & "," & ws_rexternal.Range("K" & a) & "," & ws_rexternal.Range("L" & a) & "," & ws_rexternal.Range("M" & a)
Next a
For b = 2 To ex_LR
ws_rinternal.Range("T" & b) = ws_rexternal.Range("A" & b) & "," & ws_rexternal.Range("B" & b) & "," & ws_rexternal.Range("C" & b) & "," & ws_rexternal.Range("D" & b) & "," & ws_rexternal.Range("E" & b) & "," & ws_rexternal.Range("F" & b) & "," & ws_rexternal.Range("G" & b) & "," & ws_rexternal.Range("H" & b) & "," & ws_rexternal.Range("I" & b) & "," & ws_rexternal.Range("J" & b) & "," & ws_rexternal.Range("K" & b) & "," & ws_rexternal.Range("L" & b) & "," & ws_rexternal.Range("M" & b)
Next b
'start reconciliation
For a = 2 To ex_LR
For b = 2 To in_LR
If ws_rexternal.Range("T" & a) = ws_rinternal.Range("T" & b) Then
ws_rexternal.Range(Cells(a, 1).Address, Cells(a, 14).Address).Copy Destination:=ws_matched.Range(Cells(a, 1).Address, Cells(a, 14).Address)
ws_rinternal.Range(Cells(b, 1).Address, Cells(b, 14).Address).Copy Destination:=ws_matched.Range(Cells(a, 16).Address, Cells(a, 30).Address)
ws_matched.Cells(a, 15).Value = "Matched"
ws_matched.Cells(a, 15).Interior.Color = RGB(0, 255, 0)
ws_rexternal.Rows(a).ClearContents
ws_rinternal.Rows(b).ClearContents
End If
Next b
Next a
'reformat the unmatched and matched
For d = ex_LR To 1 Step -1
Set ex_Row = ws_rexternal.Rows(d)
If WorksheetFunction.CountA(ex_Row) = 0 Then
ws_rexternal.Rows(d).Delete
End If
Next d
For e = in_LR To 1 Step -1
Set in_Row = ws_rinternal.Rows(e)
If WorksheetFunction.CountA(in_Row) = 0 Then
ws_rinternal.Rows(e).Delete
End If
Next e
report_exLR = ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row
report_inLR = ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row
Set report_exrng = ws_rexternal.Range("A1:A" & report_exLR)
report_exrng.EntireRow.Copy ws_unmatched.Cells(1, 1)
Set report_inrng = ws_rinternal.Range("A1:A" & report_inLR)
report_inrng.EntireRow.Copy ws_unmatched.Cells(ex_LR, 1).Offset(5, 0)
End Sub
Ok this is probably a lot more complex than it needs to be, but it seems to work OK.
It would be much simpler to just flag the data in-place as matched/unmatched, with a pointer to the matching row on the other sheet.
Sub FormatExcel()
Dim report_exLR As Long, ws_rexternal As Worksheet, ws_unmatched As Worksheet
Dim report_inLR As Long, ws_rinternal As Worksheet, ws_matched As Worksheet
Dim report_exrng As Range, report_inrng As Range
Dim rngInt As Range, rngExt As Range, k, rw As Range, t, rwMatch As Long
Dim rngIntKeys As Range, rngExtKeys As Range, m, rng As Range, n As Long
Dim rngUnmatchedInt As Range, rngUnmatchedExt As Range
Setup
t = Timer
With ThisWorkbook
Set ws_rexternal = .Worksheets("Reformat External")
Set ws_rinternal = .Worksheets("Reformat Internal")
Set ws_unmatched = .Worksheets("Unmatched")
Set ws_matched = .Worksheets("Matched")
End With
'clear previous data
ws_unmatched.Cells.Clear
ws_matched.Cells.Clear
'source data ranges
Set rngInt = ws_rinternal.Range("A2:M" & ws_rinternal.Cells(Rows.Count, 2).End(xlUp).Row)
Set rngExt = ws_rexternal.Range("A2:M" & ws_rexternal.Cells(Rows.Count, 2).End(xlUp).Row)
'speed up copy/paste
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'generate all keys for Internal rows in ColT
For Each rw In rngInt.Rows
rw.EntireRow.Columns("T").Value = RowKey(rw)
Next rw
Set rngIntKeys = rngInt.EntireRow.Columns("T") 'range with keys
Debug.Print "Generated keys", Timer - t
rwMatch = 1
For Each rw In rngExt.Rows
If rw.Row Mod 100 = 0 Then Debug.Print "Row: " & rw.Row, Timer - t
m = Application.Match(RowKey(rw), rngIntKeys, 0)
If Not IsError(m) Then 'got match on "internal" sheet?
rwMatch = rwMatch + 1
rw.Copy ws_matched.Cells(rwMatch, "A")
ws_matched.Cells(rwMatch, "N").Value = "Matched"
rngInt.Rows(m).Copy ws_matched.Cells(rwMatch, "P")
rngIntKeys.Cells(m).ClearContents 'remove matched key from T
Else
BuildRange rngUnmatchedExt, rw 'collect unmatched external row
End If
Next rw
Debug.Print "Copied matches", Timer - t
'copy unmatched external
If Not rngUnmatchedExt Is Nothing Then
rngUnmatchedExt.Copy ws_unmatched.Range("A1")
End If
'copy unmatched internal
Set rngIntKeys = rngInt.EntireRow.Columns("T")
For n = 1 To rngExt.Rows.Count
If Len(rngIntKeys.Cells(n).Value) > 0 Then
BuildRange rngUnmatchedInt, rngExt.Rows(n)
End If
Next n
If Not rngUnmatchedInt Is Nothing Then
rngUnmatchedInt.Copy _
ws_unmatched.Cells(ws_unmatched.UsedRange.Rows.Count + 5, 1)
End If
Debug.Print "Copied non-matches", Timer - t
Application.Calculation = xlCalculationAutomatic
End Sub
'generate a "key" by concatenating all cell values in `rng` with "|"
Function RowKey(rng As Range) As String
RowKey = Join(Application.Transpose(Application.Transpose(rng.Value)), "|")
End Function
'build up a range from sub-ranges
Sub BuildRange(ByRef rngTot As Range, rngAdd As Range)
If rngTot Is Nothing Then
Set rngTot = rngAdd
Else
Set rngTot = Application.Union(rngTot, rngAdd)
End If
End Sub
For completeness here's the sub I used to reset the sheets and create sample data:
'reset the sheets and create some sample data
Sub Setup()
Const ROWSN As Long = 1000 '# of rows to create
Const RNDV As String = "=ROUND(rand()*5,0)" 'adjust to change chance of matched rows
Dim ws_rexternal As Worksheet, ws_unmatched As Worksheet
Dim ws_rinternal As Worksheet, ws_matched As Worksheet
With ThisWorkbook
Set ws_rexternal = .Worksheets("Reformat External")
Set ws_rinternal = .Worksheets("Reformat Internal")
Set ws_unmatched = .Worksheets("Unmatched")
Set ws_matched = .Worksheets("Matched")
End With
'clar all sheets
ws_unmatched.Cells.Clear
ws_matched.Cells.Clear
ws_rexternal.Cells.Clear
ws_rinternal.Cells.Clear
'ws_rexternal.Range ("A2:M1000")
With ws_rexternal.Range("A2:C2").Resize(ROWSN)
.Formula = RNDV
.Value = .Value
End With
ws_rexternal.Range("D2:M2").Resize(ROWSN).Value = "blah"
With ws_rinternal.Range("A2:C2").Resize(ROWSN)
.Formula = RNDV
.Value = .Value
End With
ws_rinternal.Range("D2:M2").Resize(ROWSN).Value = "blah"
End Sub

vba to sort the data into matrix form

I have some data, for the first column date, it contains two dates.
Then I have the fund code and the categories, the last column is the categories value.
How shall I put them into matrix format, for example, the categories is horizontal and the value correspond to the fund name and categories and the date.
Following code should be helpful.
Option Explicit
Sub Demo()
With Application
.ScreenUpdating = False 'stop screen flickering
.Calculation = xlCalculationManual 'prevent calculation while execution
End With
Dim i As Long, lastrow As Long, tblLastRow As Long, tblLastColumn As Long
Dim dict As Object
Dim rng As Variant
Dim ws As Worksheet
Dim cel As Range, dateRng, fundCodeRng As Range, categoryRng As Range, valueRng As Range
Set dict = CreateObject("Scripting.Dictionary")
Set ws = ThisWorkbook.Worksheets("Sheet1") 'change Sheet1 to your worksheet
With ws
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row 'get last row with data
'set ranges for date, fund code, category and value to be used later in code
Set dateRng = .Range("A2:A" & lastrow)
Set fundCodeRng = .Range("B2:B" & lastrow)
Set categoryRng = .Range("C2:C" & lastrow)
Set valueRng = .Range("D2:D" & lastrow)
'get unique records for date and fund coding combined together
For i = 2 To lastrow
dict(.Cells(i, 1).Value & "|" & .Cells(i, 2).Value) = dict(.Cells(i, 1).Value & "|" & .Cells(i, 2).Value)
Next
With .Range("F2").Resize(dict.Count) 'date and fund code will be displayed from cell F2
.Value = Application.Transpose(dict.Keys)
.TextToColumns Destination:=.Cells, DataType:=xlDelimited, Other:=True, OtherChar:="|"
.Offset(, 2).Resize(dict.Count).Value = Application.Transpose(dict.Items)
End With
'empty dictionary
dict.RemoveAll
Set dict = Nothing
Set dict = CreateObject("Scripting.Dictionary")
'get unique categories and display as header
rng = .Range("C1:C" & lastrow)
For i = 2 To UBound(rng)
dict(rng(i, 1) & "") = ""
Next
.Range("H1").Resize(1, UBound(dict.Keys()) + 1).Value = dict.Keys 'categories will be displayed from column H
tblLastRow = .Range("F" & Rows.Count).End(xlUp).Row 'get last row in new table
tblLastColumn = Cells(1, Columns.Count).End(xlToLeft).Column 'get last column of category in new table
'display corresponding values for date, fund code and category
For Each cel In .Range(.Cells(2, 8), .Cells(tblLastRow, tblLastColumn)) 'Cells(2, 8) represent Cell("H2")
cel.FormulaArray = "=IFERROR(INDEX(" & valueRng.Address & ",MATCH(1,(" & dateRng.Address & "=" & .Cells(cel.Row, 6) & ")*(" & fundCodeRng.Address & "=""" & .Cells(cel.Row, 7) & """)*(" & categoryRng.Address & "=""" & .Cells(1, cel.Column) & """),0)),"""")"
cel.Value = cel.Value
Next cel
End With
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
See image for reference.
EDIT :
If Fund Code could be numbers also then replace
cel.FormulaArray = "=IFERROR(INDEX(" & valueRng.Address & ",MATCH(1,(" & dateRng.Address & "=" & .Cells(cel.Row, 6) & ")*(" & fundCodeRng.Address & "=""" & .Cells(cel.Row, 7) & """)*(" & categoryRng.Address & "=""" & .Cells(1, cel.Column) & """),0)),"""")"
with
cel.FormulaArray = "=IFERROR(INDEX(" & valueRng.Address & ",MATCH(1,(" & dateRng.Address & "=" & .Cells(cel.Row, 6) & ")*(Text(" & fundCodeRng.Address & ",""0"")=""" & .Cells(cel.Row, 7) & """)*(" & categoryRng.Address & "=""" & .Cells(1, cel.Column) & """),0)),"""")"

ISNUMBER returning #VALUE! error in formula with VBA

This question is building from the solution found here. I wanted to be able to check if the "LowLimit" cell is a number. If it is then carry out equation, else return value from "MeasValue" column. Here is an example of the data set with my current outcome:
As you can see, the 6th data entry calculation gives the wrong calculation. The number LowLimit value of 22 seems to be hard coded in the formula. Can you help me fix this? Thanks.
Here is the code that I have so far:
Sub ReturnMarginal()
'UpdatebySUPERtoolsforExcel2016
Dim xOut As Worksheet
Dim xWb As Workbook
Dim xWks As Worksheet
Dim InterSectRange As Range
Dim lowLimCol As Integer
Dim hiLimCol As Integer
Dim measCol As Integer
Application.ScreenUpdating = False
Set xWb = ActiveWorkbook
For Each xWks In xWb.Sheets
xRow = 1
With xWks
FindString = "LowLimit"
If Not xWks.Rows(1).Find(FindString) Is Nothing Then
.Cells(xRow, 16) = "Meas-LO"
.Cells(xRow, 17) = "Meas-Hi"
.Cells(xRow, 18) = "Min Value"
.Cells(xRow, 19) = "Marginal"
lastRow = .UsedRange.Rows.Count
lowLimCol = Application.WorksheetFunction.Match("LowLimit", xWks.Range("1:1"), 0)
hiLimCol = Application.WorksheetFunction.Match("HighLimit", xWks.Range("1:1"), 0)
measLimCol = Application.WorksheetFunction.Match("MeasValue", xWks.Range("1:1"), 0)
'If IsNumeric(.Cells(2, lowLimCol).Value2) Then
' .Range("P2:P" & LastRow).Formula = "=" & Cells(2, measLimCol).Address(False, False) & "-" & Cells(2, lowLimCol).Address(False, False)
'Else
' .Range("P2:P" & LastRow).Formula = "=" & Cells(2, measLimCol).Address(False, False)
'End If
.Range("P2:P" & lastRow).Formula = "=IF(ISNUMBER(" & .Cells(2, lowLimCol).Value & ")," & Cells(2, measLimCol).Address(False, False) & "-" & Cells(2, lowLimCol).Address(False, False) & "," & Cells(2, measLimCol).Address(False, False) & ")"
.Range("Q2:Q" & lastRow).Formula = "=" & Cells(2, hiLimCol).Address(False, False) & "-" & Cells(2, measLimCol).Address(False, False)
.Range("R2").Formula = "=min(P2,Q2)"
.Range("R2").AutoFill Destination:=.Range("R2:R" & lastRow)
.Range("S2").Formula = "=IF(AND(R2>=-3, R2<=3), ""Marginal"", R2)"
.Range("S2").AutoFill Destination:=.Range("S2:S" & lastRow)
End If
End With
Application.ScreenUpdating = True 'turn it back on
Next xWks
End Sub
I think the main improvement you can make here is to get the column letters for LowLimit, HighLimit and MeasValue once you establish where they are in row 1. Then you can refer to those column letters when you set the .Formula properties.
There is a helpful post on converting column numbers to letters here.
Also, you don't need to auto-fill columns R and S - you can populate in the same way you are doing for columns P and Q.
I updated your code a little - hope it helps:
Option Explicit
Sub ReturnMarginal()
Dim ws As Worksheet
Dim lngLowLimCol As Long, strLowLimCol As String
Dim lngHiLimCol As Long, strHiLimCol As String
Dim lngMeasCol As Long, strMeasCol As String
Dim lngLastRow As Long
Dim wsf As WorksheetFunction
' get worksheetfunction references
Set wsf = Application.WorksheetFunction
' iterate worksheets
For Each ws In ThisWorkbook.Worksheets
' validate LowLimit label is on sheet
If ws.Rows(1).Find("LowLimit") Is Nothing Then Exit Sub
' get location of input data columns and number of rows
lngLowLimCol = wsf.Match("LowLimit", ws.Rows(1), 0)
lngHiLimCol = wsf.Match("HighLimit", ws.Rows(1), 0)
lngMeasCol = wsf.Match("MeasValue", ws.Rows(1), 0)
lngLastRow = ws.Cells(1, lngLowLimCol).End(xlDown).Row
' get column letters for input data columns
strLowLimCol = Split(ws.Cells(1, lngLowLimCol).Address(True, False), "$")(0)
strHiLimCol = Split(ws.Cells(1, lngHiLimCol).Address(True, False), "$")(0)
strMeasCol = Split(ws.Cells(1, lngMeasCol).Address(True, False), "$")(0)
' output headers
ws.Range("P1") = "Meas-LO"
ws.Range("Q1") = "Meas-Hi"
ws.Range("R1") = "Min Value"
ws.Range("S1") = "Marginal"
' assign formulas to outputs
' Meas-LO
With ws.Range("P2:P" & lngLastRow)
.Formula = "=IF(ISNUMBER(" & strLowLimCol & "2)," & _
strMeasCol & "2-" & strLowLimCol & "2," & _
strMeasCol & "2)"
End With
' Meas-Hi
With ws.Range("Q2:Q" & lngLastRow)
.Formula = "=" & strHiLimCol & "2-" & strMeasCol & "2"
End With
' Min Value
With ws.Range("R2:R" & lngLastRow)
.Formula = "=MIN(P2,Q2)"
End With
' Marginal
With ws.Range("S2:S" & lngLastRow)
.Formula = "=IF(AND(R2>=-3,R2<=3),""Marginal"",R2)"
End With
Next 'ws
End Sub
Output:

VBA: Delete one row if values match

I am trying to create a macro that looks for "Total net" and "Program Operation net" in column C. Once located, the macro compares the rows of these two cells and of their values match then row of "Total Net" get deleted.
This is my code so far...
Sub DeletingEmptyPages()
Dim WS As Worksheet
For Each WS In Sheets
Dim Mystring As String
Dim MystringII As String
MystringII = "Total Net"
Mystring = "Program Operating Net"
Dim n As Long
Dim nlast As Long
Dim rw As Range
Set rw = ActiveWorkbook.ActiveSheet.UsedRange.Rows
nlast = rw.count
For n = nlast To 9 Step -1
If (Column(c).Value = MystringII And Column(c).Value = Mystring) Then
rw.Rows(n).Delete
End If
Next n
Next WS
End Sub
I suppose that when both strings exist in column "C", you want to compare if columns "A" and "B" are equal in both rows. You can use the following code and easily adapt it if more columns need to be compared on the matched rows:
Sub Delete_DuplicateTotalNet()
Dim WS As Worksheet, row1 As Long, row2 As Long
For Each WS In Sheets
With WS
On Error Resume Next
row1 = WorksheetFunction.Match("Total Net", .Columns("C"), 0)
row2 = WorksheetFunction.Match("Program Operating Net", .Columns("C"), 0)
If Err.Number <> 0 Then GoTo NextWS
If .Range("A" & row1).Value = .Range("A" & row2).Value And _
.Range("B" & row1).Value = .Range("B" & row2).Value Then
.Rows(row1).Delete
End If
End With
NextWS:
Err.Clear
Next WS
End Sub
This is what it looks like but causes a runtime error
Sub Delete_DuplicateTotalNet()
Dim WS As Worksheet, row1 As Long, row2 As Long, rng As Long
For Each WS In Sheets
On Error GoTo NextWS
With WS
If WS.Visible = xlSheetVisible Then
row1 = WorksheetFunction.Match("Total Net", .Columns(3), 0)
row2 = WorksheetFunction.Match("Program Operating Net", .Columns(3), 0)
If .Range("D" & row1).Value = .Range("D" & row2).Value And _
.Range("E" & row1).Value = .Range("E" & row2).Value And _
.Range("F" & row1).Value = .Range("F" & row2).Value And _
.Range("G" & row1).Value = .Range("G" & row2).Value And _
.Range("H" & row1).Value = .Range("H" & row2).Value And _
.Range("I" & row1).Value = .Range("I" & row2).Value And _
.Range("J" & row1).Value = .Range("J" & row2).Value And _
.Range("K" & row1).Value = .Range("K" & row2).Value Then
.Rows(row1).Delete
End If
End If
End With
NextWS:
Err.Clear
Next WS
End Sub

How to increase only last digit of a serial number string in Excel VBA?

I'm new to vba and trying to write a barcode scanner algorithm. It works fine right now but I want to keep serial numbers in my exel table and their structure has to be like "A151000". I want with each barcode entered a cell with an inputbox also be assigned to a serial number. for example when a new entry(Barcode) written in column C I want in column B serial numbers last digit increased by 1 and stored in that cell automatically.
Right now I can drag the cell from corner and exel increases the last digit. How can I trigger this with new entries automatically? Thanks in advance.
A151000
A151001
A151002
...
Sub DataInput()
Dim SearchTarget As String
Dim myRow As Long
Dim Rng As Range
Static PrevCell As Range
Dim FoundCell As Range
Dim CurCell As Range
Dim a As String
Dim Target As Range
Dim buttonclick As Boolean
V = True
If PrevCell Is Nothing Then
myRow = Selection.Row
Set PrevCell = Range("C" & myRow)
End If
Set Rng = Range("C:C,C:C") 'Columns for search defined here
With Rng
Set FoundCell = .Cells.Find(What:=SearchTarget, _
After:=PrevCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=True)
End With
Dim Eingabezahl As String
Do While Eingabezahl! = ""
Eingabezahl = InputBox("Last barcode scanned" & " " & Eingabezahl)
Range("C" & Range("C" & Rows.Count).End(xlUp).Row + 1) = Eingabezahl
Range("D" & Range("D" & Rows.Count).End(xlUp).Row + 1) = Now()
Range("E" & Range("E" & Rows.Count).End(xlUp).Row + 1) = "VALID"
Loop
End Sub
TO use the Autofill function and not change your original code you could just add in the autofill in your sub:
Dim Eingabezahl As String
Dim rngLastBCell As Range
Do While Eingabezahl = ""
Eingabezahl = InputBox("Last barcode scanned" & " " & Eingabezahl)
Set rngLastBCell = Range("B" & Rows.Count).End(xlUp)
rngLastBCell.AutoFill Destination:=Range(rngLastBCell, rngLastBCell.Offset(1)), Type:=xlFillDefault
Range("C" & Range("C" & Rows.Count).End(xlUp).Row + 1) = Eingabezahl
Range("D" & Range("D" & Rows.Count).End(xlUp).Row + 1) = Now()
Range("E" & Range("E" & Rows.Count).End(xlUp).Row + 1) = "VALID"
Loop
Or you could use the following that using the same concept (an autofill) but condenses al of your calls to the worksheet into a single line:
Dim Eingabezahl As String
Dim rngLastBCell As Range
Do While Eingabezahl = ""
Eingabezahl = InputBox("Last barcode scanned" & " " & Eingabezahl)
Set rngLastBCell = Range("B" & Rows.Count).End(xlUp)
rngLastBCell.AutoFill Destination:=Range(rngLastBCell, rngLastBCell.Offset(1)), Type:=xlFillDefault
rngLastBCell.Offset(1, 1).Resize(, 3) = Array(Eingabezahl, Now(), "VALID")
Loop
Although I would recommend just using appenending the current row to the end of your serial and not making as many calls to the worksheet by using an array:
Dim rngB As Range
Dim Eingabezahl As String
Dim SerialBase As String
SerialBase = "A15100"
Do While Eingabezahl = ""
Eingabezahl = InputBox("Last barcode scanned" & " " & Eingabezahl)
Set rngB = Range("B" & Rows.Count).End(xlUp).Offset(1)
rngB.Resize(, 4).Value = Array(SerialBase & rngB.Row, Eingabezahl, Now(), "VALID")
Loop