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
Related
What I'm trying to do is remove any rows where a cell value in a specific column matches what is defined to remove. After that is done re-sequence the value in another column by group.
Using the example below:
I want to look at column B and remove any rows that have a value of A or C. Then I want to basically renumber after the dot (.) in column A to reset itself.
Before Macro Code Fig. 1
After value A and C are removed Fig. 2
Final list after column A is renumbered Fig. 3
I figured out how to remove the rows using this code, but stuck on what to do next:
Sub DeleteRowBasedOnCriteriga()
Dim RowToTest As Long
For RowToTest = Cells(Rows.Count, 2).End(xlUp).Row To 2 Step -1
With Cells(RowToTest, 2)
If .Value = "A" Or .Value = "C" _
Then _
Rows(RowToTest).EntireRow.Delete
End With
Next RowToTest
End Sub
This will be easier to do looping from the top down (using step 1 instead of step -1). I've tried to stay true to your original coding and made this:
Sub DeleteRowBasedOnCriteriga()
Dim RowToTest As Long
Dim startRow As Long
Dim i As Integer
startRow = 2
'Clear the rows that have "A" or "C" in column B
For RowToTest = Cells(Rows.Count, 1).End(xlUp).Row to startRow To Step -1
With Cells(RowToTest, 2)
If .Value = "A" Or .Value = "C" _
Then _
Rows(RowToTest).EntireRow.Delete
End With
Next RowToTest
'If the left 3 characters of the cell above it are the same,_
'then increment the renumbering scheme
For RowToTest = startRow To Cells(Rows.Count, 1).End(xlUp).Row
If Left(Cells(RowToTest, 1).Value, InStr(1, Cells(RowToTest, 1), "\")) = Left(Cells(RowToTest, 1).Offset(-1, 0).Value, InStr(1, Cells(RowToTest, 1), "\")) Then
i = i + 1
Cells(RowToTest, 1).Value = Left(Cells(RowToTest, 1).Value, InStr(1, Cells(RowToTest, 1), ".")) & i
Else
i = 0
Cells(RowToTest, 1).Value = Left(Cells(RowToTest, 1).Value, InStr(1, Cells(RowToTest, 1), ".")) & i
End If
Next RowToTest
End Sub
EDIT: I've updated it to compare all of the string before the backslash and compare using that.
EDIT++: It has been brought to my attention that when deleting rows it is better to work from the bottom up (step -1) to ensure every row is accounted for. I've re-implemented the original steps in the first code.
Admittedly, this isn't probably the most efficient, but it should work.
Sub DeleteRowBasedOnCriteriga()
Dim RowToTest As Long, i As Long
Application.ScreenUpdating = False
For RowToTest = Cells(Rows.Count, 2).End(xlUp).Row To 2 Step -1
With Cells(RowToTest, 2)
If .Value = "A" Or .Value = "C" Then Rows(RowToTest).EntireRow.Delete
End With
Next RowToTest
Dim totalRows As Long
totalRows = Cells(Rows.Count, 1).End(xlUp).Row
Dim curCelTxt As String, aboveCelTxt As String
For i = totalRows To i Step -1
If i = 1 Then Exit For
curCelTxt = Left(Cells(i, 1), WorksheetFunction.Search("\", Cells(i, 1)))
aboveCelTxt = Left(Cells(i - 1, 1), WorksheetFunction.Search("\", Cells(i - 1, 1)))
If curCelTxt = aboveCelTxt Then
Cells(i, 1).Value = ""
Else
Cells(i, 1).Value = WorksheetFunction.Substitute(Cells(i, 1), Right(Cells(i, 1), Len(Cells(i, 1)) - WorksheetFunction.Search(".", Cells(i, 1))), "0")
End If
Next i
Dim rng As Range, cel As Range
Dim tempLastRow As Long
Set rng = Range("A1:A" & Cells(Rows.Count, 2).End(xlUp).Row)
For Each cel In rng
If cel.Offset(1, 0).Value = "" Then
tempLastRow = cel.End(xlDown).Offset(-1, 0).Row
If tempLastRow = Rows.Count - 1 Then
tempLastRow = Cells(Rows.Count, 2).End(xlUp).Row
cel.AutoFill Destination:=Range(cel, Cells(tempLastRow, 1))
Exit For
Else
cel.AutoFill Destination:=Range(cel, Cells(tempLastRow, 1))
End If
End If
Next cel
Application.ScreenUpdating = True
End Sub
Mainly, I discovered that you can use AutoFill to fix the last number in the string. Meaning if you AutoFill this text, CAT\Definitions.0 down, you get the number updating as you drag/fill.
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
I'm new to macro's and need to the following on 1,000+ line sheet:
I have a sheet and and i need to duplicate every other row and then modified the new rows.
to duplicate the additional row i run this macro:
Sub CopyRows()
Dim LR As Long
Dim i As Long
LR = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For i = LR To 2 Step -1
Rows(i).Copy
Range(Rows(i + 1), Rows(i + 1)).Insert Shift:=xlDown
Application.CutCopyMode = False
Next i
End Sub
There are two additional operations I need to do on every other row after the header row.
Operation 1:
In columns B and C I need to replace the text with "data for B" and "Data for C" the text is static for each replacement.
Operation 2:
I need to cut the data in Column H and paste it in column I.
Any help in doing this Macro would be appreciated.
This is in Excel 2016
My final solution thanks to #MortenAnthonsen his solution gave me what I needed to work the following out:
Sub myMaker()
Dim LR As Long
Dim i As Long
LR = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For i = LR To 2 Step -1
Rows(i).Copy
Range(Rows(i + 1), Rows(i + 1)).Insert Shift:=xlDown
Application.CutCopyMode = False
Next i
For i = 3 To Cells(2, 2).End(xlDown).Row Step 2
Cells(i, 2).Value = "B Data"
Cells(i, 3).Value = "C Data"
Range("H" & i).Select
Selection.Cut
Range("I" & i).Select
ActiveSheet.Paste
Next i
End Sub
This should do the trick
Sub operations()
Dim i As Integer
For i = 2 To Cells(2, 2).End(xlDown).Row Step 2
Cells(i, 2).Value = "data for B"
Cells(i, 3).Value = "Data for C"
Next i
Range(Range("H2"), Range("H2").End(xlDown)).Cut Destination:= _
Range(Range("H2"), Range("H2").End(xlDown)).Offset(0, 1)
End Sub
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
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