Excel VBA - Incremental Check and Merge - excel

OK so here I go with my first question, advance apologies for any ambiguities.
I am working on a sheet where I pull data through SQL, and copy it to a certain table. The data contains string value. I am currently using vba to pull data (as there are variable involved), and copy it to grid how I want it.
The problem comes here; after I have copied the data, I have to merge certain Cells (sometimes two sometimes 3), and I do this manually. The condition is if C13 = C14 then merge, and if I merge C13 and C14 I have to merge B13 and B14 as well, and D13 and D14 as well. Next I want to check if the merged cell (which is now C13) is equal to C15, and then merge C13 to C15, and if this condition is true then B & D are also going to be merged.
If the condition of C13 is not true i.e. C13 <> C14 I want to go to next cell C14 and check if C14 = C15 or not.
I want to do this with vba, but trying to do this manually, will run into miles and miles of codes can someone please help?
This is the start of the code I have found here and managed to change a bit but now I am lost
Sub Merge()
Dim k As Range, cell As Range, name As String
Set k = Range("C13:C50")
For Each cell In k
If cell.Value =
End If
Next
End Sub

I could propose you the following code:
Sub Merge()
Dim k As Range, cell As Range, name As String
Set k = Range("C13:C50")
Application.DisplayAlerts = False
Do_it_again:
For Each cell In k
If cell.Value = cell.Offset(1, 0).Value _
And IsEmpty(cell) = False Then
Debug.Print cell.Address
'for column C
Range(cell, cell.Offset(1, 0)).Merge
'for column B
cell.Offset(0, -1).Resize(cell.MergeArea.Rows.Count, 1).Merge
'for column D
cell.Offset(0, 1).Resize(cell.MergeArea.Rows.Count, 1).Merge
GoTo Do_it_again
End If
Next
Application.DisplayAlerts = True
End Sub
I don't necessary like the code I proposed but after all it works as presented below.
Edit to improve efficiency
I have to admit that previous code wasn't efficient for big data table, like 5000 rows or more. One below is 90% faster but still need approx 10-20 sec for 5000 rows of data.
Most important changes compared to the code above are marked *****.
Sub Merge()
Dim k As Range, cell As Range, name As String
Dim kStart As Range, kEnd As Range '*****
Set kStart = Range("C13") '*****
Set kEnd = Range("C8000") '*****
Application.DisplayAlerts = False
Application.ScreenUpdating = False '*****
Do_it_again:
For Each cell In Range(kStart, kEnd) '*****
If cell.Value = cell.Offset(1, 0).Value _
And IsEmpty(cell) = False Then
Application.StatusBar = cell.Address '***** check progress in Excel status bar
'for column C
Range(cell, cell.Offset(1, 0)).Merge
'for column B
cell.Offset(0, -1).Resize(cell.MergeArea.Rows.Count, 1).Merge
'for column D
cell.Offset(0, 1).Resize(cell.MergeArea.Rows.Count, 1).Merge
Set kStart = cell '*****
GoTo Do_it_again
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True '*****
End Sub

Sorry, forgot to initialize count # 14
current = cells(13,3)
count = 14
for i = 14 to 15
next = cells(i,3)
If current = next then
'match encountered, merge columns B,C,D
for j = 2 to 4
cells(13,j) = cells(13,j) & cells(count,j)
next j
count = count + 1
end if
next i
If you are not trying to append but replace the value of C13 with C14 if matched, and C13 with C15 if matched etc..., then change the line
cells(13,j) = cells(13,j) & cells(count,j)
to
cells(13,j) = cells(count,j)

Related

Replace with 3 conditions is failing - Excel VBA

