I have written a script that simplifies a spreadsheet, but I need help with dynamically populating fields. The current format of the spreadsheet has inconsistent spacing so it is difficult to put together and if then statement that populates only populates subsections of a document.
I have attached an of the way the document looks.
What I am trying to do is populate the Highlighted fields on the left based on the highlighted field on the right. e.g. (When Field "F3" populated - If "2012" and "092000" then populate BBFY with "2012" from cell "F2" in cells "A4" to "A11" Stop at last BOC number".) Start same process at next process with next group of data. Then if there is new data for the BOC name 2013 092300, fill in the corresponding information based on that information.
I am just having trouble trying to identify the correct calls to many changes are making it difficult to tell the code to change values based on new parameters. As you can see the highlighted values in F change and thus change the related information below. I have blocked out where I am trying to start up this section of the code.
The code I have so far gets me to the layout you see below. In addition I am trying to make a new worksheet based off of each section, but I will try to tackle that another time.
Sub SOFCMacro()
'Begins Macro Optimizations
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
'Declarations
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim rng As Range
'Renames Sheet1 and Make It an Object
Set Main = ActiveSheet
Main.Name = "BAR"
'Add and Name Worksheets
Set WS1 = Sheets.Add
WS1.Name = "SOFC"
'Clear Formatting
Sheets("BAR").Activate
With ActiveSheet
.Cells.ClearFormats
End With
***'Comma Diliminate Funding Information
Sheets("Bar").Activate
With ActiveSheet
Set rng = .Range(rng, .Cells(.Rows.Count, rng.Column).End(xlUp))
For i = Last To 1 Step -1
If Not IsError(.vaule) Then
ElseIf (cells(i, "F").value = "092000:" and "Salaries:" Then cells(Cells, i, "A").value = (Cells(i, "F").Value) Like "20*"
ElseIf .value = "092300:" and "Defender:" Then cells(Cells, i, "A").value = (Cells(i, "F").Value) Like "20*"
ElseIf .value = "51140X:" and "Judiciary:" Then cells(Cells, i, "A").value = (Cells(i, "F").Value) Like "20*"
ElseIf .value = "51140E:" and "Electronic:" Then cells(Cells, i, "A").value = (Cells(i, "F").Value) Like "20*"
End if
End With***
'Copies Columns from Budget Availability Reports to SOFC Worksheet
Sheets("BAR").Columns(1).Copy Destination:=Sheets("SOFC").Columns(4)
Sheets("BAR").Columns(2).Copy Destination:=Sheets("SOFC").Columns(5)
Sheets("BAR").Columns(3).Copy Destination:=Sheets("SOFC").Columns(6)
Sheets("BAR").Columns(4).Copy Destination:=Sheets("SOFC").Columns(7)
'Deletes "Main Worksheet"
Sheets("BAR").Delete
'Inserts Header Row
Sheets("SOFC").Range("A2").EntireRow.Insert
'Add Headers to Sheet
Sheets("SOFC").Range("A1").Value = "BBFY"
Sheets("SOFC").Range("B1").Value = "EBFY"
Sheets("SOFC").Range("C1").Value = "FUND"
Sheets("SOFC").Range("D1").Value = "BUDGET ORG"
Sheets("SOFC").Range("E1").Value = "BOC"
Sheets("SOFC").Range("F1").Value = "BOC Name"
Sheets("SOFC").Range("G1").Value = "ALLOTMENT"
'Deletes Unneeded Rows
Sheets("SOFC").Activate
With ActiveSheet
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
For Lrow = Lastrow To Firstrow Step -1
With .Cells(Lrow, "D")
If Not IsError(.Value) Then
ElseIf .Value = "Activity Type:" Then .EntireRow.Delete
ElseIf .Value = "Activity:" Then .EntireRow.Delete
ElseIf .Value = "AO Division:" Then .EntireRow.Delete
End If
End With
Next Lrow
End With
'Deletes Rows Based On Criteria
Last = Cells(Rows.Count, "D").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "D").Value) = "Fund:" Then
'Cells(i, "A").EntireRow.ClearContents ' USE THIS TO CLEAR CONTENTS BUT NOT DELETE ROW
ElseIf (Cells(i, "D").Value) = "Activity Type:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "D").Value) = "Activity:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "D").Value) = "AO Division:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "D").Value) = " Org Code" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "Org Code Subtotal:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "AO Division Subtotal:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "Activity Subtotal:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "Activity Type Subtotal:" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "Fund Subtotal:" Then
Cells(i, "A").EntireRow.Delete
'Change Values for Courts in Current Wave
ElseIf (Cells(i, "F").Value) = "ARW - Arkansas Western" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "CAN - California Northern" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "GAS - Georgia Southern" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "MDX - Maryland" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "NDX - North Dakota" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "NYE - New York Eastern" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "ORX - Oregon" Then
Cells(i, "A").EntireRow.Delete
ElseIf (Cells(i, "F").Value) = "SDX - South Dakota" Then
Cells(i, "A").EntireRow.Delete
'Change Values for Courts in Current Wave
ElseIf (Cells(i, "F").Value) = "" Then
Cells(i, "A").EntireRow.Delete
Else
End If
Next i
'Gets BBFY and Fund and Place Values in Correct Columns
'Last = Cells(Rows.Count, "D").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "D").Value) = "Fund:" Then
ElseIf (Cells(i, "F").Value) Like "20*" Then
YearYo = Left(Cells(i, "20*"), 4)
If Date Like "20*" Then
Cells(i, "A").Value = Date
End If
Else
End If
Next i
'Gets Leading 0 for Fund Code
Columns("C:C").Select
Selection.NumberFormat = "000000"
End Sub
One suggestion, if your spreadsheet is consistent in the BOC column, then maybe that's the best place to start.
Dim i as Integer
Dim j as Integer
Dim LR as Long
LR = Cells(Sheets("NAME").Columns(6).Rows.Count, 1).End(xlUp).Row
For j = 1 to LR
For i = 1 to 3
If Cells(j,i)/Value="" Then
Cells(j,i).Formula= 'come up with reference for the BOC Name
Else:
End If
Next i
Next j
It's not perfect and could probably be done better with a For Each (I'm not very good with those), but it could be at least a start. This option doesn't find dynamic ranges to fill in the blank (e.g. dynamically define the big yellow block of squares and paste into them). It just loops through all cells in the first 3 rows, til the end of the last row (used column F (Columns(6)) as is seems to be your only fully filled column).
If you want more specific to what goes into each cell:
Dim i as Integer
Dim LR as Long
LR = Cells(Sheets("NAME").Columns(6).Rows.Count, 1).End(xlUp).Row
For i = 1 to LR
If Cells(i,1)/Value="" Then
Cells(i,1).Formula= "=Left(REF,4)'come up with reference for the BOC Name
Cells(i,2).Formula= "=Left(Right(REF,6),11)
Cells(i,3).Formula= "=Right(REF,3)
Else:
End If
Next i
Related
I am very much a novice with VBA but i have managed to write code that runs. My issue is that when i run it with many thousands of rows it basically grinds to a halt and nothing happens for well over an hour (when i run for 150K rows). On top of my code i have added:
I have also attempted to avoid using .select whenever i could. Is there anything that i'm missing or is there a way that i could improve my code? Since i've pasted various code i'm sure i've done something wrong.
Sub Eng11()
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Dim Last As Long
Dim i As Long
Dim wkb1 As Workbook
Dim sht1 As Worksheet
Dim wkb2 As Workbook
Dim sht2 As Worksheet
Dim lastrow As Long
Dim sPath As String, sFile As String
Dim wb As Workbook
Dim x As Long
Dim ws As Worksheet
sPath = "C:\Users\nascd\Downloads\Pronto Master\"
sFile = sPath & Sheets("Sheet 1").Range("J2").Text
Set wkb1 = ThisWorkbook
Set wkb2 = Workbooks.Open(sFile)
Set sht1 = wkb1.Sheets("Data Table")
Set sht2 = wkb2.Sheets("Sheet1")
Set ws = sht2
Last = Cells(Rows.Count, "AX").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "AZ").Text) = (Cells(i, "AB").Text) And _
(Cells(i, "BA").Text) = (Cells(i, "AC").Text) And _
(Cells(i, "AY").Text) = "C" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
Next i
For i = Last To 2 Step -1
If (Cells(i, "AZ").Text) = (Cells(i, "AB").Text) And _
(Cells(i, "BA").Text) = (Cells(i, "AC").Text) And _
(Cells(i, "AY").Text) = "C" And (Cells(i, "AA").Text) = "T" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
Next i
For i = Last To 2 Step -1
If (Cells(i, "AY").Text) = "1" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
Next i
For i = Last To 2 Step -1
If (Cells(i, "AY").Text) = "2" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
Next i
End Sub
I think that this is as condensed as I can make it. Certainly some logic magician could come in and make this shorter but I think they might not be able to fit the if logic onto a single line!
This will only loop once, which should have been your biggest obstacle in terms of time to run. I made sure to specify that you're searching in sht2, removed some unused variables, and made sure to reset your application settings at the end of the sub. Other than that, the only thing I really did was combine your if statements as best as I could and put them into one loop.
Sub Eng11()
With Application
.DisplayAlerts = False
.AskToUpdateLinks = False
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
Dim sht1 As Worksheet
Set sht1 = ThisWorkbook.Sheets("Data Table")
Dim sPath As String
sPath = "C:\Users\nascd\Downloads\Pronto Master\"
Dim sFile As String
sFile = sPath & sht1.Range("J2").Value2
Dim sht2 As Worksheet
Set sht2 = Workbooks.Open(sFile).Sheets(1)
Dim lastRow As Long
lastRow = sht2.Cells(Rows.count, "AX").End(xlUp).row
Dim i As Long
For i = 2 To lastRow
With sht2
If .Cells(i, "AZ").Value2 = .Cells(i, "AB").Value2 And _
.Cells(i, "BA").Value2 = .Cells(i, "AC").Value2 Then
If .Cells(i, "AY").Value2 = "C" And _
(.Cells(i, "AA").Value2 = "E" Or .Cells(i, "AA").Value2 = "T") Then
.Cells(i, "AX").Value2 = .Cells(i, "Z").Value2
.Cells(i, "AY").Value2 = .Cells(i, "AA").Value2
.Cells(i, "AZ").Value2 = .Cells(i, "AB").Value2
.Cells(i, "BA").Value2 = .Cells(i, "AC").Value2
End If
ElseIf .Cells(i, "AA").Value2 = "E" And _
(.Cells(i, "AY").Value2 = 2 Or .Cells(i, "AY").Value2 = 1) Then
.Cells(i, "AX").Value2 = .Cells(i, "Z").Value2
.Cells(i, "AY").Value2 = .Cells(i, "AA").Value2
.Cells(i, "AZ").Value2 = .Cells(i, "AB").Value2
.Cells(i, "BA").Value2 = .Cells(i, "AC").Value2
End If
End With
Next i
With Application
.DisplayAlerts = True
.AskToUpdateLinks = True
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
Sub Eng11()
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Dim Last As Long
Dim i As Long
Dim wkb1 As Workbook
Dim sht1 As Worksheet
Dim wkb2 As Workbook
Dim sht2 As Worksheet
Dim lastrow As Long
Dim sPath As String, sFile As String
Dim wb As Workbook
Dim x As Long
Dim ws As Worksheet
sPath = "C:\Users\nascd\Downloads\Pronto Master\"
sFile = sPath & Sheets("Sheet 1").Range("J2").Text
Set wkb1 = ThisWorkbook
Set wkb2 = Workbooks.Open(sFile)
Set sht1 = wkb1.Sheets("Data Table")
Set sht2 = wkb2.Sheets("Sheet1")
Set ws = sht2
Last = Cells(Rows.Count, "AX").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "AZ").Text) = (Cells(i, "AB").Text) And _
(Cells(i, "BA").Text) = (Cells(i, "AC").Text) And _
(Cells(i, "AY").Text) = "C" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
If (Cells(i, "AZ").Text) = (Cells(i, "AB").Text) And _
(Cells(i, "BA").Text) = (Cells(i, "AC").Text) And _
(Cells(i, "AY").Text) = "C" And (Cells(i, "AA").Text) = "T" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
If (Cells(i, "AY").Text) = "1" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
If (Cells(i, "AY").Text) = "2" And (Cells(i, "AA").Text) = "E" Then
Cells(i, "AX").Value = Cells(i, "Z").Value
Cells(i, "AY").Value = Cells(i, "AA").Value
Cells(i, "AZ").Value = Cells(i, "AB").Value
Cells(i, "BA").Value = Cells(i, "AC").Value
End If
Next i
End Sub
Can you pardon to let me the know the difference of last two Ifs as the function is same for both ifs condition.
I have written basic Excel macro for filtering data which kinda worked OK. But I struggle with deleting rows, if column F does not start with "BE". In column F there are ISINs for commercial papers and first two letter are country code, followed by few numbers. There is also header.
If you are interested, here is the procedure for what the macro should do:
Delete row 1 and 2
Sort by Pay date (PD): (oldest to newest)
Withhold the events (rows) with specific pay date (column L)
Withhold in column H everything that are not these:
Shares
Shares limited Partnership
Shares Fractions
Funds
Certificates ADR
Certificates
Investment funds BE dividend
Investment funds BE capitalization
Pre-emptive right
Mortage certificates
Sort by ISIN code: A to Z (column F)
Withhold everything else than "BE" in column F
My current code looks like this.
Sub Paycheck()
'Delete first two rows
Rows(2).EntireRow.Delete
Rows(1).EntireRow.Delete
' Restore screen updating and events
Application.ScreenUpdating = False
Application.EnableEvents = False
' DELETES ALL ROWS FROM A2 DOWNWARDS WITH THE WORDs IN COLUMN H
' USE THIS TO CLEAR CONTENTS BUT NOT DELETE ROW "Cells(i, "A").EntireRow.ClearContents"
Last = Cells(Rows.Count, "H").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "H").Value) <> "SHARES" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Shares limited Partnership" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Shares Fractions" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Funds" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Certificates ADR" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Certificates" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Investment funds BE dividend" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Investment funds BE capitalization" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Pre-emptive right" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Mortgage certificates" Then
Cells(i, "A").EntireRow.Delete
End If
' Deleting other than BE
If (Mid(cell(i, "F").Value, 0, 2) <> "BE") Then
Cells(i, "A").EntireRow.Delete
End If
Next i
' This will clear dates which are not today
Last = Cells(Rows.Count, "L").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "L").Value) < Date Then
Cells(i, "A").EntireRow.Delete
End If
Next i
Last = Cells(Rows.Count, "L").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "L").Value) > Date Then
Cells(i, "A").EntireRow.Delete
End If
Next i
'Order the table ascending
Selection.AutoFilter
ActiveWorkbook.Worksheets("Events").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Events").AutoFilter.Sort.SortFields.Add Key:=Range _
("F:F"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Events").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Selection.AutoFilter
End Sub
As you can see approx in middle of the code, I tried to use basic "if" function with "mid". But I think I got it wrong (because it does not work). I even tried some other codes I have found (I am beginner and I am looking around internet for solutions).
What I have tried or found and did not work. For example:
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ActiveWorkbook.Sheets("Events")
lastRow = ws.Range("F" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("F1:F" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter Field:=1, Criteria1:="<>*BE*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
I also found some loop code, which also did not worked (and took a lot of time, we are talking about thousands of rows I need to filter). Currently I am in situation when even the code that worked before, does not work anymore (because I somewhere fucked up) so I would really like your advice, how to make this work according to the procedure mentioned above.
I would be very grateful!
Thank you for your time
Try this..this code simple skip the row which has value start with BE in Column F
Note: not tested
Last = Cells(Rows.Count, "H").End(xlUp).Row
For i = Last To 1 Step -1
' If Column F values starts with BE then skip the row
If Cells(i, "F").Value = "BE*" Then
GoTo nextline:
End If
If (Cells(i, "H").Value) <> "SHARES" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Shares limited Partnership" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Shares Fractions" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Funds" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Certificates ADR" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Certificates" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Investment funds BE dividend" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Investment funds BE capitalization" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Pre-emptive right" Then
Cells(i, "A").EntireRow.Delete
End If
If (Cells(i, "H").Value) <> "Mortgage certificates" Then
Cells(i, "A").EntireRow.Delete
End If
nextline:
Next i
' This will clear dates which are not today
Last = Cells(Rows.Count, "L").End(xlUp).Row
For i = Last To 2 Step -1
If Cells(i, "F").Value = "BE*" Then
GoTo nextline1:
End If
If (Cells(i, "L").Value) < Date Then
Cells(i, "A").EntireRow.Delete
End If
nextline1:
Next i
Last = Cells(Rows.Count, "L").End(xlUp).Row
For i = Last To 2 Step -1
If Cells(i, "F").Value = "BE*" Then
GoTo nextline2:
End If
If (Cells(i, "L").Value) > Date Then
Cells(i, "A").EntireRow.Delete
End If
nextline2:
Next i
The following script selects a range of data on one sheet and transfers the selection to another sheet.
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For i = 6 To LastRow
If Cells(i, 1) <> "" And Cells(i, 21) = "OK" And Cells(i, 22) <> "Yes" Then
Range(Cells(i, 1), Cells(i, 4)).Select
Selection.Copy
erow = Worksheets("iForms").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Worksheets("iForms").Cells(erow, 1).PasteSpecial Paste:=xlPasteValues
If Cells(i, 1) <> "" Then Cells(i, 22).Value = "Yes"
If Cells(i, 22) <> "" Then Cells(i, 23).Value = Now
If Cells(i, 23) <> "" Then Cells(i, 24).Value = Environ("UserName")
ActiveWorkbook.Save
End If
Next i
I would now like to introduce a script which will replace the row of data on the target sheet if the value in column A already exists, but i'm not sure how to achieve this, any help is much appreciated.
Thank you in advance.
Public Function IsIn(li, Val) As Boolean
IsIn = False
Dim c
For Each c In li
If c = Val Then
IsIn = True
Exit Function
End If
Next c
End Function
dim a: a= range(destWB.sheet(whatever)..range("A1"),destWB.Range("A" & destWB.sheet(whatever).Rows.Count).End(xlUp)).value
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For i = 6 To LastRow
if isin(a, Cells(i, 1) ) then
do whatever you want
else
If Cells(i, 1) <> "" And Cells(i, 21) = "OK" And Cells(i, 22) <> "Yes" Then
Range(Cells(i, 1), Cells(i, 4)).Select
Selection.Copy
erow = Worksheets("iForms").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Worksheets("iForms").Cells(erow, 1).PasteSpecial Paste:=xlPasteValues
If Cells(i, 1) <> "" Then Cells(i, 22).Value = "Yes"
If Cells(i, 22) <> "" Then Cells(i, 23).Value = Now
If Cells(i, 23) <> "" Then Cells(i, 24).Value = Environ("UserName")
ActiveWorkbook.save
End If
End If
Next i
I suggest using a Dictionary-Object which is most likely a Hash-Map. The advantage is that you can use the built in method Dictionary.Exists(Key) to check if the Dictionary already holds the specified value (Key).
Also you should not save the Workbook in every step of the iteration. It would be better (and faster) to only save the workbook after completing the copying of your whole data.
Additionally your If-Tests after copy-paste are not neccessary, because you are already checking for Cells(i,1)<>"" before copying so you don't have to check this again as it does not change.
The following code shows how to get your desired result:
Set dict = CreateObject("Scripting.Dictionary")
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For i = 6 To LastRow
If Cells(i, 1) <> "" And Cells(i, 21) = "OK" And Cells(i, 22) <> "Yes" Then
If dict.Exists(Cells(i,1).Value) Then
'value already exists -> update row number
dict.Item(Cells(i,1).Value)=i
Else
'save value of column A and row number in dictionary
dict.Add Cells(i,1).Value, i
End If
Cells(i, 22).Value = "Yes"
Cells(i, 23).Value = Now
Cells(i, 24).Value = Environ("UserName")
End If
Next i
'finally copy over your data (only unique values)
For Each i In dict.Items
Range(Cells(i, 1), Cells(i, 4)).Select
Selection.Copy
erow = Worksheets("iForms").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Worksheets("iForms").Cells(erow, 1).PasteSpecial Paste:=xlPasteValues
Next i
I am new here.
I am trying to build a quick VBA program to "flatten" a Bill of Materials by heirarchy (BOM Level) and Status.
Here is some sample data:
The sample data shows a BOM with a Car as a top level assembly, Wheel and Engine as second level assemblies, and various children parts that make up those assemblies on the third and fourth level of the BOM.
I want to delete any rows that have the value "ZE", "ZM", or blank in column C.
I also want to delete any rows that have the value "ZA" and are also direct children of another "ZA" item. (Example - Delete the Rim row from the BOM because the Wheel is the Parent "ZA" item)
Here is what I have so far:
Sub deletechildren()
Dim lr As Long, i As Long, k As Long
lr = Cells(Rows.Count, 1).End(xlUp).Row
For i = lr To 1 Step -1
If i > 2 Then
k = i - 1
End If
If Cells(i, 3).Value = "ZA" And Cells(i, 1).Value = Cells(k, 1).Value Then
Cells(i, 3).EntireRow.Delete
ElseIf Cells(i, 3).Value = "ZE" Then
Cells(i, 3).EntireRow.Delete
ElseIf Cells(i, 3).Value = "ZM" Then
Cells(i, 3).EntireRow.Delete
ElseIf Cells(i, 3).Value = "" Then
Cells(i, 3).EntireRow.Delete
End If
Next i
lr = Cells(Rows.Count, 1).End(xlUp).Row
End Sub
I am getting some error on the first part of the If statement, where I want to parse out any "ZA" status children from the "ZA" parent.
Any ideas?
Sub DeleteChildren()
Dim lastRow As Long
Dim i As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
If (Cells(i, 3).Value = "ZE" Or Cells(i, 3).Value = "ZM" Or Cells(i, 3).Value = "") And Cells(i, 1) <> "" Then
Rows(i).EntireRow.Delete xlShiftUp
i = i - 1
GoTo NextIteration
End If
If Cells(i, 1).Value > 1 Then
If (Cells(i, 3).Value = "ZA" And Cells(i - 1, 3).Value = "ZA") And Not Cells(i, 1).Value < Cells(i - 1, 1).Value Then ' This way is a there are multiple levels with "ZA" there can
Cells(i, 5).Value = "Delete"
End If
End If
NextIteration:
Next i
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastRow
If Cells(i, 5).Value = "Delete" Then
Rows(i).EntireRow.Delete xlShiftUp
i = i - 1
End If
Next i
End Sub
A part of the problem is that the variable k is not being used to correctly identify parent/children relationships (if I understand your requirements correctly). In your case, you are comparing the each value with the row above it, but in a bill of materials, the parent row might be multiple rows above, and is denoted by a hierarchy value - 1.
See my revised code below. In the code, we first delete any rows that we know to delete (ZM, ZE, and Blanks). Next, we loop up the hierarchy values until we find one hierarchy value above the current row. That becomes the parent row, and from there, we test.
Let me know if you need additional help.
Sub deletechildren()
Dim lr As Long, i As Long, k As Long
lr = Cells(Rows.Count, 1).End(xlUp).Row
For i = lr To 1 Step -1
If i > 2 Then
k = i - 1
If Cells(i, 3) = "ZE" Or Cells(i, 3) = "ZM" Or Cells(i, 3) = "" Then
Rows(i).Delete
Else
k = i - 1
Do Until i <= 2 Or (Cells(i, 1) - Cells(k, 1) = 1)
k = k - 1
Loop
'Now, k represents the parent row.
If Cells(i, 3) = "ZA" And Cells(k, 3) = "ZA" Then
Rows(i).Delete
End If
End If
End If
Next i
lr = Cells(Rows.Count, 1).End(xlUp).Row
End Sub
I'd use Autofilter() and Sort() methods of Range object like follows:
Option Explicit
Sub deletechildren()
Dim i As Long
With Worksheets("BOM")
With .Range("A1:D" & .Cells(.Rows.Count, 1).End(xlUp).Row)
.AutoFilter Field:=3, Criteria1:=Array("ZE", "ZM", "="), Operator:=xlFilterValues
With .Offset(1).Resize(.Rows.Count - 1)
If Application.WorksheetFunction.Subtotal(103, .Columns(1)) > 1 Then .SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
.AutoFilter
.Sort key1:=Range("C1"), order1:=xlAscending, key2:=Range("A1"), order2:=xlAscending, Header:=xlYes
i = .Rows(.Rows.Count).Row
Do Until .Cells(i, 1) = .Cells(2, 1)
i = i - 1
Loop
If i < .Rows.Count Then .Rows(i + 1).Resize(.Rows.Count - i).EntireRow.Delete
End With
End With
End Sub
I have a text file, that when I import into excel looks like this:
I've been trying to do the following:
Column A is the controller.
When a number above "97" appears in Col A I want to delete it.
I only want to let the first row of "1's" remain.
For every "2" that appears, I firstly want to copy the value in Col B in the "2" row, and paste it over every "3" until I hit the next "2".
Then I'd like to delete the Row's with "2".
So eventually the file should look like:
What I've got so far is:
Sub Deleterow97()
'Macro to format text file to readable format for client
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "A").Value) = "97" Then
Cells(i, "A").EntireRow.Delete
End If
Next i
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "A").Value) = "98" Then
Cells(i, "A").EntireRow.Delete
End If
Next i
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step -1
If (Cells(i, "A").Value) = "99" Then
Cells(i, "A").EntireRow.Delete
End If
Next i
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "A").Value) = "1" Then
Cells(i, "A").EntireRow.Delete
End If
Next i
Dim CellValue As String
Dim RowCrnt As Integer
Dim RowMax As Integer
With Sheets("Sheet1") ' Replace Sheet1 by the name of your sheet
RowMax = .Cells(Rows.Count, "B").End(xlUp).Row
For RowCrnt = 1 To RowMax
If .Cells(RowCrnt, 1) = "2" Then
.Range("A:A").Replace What:="3", Replacement:=.Cells(RowCrnt, 2), LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End If
Next
Last = Cells(Rows.Count, "A").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "A").Value) = "2" Then
Cells(i, "A").EntireRow.Delete
End If
Next i
End With
End Sub
When the replace function copies the value in Col B for every "2" in Col A it then pastes over every 3 with a number that looks like: 1.11111110+28
You don't need to loop so many times as you can use an OR in 1 loop and you don't need those variables for a one off thing really, This doesn't fix your problem but here is a much shorter and easier to manage version of your code:
I put a couple of comments in where I am not sure what it is supposed to do.
Sub Deleterow97()
'Macro to format text file to readable format for client
For i = Cells(Rows.Count, "A").End(xlUp).Row To 1 Step -1
If Cells(i, "A").Value = "97" Or Cells(i, "A").Value = "98" Or Cells(i, "A").Value = "99" Or Cells(i, "A").Value = "1" Then Cells(i, "A").EntireRow.Delete
Next i
With Sheets("Sheet1") ' Replace Sheet1 by the name of your sheet
For RowCrnt = 1 To .Cells(Rows.Count, "B").End(xlUp).Row
If .Cells(RowCrnt, 1) = "2" Then .Range("A:A").Replace What:="3", Replacement:=.Cells(RowCrnt, 2), LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Next
For i = Cells(Rows.Count, "A").End(xlUp).Row To 2 Step -1 'I am not sure why this is in the WITH, should it be .Cells??
If Cells(i, "A").Value = "2" Then Cells(i, "A").EntireRow.Delete 'See above comment Also don't use brackets around the cells(blahblah) in the If, you don't need them
Next i
End With
End Sub