I am looking for a quick way to fill some fields based on a the following condition. (See image)
I have a list containing 3 columns. I need to fill Column C depending on the letter in Column A. When I go to C34 I would like to automatically search the rows above and based on the letter in Column A copy the 11 names from the latest occurrence above. So in C34-C44 the names from C1-C11 would get copied as a block.
Is there a function in Excel that can do that?
You can use a simple VBA macro with two FOR loops to solve your issue:
Sub CompleteRows()
Dim lastrow As Long
lastrow = Cells(Rows.Count, "A").End(xlUp).Row 'finds last row in column A
For x = 1 To lastrow 'loop that starts with value 1 and goes all the way to the value of lastrow
If Cells(x, 3).Value = "" Then 'if value in column C is empty then continue on
For y = 1 To lastrow 'second loop that runs through the same range
If Cells(y, 1).Value = Cells(x, 1).Value And Cells(y, 2).Value = Cells(x, 2).Value Then
'If the value of the first column and the value of the second
'column for both values match, then add value to column C
Cells(x, 3).Value = Cells(y, 3).Value
Exit For 'Exit loop if value was found
End If
Next y
End If
Next x
End Sub
Related
I am trying to write a macro that would go through the column and see if current cell contains value (reading from left) from the previous row, same column. elow is an example image with yellow cells marked for deleting. For example, there's cell with value "22.2" and next contains that same value and ".1" at the end, meaning that it's a sub-item and needs to be deleted.
What I have in mind code wise is this:
Sub DeleteSubparts()
'Declare variables
Dim LastRow As String
LastRow = Cells(Rows.Count, "E").End(xlUp).Row
'Delete parts subgroup
For i = 2 To LastRow
If Cells(i, 10).Value = Left(Cells(i - 1, 10)) Then
Cells(i, 10).Value = ""
End If
Next i
End Sub
This idea is not really the best approach, but each value in that column "J" is unique and sorted A-z so this idea should work. But general goal is to see if there's a subpart of any part in the list and if so - delete that subpart.
Could someone, please, assist me with finishing that code?
P.S. In my code it just blanks the cell for testing sakes, but there's some problem in how I wrote the code. It returns "Argument not optional" error
EDIT:
Trying something taht seems more correct and doesn't return an error, but still does nothing that's visible nor intended.
If Cells(i, 10).Value = Left(Cells(i - 1, 10), Len(Cells(i - 1, 10))) Then
Cells(i, 10).Value = ""
End If
This will delete the entire row containing the "child" cell.
Option Explicit
Sub DeleteRows()
Dim row As Long
Const col As Integer = 10 ' col J
With Worksheets("Sheet1")
' Start on second row of data
row = 2
Do While .Cells(row, col).Value <> ""
' Use Like to compare the value of the current cell to the value of the previous cell
If .Cells(row, col).Value Like .Cells(row - 1, col).Value & ".*" Then
.Rows(row).Delete
Else
row = row + 1
End If
Loop
End With
End Sub
or this will just clear the child cell contents.
If .Cells(row, col).Value Like .Cells(row - 1, col).Value & ".*" Then
.Cells(row, col).Clear
End If
row = row + 1
Not sure if this is a possibility but here goes. I'm at a standstill for this vba code. I tried attaching a picture example - not sure if it'll show up correctly.
Everything in blue font, I have created a vba code to copy it directly from the top rows down
1) I need a macro that would look in all the cells in the header row 1 for "Cont Type" and if it finds in it any cell, then in the same column directly below the yellow highlighted row (in this case, it's row 5 but it could change because the data will be updated daily), put in the word "Finance" and the word "Finance" has to go all the way down to match the number of rows in column A.
click on the link to see example of what I'm trying to accomplish
Example
You'll need to use a loop to do so. So something like this:
x = 1 'the starting column to look for content type
Do While cells(1, x) <> "" 'look in every column until your columns are empty
If Cells(1, x) = "Cont Type" Then
Range(Cells(6, x), Cells(n, x)) = "Finance" 'With n equaling your last column to insert this to
Else
End If
x = x + 1 'go to the next column to look
Loop
Try:
Option Explicit
Sub test()
Dim LastColumn As Long, i As Long
'Change sheet name if needed
With ThisWorkbook.Worksheets("Sheet1")
'Find LastColumn of row 1
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
'Loop Cells of the first row
For i = 1 To LastColumn
'If cells in row 1 and column i is "Cont Type"
If .Cells(1, i).Value = "Cont Type" Then
'Import in range
.Range(.Cells(6, i), .Cells(9, i)).Value = "Finance"
End If
Next i
End With
End Sub
Results:
Goes directly to MsgBox without seemingly changing anything.
I've been playing around with this code for awhile now since I'm new to VBA. I'm aware this script isn't pointed at a specific spreadsheet.
Private Sub MergeData()
'The cell it will use to search
Dim idCheck As Range
'The cell it will use to compare text
Dim currentCell As Range
'The cell is will use to compare duplicates
Dim oneRowBelow As Range
'Will briefly say if something changed in furthest column
Dim changes As String
'This will be used to format the "Changes" column
Dim rowNumberValue As Integer, columnNumberValue As Integer, rowBelow As Integer
colNum = 3
rowNumberValue = ActiveCell.Row
columnNumberValue = ActiveCell.Column
rowBelow = ActiveCell.Row + 1
'Searches by ID column
For Each idCheck In Worksheets("Test").Range("B2:B1000")
'This checks to find duplicate ID rows
If idCheck.Value = idCheck.Offset(-1, 0).Value Then
'Goes from each column starting from the ID column (H = 7th letter in alphabet and H is the last column)
'Technically S is the last column since S just lists what has changed
For colNum = 3 To 7
'Checks to see if the current cell has no value but the duplicate cell does
If Cells(rowNumberValue, colNum) = "" And Cells(rowBelow, colNum) <> "" Then
'Changes current cell value to the duplicate cell value
Cells(rowNumberValue, colNum) = Cells(rowBelow, colNum)
'Writes in the 19th column whether or not data has been changed
changes = "Added"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 4
End If
'Checks to see if current cell has value but the duplicate cell doesn't
If Cells(rowNumberValue, colNum) <> "" And Cells(rowBelow, colNum) = "" Then
'Merges the two cells ( Unfortunately .Merge takes the top cell value only)
Range(Cells(rowNumberValue, colNum), Cells(rowBelow, colNum)).Merge
'Writes in the 19th column whether or not data has been changed
changes = "Added"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 4
End If
'Checks to see if the cell value is different from the duplicate value
If Cells(rowNumberValue, colNum) <> Cells(rowBelow, colNum) Then
'This just sets the first value to the duplicate value (since it doesn't matter which one is overwritten)
Cells(rowBelow, colNum) = Cells(rowNumberValue, colNum)
'Writes in the 19th column whether or not data has been changed
changes = "Changed"
Cells(rowNumberValue, 19) = changes
Cells(rowNumberValue, 19).Interior.ColorIndex = 6
End If
Next colNum
End If
colNum = 3
Next
MsgBox "All done"
End Sub
So for example, if two rows have the number 123 in their ID column, and the Name column in the first row lists Timothy and the second row lists Tim, the script should change the row to say Bob and say in the furthest column what was changed. Or, if the first or second row has an empty cell while the other row doesn't, the data from the non-empty cell would be merged/copied over to the empty one.
It doesn't matter which data is overwritten, as long as all empty cells that can be filled, are filled.
From my comment, I believe you're causing false conditions due to where your variables are defined:
'Searches by ID column
For Each idCheck In Worksheets("Test").Range("B2:B1000")
'find current cell's row to be used in if-statements
rowNumberValue = ActiveCell.Row 'MOVED INTO ROW LOOP ==============
rowBelow = ActiveCell.Row + 1 'MOVED INTO ROW LOOP ==============
'This checks to find duplicate ID rows
If idCheck.Value = idCheck.Offset(-1, 0).Value Then
'Goes from each column starting from the ID column (H = 7th letter in alphabet and H is the last column)
'Technically S is the last column since S just lists what has changed
For colNum = 3 To 7 'COLNUM IS DEFINED, NOT NEEDED BEFOREHAND ==========
columnNumberValue = ActiveCell.Column 'if you need this, put it inside of this section, but you shouldn't need it due to colNum existing =========
'Your other code here
Next colNum
End If
Next
You also don't need to reset, manually, your colNum to 3 at the end, due to the For loop doing that when it iterates.
Flagged my comments/changes in your code with ======== after the comments.
I am trying to replicate this view where new rows in the bottom table are created based on the values in Column'A' of the top table.
Here is my code:
Sub testProc()
Worksheets("Sheet1").Activate
Dim r, count As Range
Dim LastRow As Long
Dim temp As Integer
'Dim lngLastRow As Long
Set r = Range("A:L")
Set count = Range("A:A")
LastRow = Range("F" & 9).End(xlUp).Row
'LastRow = Cells(Rows.count, MyRange.Column).End(xlUp).Row
For n = LastRow To 1 Step -1
temp = Range("A" & n)
If (temp > 0) Then
Rows(n + 1 & ":" & n + temp).Insert Shift:=xlDown
Range("H" & (ActiveCell.Row) - 2).Copy Range("E" & (ActiveCell.Row) - 1)
Range("G" & (ActiveCell.Row)).Select
'ActiveCell.Offset(RowOffset:=1, ColumnOffset:=-6).Activate
'Cells(ActiveRow, 8).Value.Cut
'Cells.Offset(2 - 6).Value.Paste
'Range("G" & (ActiveCell.Row)).Select
'ActiveCell.Offset(0 - Selection.Column + 1).Range("A1:AG1").Select
'Value = Range(G, H)
'ActiveCell.Offset(1, -6).Paste
'ActiveCell.Offset(1, -6).Paste
'ActiveCell.Offset(RowOffset:=1, ColumnOffset:=-6).Paste
'Range.Offset(1, -6).Paste
'Value = Range("G" & (ActiveCell.Row), "H" & (ActiveCell.Row)).Value
'ActiveCell.Offset(2, -6).Range
'ActiveCell.Offset(rowOffset:=3, columnOffset:=3).Activate
End If
Next n
End Sub
I do not know what I am doing and Excel is crashing with and without messages
The easiest solution to this would be to use two separate worksheets, but you can work around this pretty easily with some math or a cell with a reserved word. You also want to use as few reference variables as possible and let Excel tell you what the ranges are defined as by using contiguous ranges.
I'm not going to write the whole function for you, but give you the building blocks that will let you piece it together and hopefully you'll learn more as you do it.
Here's how to set up the object variables that you'll reference throughout the code:
Dim sourceSheet as Worksheet
Dim targetSheet as Worksheet
' replace with the names of sheets you want to use
sourceSheet = Worksheets("Sheet1")
targetSheet = Worksheets("Sheet2")
Now, for looping through the source table. If you know that the first row in the Sheet is always the Title row and your instructions start in row 2 then you can use this to loop through every instruction:
Dim sourceRowIndex = 2
While Not IsEmpty(sourceSheet.cells(sourceRowIndex, 1))
' ** do stuff here
' increment row index
sourceRowIndex = sourceRowIndex + 1
Wend
You could also use a For Each loop or a For Next or a Do While, take your pick once you understand the logic used.
Note that "Cells" takes two numbers - the row number then the column number. This is very handy when you're looping through a series of rows and columns and don't want to have to deal with addresses like A1 or C5.
This will loop through everything in the top table, but now you need to add an inner loop that will actually process the instructions. Add all of the code below after the While and before the Wend.
Finally, you need to add the rows to the Target. The trick here is to use the CurrentRegion property to figure out where the last row in the range is, then just add one to get the next blank row.
Dim targetFirstEmptyRow
' Look up the Current Range of cell A1 on target worksheet
targetFirstEmptyRow = targetSheet.cells(1,1).CurrentRegion.Rows + 1
Then to assign values don't use copy and paste, just assign the values directly. This will write the first row you have defined:
targetSheet.cells(targetFirstEmptyRow, 1).value = sourceSheet.cells(sourceRowIndex, 1).value
targetSheet.cells(targetFirstEmptyRow, 4).value = sourceSheet.cells(sourceRowIndex, 4).value
targetSheet.cells(targetFirstEmptyRow, 5).value = sourceSheet.cells(sourceRowIndex, 5).value
Then after you write out those three values you can get the next empty row by using this again (note that your sourceRowIndex hasn't changed):
targetFirstEmptyRow = targetSheet.cells(1,1).CurrentRange.Rows + 1
Using the cells(row, column) logic it's pretty easy to write the second row as well:
targetSheet.cells(targetFirstEmptyRow, 2).value = sourceSheet.cells(sourceRowIndex, 6).value
targetSheet.cells(targetFirstEmptyRow, 3).value = sourceSheet.cells(sourceRowIndex, 7).value
targetSheet.cells(targetFirstEmptyRow, 6).value = "Dev"
Adding the third row (when it's required) is nearly exactly the same as the second. However, you want to check to see if the third row is necessary:
If sourceWorksheet.cells(sourceRowIndex, 1) = 3 Then
' insert your third row here
End If
Here's the entire function in pseudo-code so you can piece it all together:
Set up worksheet variables
While loop through every Source row
Find next empty row in Target
Copy Row 1
Find next empty row in Target
Copy Row 2
If 3 rows
Find next empty row in Target
Copy Row 3
Increment Source Row Index
Wend
Finally, if you don't want to see the screen flashing (and you want to speed the code execution up a little) look into Application.Screenupdating to turn off screen redraw as this does its work. Just remember to turn it on again once you've finished processing everything.
Q. To create a Macro that looks up a value in sheet 1 from sheet 2
To look up for a value in Sheet 1, column "F" from rows 11 to 1000000.
Look up value in column "C" Sheet 1, rows 11 to 1000000 condition "Only cells having interior color index RED"
Table array in Sheet 2 column "C & D", rows 4 to 1000000.
To create a Button in Sheet 1 and Assign this Macro to to the Button.
VBA code
Sub VA01()
' CREATING SALES ORDER
Worksheets("sheet1").Range("C11:C1000000").Select
finalrow = Cells(Rows.Count, 3).End(xlUp).Row
For x = 11 To finalrow
If Cells(x, 3).Interior.ColorIndex = 3 Then
Cells(x, 6).Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(R11C3:R1000000C3,Sheet2!R4C3:R1000000C4,2,0)"
End If
Next x
End Sub
Running this Macro hangs up the Excel and takes more time to execute, it is not able to create the button.
First I'd lose the 'Select' method which will require much time and resources. Also why do you select your ("C11:C1000000") Range when the code after does not use this selection ?Then i'd probably keep the vlookup part, but would only keep the value is they do not need to be updated. That would be something like:
Sub VA01()
' CREATING SALES ORDER
'Worksheets("sheet1").Range("C11:C1000000").Select
finalrow = Cells(Rows.Count, 3).End(xlUp).Row
For x = 11 To finalrow
If Cells(x, 3).Interior.ColorIndex = 3 Then
Cells(x, 6).FormulaR1C1 = "=VLOOKUP(R11C3:R1000000C3,Sheet2!R4C3:R1000000C4,2,0)"
Cells(x, 6)=Cells(x, 6).Value
End If
Next x
End Sub