What I am trying to accomplish is:
If cells in column F contain a number, then convert it to a percentage
If cells in column F are empty and the corresponding cell in column G contain 0 then write in cell in column F "-"
If cells in column F dont contain a number and the corresponding cell in column G contain a number higher than 0 then write in cell in column F "Action Required"
Column G is formatted as number.
However, with the given code, everything becomes "-". Where is the trick?
Sub Replace()
Dim ws As Worksheet, dataLastRow As Long, cell As Range, MyRng As Range
Set ws = ThisWorkbook.Worksheets("MyTab")
Application.ScreenUpdating = False
dataLastRow = ws.Range("F" & Rows.Count).End(xlUp).Row
Set MyRng = ws.Range("F2:F" & dataLastRow)
' Loop through column F
For Each cell In MyRng
If cell = "" And cell.Offset(0, 1) = 0 Then
cell = "-"
ElseIf cell = "" And cell.Offset(0, 1) > 0 Then
cell = "Action Required"
ElseIf cell >= 0 Then
With MyRng
.NumberFormat = "0.00%"
.Value = .Value
End With
Else
End If
Next cell
Application.ScreenUpdating = True
End Sub
Your question looks weird: you get a list of data, you need to summarise those data and instead of putting the summary in another column, you decide to overwrite your data with your summary.
In case you change your mind, I've written this formula which creates the summary (not entirely correct, some small adaptations need to be done):
=IF(AND(ISBLANK(F1),G1=0),"-",IF(ISNUMBER(F1),F1,"Action required"))
(Oh, in case you use the formula, don't forget modifying the cell format into percentage.)

Excel VBA, searching values in specific cells in a named range

I'm rather new to all of this and have looked everywhere.
I have a named range "Ruptures" (N14:P60) in sheet 7 in which I would like to find in column P values greater than 0 and paste corresponding cells N:P in sheet 9 F:H. I can't seem to search only column P.
This is what I've tried so far:
Dim cell As Variant
Dim count As Long
count = 0
With Sheet7
Set Rng = Sheet7.Range("Ruptures")
For Each cell In Rng
'But I only want to check cells from the P column (this is where I am stumped)
If cell.Value > 0 Then
Range(cell.Offset(0, -2), cell.Offset(0, 0)).Copy
Sheet9.Activate
Range("F14", "H14").Offset(count, 0).PasteSpecial (xlPasteValues)
count = count + 1
Sheet7.Activate
Next
End With
End If
End Sub
Thank so much in advance and have a great day ! :)
Ursula
This is iterating over the entire (multi-column) range:
Set Rng = Sheet7.Range("Ruptures")
For Each cell In Rng
You can limit this to the third column using this:
For Each cell in Rng.Columns(3)
I would also simplify the copy/paste to avoid unnecessary worksheet Activate and to use direct Value assignment from one range to the other (see here for more detail as well). And as noted in the comments, your Next statement can't be inside the If block:
For Each cell in Rng.Columns(3)
If cell.Value > 0 Then
Sheet9.Range("F14", "H14").Offset(count, 0).Value = Range(cell.Offset(0, -2), cell.Offset(0, 0)).Value
count = count + 1
End If
Next
This could be further refined using Resize methods:
For Each cell in Rng.Columns(3)
If cell.Value > 0 Then
Sheet9.Range("F14").Offset(count).Resize(1,3).Value = cell.Offset(0,-2).Resize(1,3).Value
count = count + 1
End If
Next

How to provide range in Macro in Excel in below formula

I have to create a formula where say 3 columns are present A, B & C which has values till say serial 5. So now have to check If value in cell say C1 is blank then cell B1 would be A1/Count(C).
I am able to perform this for single cell but how can use below formula for range from A1:A5, B1:B5 and C1:C5
Sub CheckCnt()
Range("C6") = WorksheetFunction.CountA(Range("C1:C5"))
If Range("C1") = "" Then
Range("B1") = WorksheetFunction.Round(Range("A1") / Range("C6"), 2)
Else
Range("B1") = 0
End If
End Sub
Placing this into a FOR loop should work.
Please see Revised code below.
Sub CheckCnt()
Dim rw as Integer
Range("C6").Value = WorksheetFunction.CountA(Range("C1:C5"))
For rw = 1 to 5
If Range("C" & rw).Value = "" Then
Range("B" & rw).Value = WorksheetFunction.Round(Range("A" & rw).Value / Range("C6").Value, 2)
Else
Range("B" & rw).Value = 0
End If
Next rw
End Sub
Let me know if this works. Thanks so much!
I'm not sure exactly what formula looking to insert so I've placed the ROUND formula in the range B1:B5.
B1 will be: =ROUND($A1/$C$6,2)
B2 will be: =ROUND($A2/$C$6,2)
and so on...
This code uses the R1C1 notation:
Sub CheckCnt()
'Be specific about which sheet you want the result in (otherwise it will appear in the selected sheet).
With ThisWorkbook.Worksheets("Sheet1")
With .Range("B1:B5")
.FormulaR1C1 = "=Round(RC1/R6C3,2)" 'Use a formula with R1C1 notation.
.Value = .Value 'Replace the formula with the result of the formula.
End With
End With
End Sub
RC1 means this row, column 1. R6C3 means row 6, column 3.
http://www.numeritas.co.uk/2013/09/the-%E2%80%98dark-art%E2%80%99-of-r1c1-notation/

How to run an equation along whole column in excel vba

I want to run an excel vba which will go down column E and upon finding the value = "capa" will go two cell below, calculate the hex2dec value of that cell, present it by the cell with the value "capa" in column F and continue to search down column E.
So far I've came with the below but it doesn't work:
For Each cell In Range("E:E")
If cell.Value = "Capa" Then
ActiveCell.Offset.FormulaR1C1 = "=HEX2DEC(R[2]C[-1])"
End If
Next cell
Thanks!
How about something like this?
This will search volumn E for "Capa" and, if found, will place formula in column F using the value directly below "Capa" in column E
Sub CapaSearch()
Dim cl As Range
For Each cl In Range("E:E")
If cl.Value = "Capa" Then
cl.Offset(0, 1).Formula = "=HEX2DEC(" & cl.Offset(1, 0) & ")"
End If
Next cl
End Sub
You really want to limit the loop so you don't loop over the whole sheet (1,000,000+ rows in Excel 2007+)
Also, copying the source data to a variant array will speed things up too.
Try this
Sub Demo()
Dim dat As Variant
Dim i As Long
With ActiveSheet.UsedRange
dat = .Value
For i = 1 To UBound(dat, 1)
If dat(i, 6 - .Column) = "Capa" Then
.Cells(i, 7 - .Column).FormulaR1C1 = "=HEX2DEC(R[2]C[-1])"
End If
Next
End With
End Sub

How to highlight a row if three conditions are met?

If the following conditions are met:
For any given row between row 10 and row 100 inclusively:
The cell in column A is not empty
The cell in column B is not empty
The cell in column O is empty
I would like to highlight a specific cell (let's say A1).
Example:
I populate A10 and E10 while leaving O10 empty, then cell A1 gets highlighted. If I then populate cell O10, the highlight in cell A1 disappears.
I can proceed to the next row. Any row at any time should generate these actions.
Thanks!
This will do the highlights based on the conditions you specified. When you run it, it'll stop at the first row you need to input something in column O. If you want it to keep running until row 101 and highlight all the rows, then remove then Exit Do command that's between the 2 End If statements.
Sub Highlight()
Dim TheRow As Integer
TheRow = 9
Application.ScreenUpdating = False 'This hides the visual process and speeds up
'the execution
Do
TheRow = TheRow + 1
If TheRow = 101 Then Exit Do
Cells(TheRow, 1).Select
Selection.Interior.Pattern = 0
Cells(TheRow, 2).Select
Selection.Interior.Pattern = 0
If Not Cells(TheRow, 1).Value = "" And Not Cells(TheRow, 2).Value = "" And Cells(TheRow, 15).Value = "" Then
If Cells(TheRow, 1).Value = "" Then
Cells(TheRow, 1).Select
Selection.Interior.Color = 656
End If
If Cells(TheRow, 2).Value = "" Then
Cells(TheRow, 2).Select
Selection.Interior.Color = 656
End If
Exit Do 'this is the line to remove if you want to highlight all cells
End If
Loop
Application.ScreenUpdating = True
End Sub
And then, create an event handler that triggers when a cell in column 15 changes. Put the following code in the module of the actual worksheet (in the VBA project explorer, double click on the sheet you want have this functionality for; don't put this in a different module!)
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 15 Then
If Target.Row > 9 And Target.Row < 101 Then Call Highlight
End Sub
Let me know if this solution works and remember to click "accept solution" and to vote for it!
Happy coding.
You don't need VBA: just use conditional formatting on cell A10 with the following formula:
=AND(NOT(ISBLANK($A10)),NOT(ISBLANK($B10)),ISBLANK($O10))
OK - I misunderstood what you wanted. Here is a VBA UDF to do the checking.
Enter =Checker($A$10:$B$100,$O$10:$O$100) in cell A1, then use conditional formatting on cell A1 that is triggered when it becomes True.
Public Function Checker(theRangeAB As Range, theRangeO As Variant) As Boolean
Dim varAB As Variant
Dim varO As Variant
Dim j As Long
varAB = theRangeAB.Value2
varO = theRangeO.Value2
Checker = False
For j = 1 To UBound(varAB)
If Not IsEmpty(varAB(j, 1)) And Not IsEmpty(varAB(j, 2)) Then
If IsEmpty(varO(j, 1)) Then
Checker = True
Exit For
End If
End If
Next j
End Function

Resources