Show the output in empty row - excel

I am new to VBA. i have created triangles which i need to place into the 1st empty row above the given data.
Eg: Please Refer the image.
1) Output after running below code. Yellow marked lines is the row where the output should be shown.
2) actual output it should look like this . (I have edited it manually )
I have created triangle for every data in column c. which i have matched to RANGE(I4:AK4),
but as you can see in image, i am getting output in row 13 in actual it should be in empty row.
It is just my idea: As empty row should be used as the output for the given below data.
For Eg: ROW 20 should be used as output row for given below data in column C (C21,C22,C23)
Please refer the code below as i have tried to create triangle but not able to move to 1st empty row to given below data.
Sub addshape()
Dim lastrow As Long
Dim lastCol As Long
Dim heightCell As Long
Dim widthCell As Long
Dim R As Excel.Range
Dim i As Long
Dim l As Long
Dim s As Shape
With ThisWorkbook.Sheets("Tabelle1")
lastrow = .Cells(Rows.Count, 2).End(xlUp).Row
lastCol = .Cells(4, Columns.Count).End(xlToLeft).Column
For i = 6 To lastrow
If .Cells(i, 3) = " " Then
Else
Set R = .Range(.Cells(4, 9), .Cells(4, lastCol))
If IsEmpty(.Cells(i, 3).Value) = False Then
Set s = ActiveSheet.Shapes.addshape(msoShapeIsoscelesTriangle, 51, 220, 14, 12)
With s
.Name = "triangle" & i
.Rotation = 180
.TextFrame.Characters.Text = Cells(i, 2)
.TextFrame.Characters.Font.Size = 10
.TextFrame.Characters.Font.Color = RGB(0, 0, 0)
.TextFrame.VerticalAlignment = xlVAlignCenter
.TextFrame.HorizontalAlignment = xlHAlignCenter
.Line.Weight = 1
.Line.ForeColor.RGB = RGB(0, 0, 0)
.TextEffect.Alignment = msoTextEffectAlignmentCentered
.TextFrame.Orientation = msoTextOrientationHorizontal
.TextFrame.VerticalOverflow = xlOartVerticalOverflowOverflow
.Fill.ForeColor.RGB = RGB(245, 144, 66)
End With
s.Left = 10
l = Application.WorksheetFunction.Match(.Cells(i, 3), R, 0)
l = R(1, l).Left
l = l + (R(1, l).Width / 24)
s.Left = l
End If
End If
Next i
End With
End Sub
Please share your ideas or your codes.
Will be thankful.

What you can do is loop over all your cells backwards to find the first blank cell above the cell you're working from. Then Align the top to the found cell. Concept:
j = i 'Using a new variable to start from i so to not mess up variable i.
Set A = .Range("B1") 'set a range as a blank range will throw an error when used.
Do Until A = "" 'loop until A is assigned a blank cell
j = j - 1 'step -1 to loop backwards
Set A = .Cells(j, 3) 'assign cell to A as one above the last one.
Loop
s.Top = A.Top 'align top of shape to top of found cell.
In your code this would look like so:
Sub addshape()
Dim lastrow As Long
Dim lastCol As Long
Dim heightCell As Long
Dim widthCell As Long
Dim R As Excel.Range
Dim i As Long
Dim j As Long
Dim l As Long
Dim s As Shape
Dim A As Range
With ThisWorkbook.Sheets("Tabelle1")
lastrow = .Cells(Rows.Count, 2).End(xlUp).Row
lastCol = .Cells(4, Columns.Count).End(xlToLeft).Column
For i = 6 To lastrow
If .Cells(i, 3) = " " Then
Else
Set R = .Range(.Cells(4, 9), .Cells(4, lastCol))
If IsEmpty(.Cells(i, 3).Value) = False Then
Set s = ActiveSheet.Shapes.addshape(msoShapeIsoscelesTriangle, 51, 220, 14, 12)
With s
.Name = "triangle" & i
.Rotation = 180
.TextFrame.Characters.Text = Cells(i, 2)
.TextFrame.Characters.Font.Size = 10
.TextFrame.Characters.Font.Color = RGB(0, 0, 0)
.TextFrame.VerticalAlignment = xlVAlignCenter
.TextFrame.HorizontalAlignment = xlHAlignCenter
.Line.Weight = 1
.Line.ForeColor.RGB = RGB(0, 0, 0)
.TextEffect.Alignment = msoTextEffectAlignmentCentered
.TextFrame.Orientation = msoTextOrientationHorizontal
.TextFrame.VerticalOverflow = xlOartVerticalOverflowOverflow
.Fill.ForeColor.RGB = RGB(245, 144, 66)
End With
s.Left = 10
l = Application.WorksheetFunction.Match(.Cells(i, 3), R, 0)
l = R(1, l).Left
l = l + (R(1, l).Width / 24)
s.Left = l
j = i
Set A = .Range("B1")
Do Until A = ""
j = j - 1
Set A = .Cells(j, 3)
Loop
s.Top = A.Top
End If
End If
Next i
End With
End Sub

Related

Identify Column Number by defined Header String (ignore upper case, lower case, indentation)

I have a defined header string that I am trying to locate the respective column number for in a table. The table headers titles formats are indented with Alt+Enter.
The code works fine if the header string is written normally (without indentation)
Sample: Origin_Country(in 2-letter codes)
In the excel table however the header format is different as mentioned.
sample:
Origin_
Country
(in 2 letter format)
Excel seems to think there is a space in the header due to the indentation and it is not recognized.
Did anyone encounter this and know a work around?
Option Compare Text
Option Explicit
Sub ListChanges()
Dim arrOrig, arrCurrent, delta, i As Long, ii As Long, r As Long, m
Dim rngOrig As Range, rngCurrent As Range, id, col As Long, vO, vC
Dim ls As String
Dim HeaderName As String, HeaderRow As Long
Dim j As Long
Dim LastRow As Long, LastCol As Long, RowProcess As Long
Dim TopLeftAddress As String
'Origin Country
Dim OCountryCol As Long
Dim strOCountryCol As String
'DGF Lane ID
Dim DGFLaneIDCol As Long
Dim strDGFLaneIDCol As String
'Origin Region
Dim ORegionCol As Long
Dim strORegionCol As String
'------
Dim ActSht As Worksheet
Set ActSht = Worksheets(2)
'ActiveWorkbook.Sheets(General).Range ("1:1")
TopLeftAddress = ActSht.Range("1:1").Address 'identify top left cell of the table, to see where the table starts
LastCol = ActSht.Range(TopLeftAddress).End(xlToRight).Column ' total number of columns in each pivot table
i = ActSht.Range(TopLeftAddress).Column 'column number where the table starts
HeaderRow = ActSht.Range("1:1").Row 'row number where the table starts
For j = 25 To LastCol 'i set j at 25 so that I don't have to loop through all columns
HeaderName = ActSht.Cells(HeaderRow, j)
If InStr(HeaderName, "Origin_Country(in 2-letter codes)") > 0 Then
OCountryCol = j
strOCountryCol = Split(ActSht.Cells(, OCountryCol).Address, "$")(1)
ElseIf InStr(HeaderName, "Origin_Region(enter AP, AM, EURO, MEA)") > 0 Then
ORegionCol = j
strORegionCol = Split(ActSht.Cells(, ORegionCol).Address, "$")(1)
End If
Next
Set rngOrig = Original.Cells(1).CurrentRegion
Set rngCurrent = Current.Cells(1).CurrentRegion
arrOrig = rngOrig.Value
arrCurrent = rngCurrent.Value
ReDim delta(1 To UBound(arrCurrent, 1) * (UBound(arrCurrent, 2)), 1 To 8) 'max possible size
delta(1, 1) = "Location"
delta(1, 2) = "Original Value"
delta(1, 3) = "Changed Value"
delta(1, 4) = "Deviation"
delta(1, 5) = "Header"
delta(1, 6) = "Row ID"
delta(1, 7) = "Origin Region"
delta(1, 8) = "Origin Country"
r = 1 'row in delta array
For i = 2 To UBound(arrCurrent, 1)
id = arrCurrent(i, 1)
'find the corresponding row
m = Application.Match(id, rngOrig.Columns(1), 0)
If Not IsError(m) Then
For col = 2 To UBound(arrCurrent, 2)
vO = arrOrig(m, col)
vC = arrCurrent(i, col)
If (Len(vC) > 0 Or Len(vO) > 0) And vC <> vO Then
r = r + 1
delta(r, 1) = rngCurrent.Cells(i, col).Address(False, False)
delta(r, 2) = vO
delta(r, 3) = vC
If Len(vO) > 0 And Len(vC) > 0 Then
If IsNumeric(vO) And IsNumeric(vC) Then
delta(r, 4) = vC / vO - 1 'eg
End If
End If
delta(r, 5) = arrCurrent(1, col) 'header
delta(r, 6) = arrCurrent(i, 1) 'id
delta(r, 7) = arrCurrent(i, 26) 'id region
delta(r, 8) = arrCurrent(i, 27) 'id country
End If
Next col
Else
'no id match, just record the cell address and the current id
r = r + 1
delta(r, 1) = rngCurrent.Cells(i, 1).Address(False, False)
delta(r, 6) = id
End If
Next
With Changes
.Activate
.Cells(1).CurrentRegion.Clear
.[a1].Resize(r, UBound(delta, 2)) = delta '<< edited here
With .Cells(1).CurrentRegion
.HorizontalAlignment = xlCenter
With Rows(1).Font
.Size = 12
.Bold = 1
End With
.Columns.AutoFit
End With
End With
End Sub

Delete rows based on colour of cells

At the moment I have some cells that look something like this
What I want to achieve is something that deletes duplicates but also puts all of the green cells into the same row
What I have at the moment is a code like this
Sub Delete_Duplicates()
Worksheets("MySheet").Activate
'Obtain the last row with data on column 2
a = Worksheets("MySheet").Cells(Rows.Count, 2).End(xlUp).Row
'Loop through the name of the items
For b = a To 6 Step -1
CurrentCell = Cells(b, 2).Select
CellValue = Cells(b, 2).Value
CellUp = ActiveCell.Offset(-1, 0)
If ActiveCell.Value = CellUp Then
For c = 8 To 19
If Range(b, c).Interior.Color = RGB(146, 208, 80) Then
Worksheets("MySheet").Range(b, c).Activate
Range(b, c).Copy Destination:=ActiveCell.Offset(-1, 0)
Rows(a).EntireRow.Delete
End If
Next c
End If
Next b
End Sub
What I am hoping that this code does is that it recognises if the value of the active cell is equal to the cell on top and then if their values are equal I loop through the cells from column H to column S and copy the cells that are green and paste them on top
The issue that I have at the moment is that when my code finds two cells with equal names after going to the line
If Range(b, c).Interior.Color = RGB(129, 188, 0) Then
The compiler just skips the rest of the code and wont execute anything else, can anyone help me see why is the rest of my code being skipped?
I m not 100% sure about the code because was to complex but i try to create something:
Sub TEST()
Dim LastRow As Long, i As Long, y As Long, w As Long, k As Long, RowCounter As Long, FirstInstant As Long, o As Long, l As Long
Dim arrNames As Variant, arrNumber(0) As Variant, arrCheck As Variant, arrDelete(0) As Variant, arrColor As Variant, arrSplit As Variant
Dim Found As Boolean, Found_2 As Boolean
RowCounter = 0
FirstInstant = 0
With ThisWorkbook.Worksheets("Sheet2")
LastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
arrNames = .Range("B6:B" & LastRow)
'Loop name
For i = LBound(arrNames) To UBound(arrNames)
'Loop rows
For y = 6 To LastRow
'Check there is a match
If arrNames(i, 1) = .Range("B" & y).Value Then
If FirstInstant = 0 Then
FirstInstant = y
End If
If RowCounter > 0 Then
If arrDelete(0) = "" Then
arrDelete(0) = y & ":" & y
Else
arrSplit = Split(arrDelete(0), ",")
For l = LBound(arrSplit) To UBound(arrSplit)
If arrSplit(l) = y & ":" & y Then
Found_2 = True
Exit For
End If
Next l
If Found_2 = False Then
arrDelete(0) = arrDelete(0) & "," & y & ":" & y
End If
End If
Else
RowCounter = RowCounter + 1
End If
'Loop columns
For w = 3 To 19
'Check if there is color
If .Cells(y, w).Interior.Color = RGB(129, 188, 0) Then
If arrNumber(0) = "" Then
arrNumber(0) = w
Else
arrCheck = Split(arrNumber(0), ",")
Found = False
'Check if the column already excist
For k = LBound(arrCheck) To UBound(arrCheck)
If arrCheck(k) = w Then
Found = True
Exit For
End If
Next k
If Found = False Then
arrNumber(0) = arrNumber(0) & "," & w
End If
End If
End If
Next w
End If
Next y
'Color
If arrNumber(0) <> "" Then
arrColor = Split(arrNumber(0), ",")
For o = LBound(arrColor) To UBound(arrColor)
.Cells(FirstInstant, CLng(arrColor(o))).Interior.Color = RGB(129, 188, 0)
Next o
End If
RowCounter = 0
FirstInstant = 0
Erase arrNumber
Erase arrCheck
Erase arrColor
Next i
.Range(arrDelete(0)).EntireRow.Delete
End With
End Sub

VBA formatting table with merged cells

I've got a function which merges cells in table if whole range has the same value (eg. if A1:G1 is equal to A2:B2 it will merge cells like A1&A2, B1&B2 etc. More here: How to check if two ranges value is equal)
Now I would like, to change color on table created by that funcion, like first row (doesn't matter if merged or no) filled with color, second blank etc. but I have no idea whether I should color it with merging function or create another which will detect new table with merged rows as one etc. Below is my code:
Sub test()
Dim i As Long, j As Long, k As Long, row As Long
row = Cells(Rows.Count, 2).End(xlUp).row
k = 1
For i = 1 To row Step 1
If Cells(i, 1).Value = "" Then Exit For
If Join(Application.Transpose(Application.Transpose(Range(Cells(i, 1), Cells(i, 3)))), Chr(0)) <> Join(Application.Transpose(Application.Transpose(Range(Cells(i + 1, 1), Cells(i + 1, 3)))), Chr(0)) Then
If i <> k Then
For j = 1 To 3 Step 1
Application.DisplayAlerts = False
Range(Cells(i, j), Cells(k, j)).Merge
Application.DisplayAlerts = True
Next j
End If
k = i + 1
End If
Next i
End Sub
Try:
Option Explicit
Sub test1()
Dim LastColumn As Long, LastRow As Long, i As Long
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
For i = 2 To LastRow Step 2
.Range(Cells(i, 1), .Cells(i, LastColumn)).Interior.Color = vbGreen '<- You could change the color
Next i
End With
End Sub
Before:
After:
Edited Solution:
Option Explicit
Sub test1()
Dim rng As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rng = .UsedRange
.ListObjects.Add(xlSrcRange, rng, , xlYes).Name = "Table1"
.ListObjects("Table1").TableStyle = "TableStyleLight3"
End With
End Sub
Result:
So, after some time I've figured it out by myself. Below is the code:
Dim i As Long, j As Long, k As Long, l As Long, c As Integer
row = Cells(Rows.Count, 2).End(xlUp).row
k = 7
c = 1
For i = 7 To row Step 1
If Join(Application.Transpose(Application.Transpose(Range(Cells(i, 1), Cells(i, 3)))), Chr(0)) <> Join(Application.Transpose(Application.Transpose(Range(Cells(i + 1, 1), Cells(i + 1, 3)))), Chr(0)) Then
If i <> k Then
For j = 1 To 3 Step 1
Application.DisplayAlerts = False
Range(Cells(i, j), Cells(k, j)).Merge
Application.DisplayAlerts = True
Next j
End If
Select Case c
Case 0
Range(Cells(k, 1), Cells(k, 3)).Interior.Color = xlNone
c = 1
Case 1
For l = 0 To i - k Step 1
Range(Cells(k + l, 1), Cells(k + l, 3)).Interior.Color = RGB(217, 225, 242)
Next l
c = 0
End Select
k = i + 1
End If
Next i

Insert values of a form into last row

I would like my form to add its values to a new row in a table right below the last used row. this is what I got:
Dim sh As Worksheet, lastrow As Long
If MiemCombx.Value = "General" Then
Sh = Sheets("General")
lastrow = sh.UsedRange.Row - 1 + sh.UsedRange.Rows.Count
Sh.Cells(lastrow, 1) = Nume
Sh.Cells(lastrow, 2) = Date
Sh.Cells(lastrow, 3) = MiemCombx
Sh.Cells(lastrow, 4) = ClasCombx
Sh.Cells(lastrow, 5) = ConcTxt
Sh.Cells(lastrow, 6) = JustCombx
Sh.Cells(lastrow, 7) = Impo
End If
There's a lot of ways to do this, here's one based upon the last appearance of a value in column A:
Dim sh as Worksheet
Dim c as Range
Set sh = sheets("General")
Set c = sh.Range("A1048576").End(xlUp)
c.Offset(1, 1) = Nume
c.Offset(1, 2) = Date
c.Offset(1, 3) = MiemCombx
c.Offset(1, 5) = ConcTxt
c.Offset(1, 6) = JustCombx
c.Offset(1, 7) = Impo
End Sub
Or, if you prefer using 'lastrow', then
Dim sh as Worksheet
Dim lastrow as Long
Set sh = sheets("General")
Set lastrow = sh.Range("A1048576").End(xlUp).Row + 1
sh.Cells(lastrow , 1) = Nume
sh.Cells(lastrow , 2) = Date
sh.Cells(lastrow , 3) = MiemCombx
sh.Cells(lastrow , 5) = ConcTxt
sh.Cells(lastrow , 6) = JustCombx
sh.Cells(lastrow , 7) = Impo
End Sub
Hope one works for you.

Overflow Error in VBA code

Below is my code for the project I am doing, and for some reason I keep on getting an overflow error at the line:
totalAmountWeight = (ActiveWorkbook.Worksheets("Product Info").Cells(p, 8).Value) / (ActiveWorkbook.Worksheets("Product Info").Cells(p, 7).Value)
I am not sure why this error is occurring or how to fix it.
Private Sub Worksheet_Calculate()
Dim target As Range
Set target = Range("Q1")
Dim p As Long
Dim o As Long
Dim r As Long
Dim Length As Single
Dim Width As Single
Dim Height As Single
Dim totalAmountWeight As Double
Dim i As Integer, intValueToFind As Integer
Dim sheet As Worksheet
Set sheet = ThisWorkbook.Worksheets("Product Info")
'lastrow = sheet.Cells(sheet.Rows.Count, "B").End(xlUp).row
lastrow = Range("B" & Rows.Count).End(xlUp).Row
o = 1
r = 1
If Not Intersect(target, Range("Q1")) Is Nothing Then
For p = 2 To lastrow
Length = ActiveWorkbook.Worksheets("Product Info").Cells(p, 2).Value
Width = ActiveWorkbook.Worksheets("Product Info").Cells(p, 3).Value
Height = ActiveWorkbook.Worksheets("Product Info").Cells(p, 4).Value
totalAmountWeight = (ActiveWorkbook.Worksheets("Product Info").Cells(p, 8).Value) / (ActiveWorkbook.Worksheets("Product Info").Cells(p, 7).Value)
ActiveWorkbook.Worksheets("Backend").Range("O1").Value = totalAmountWeight
Call boxes(Length, Width, Height)
Call boxesLast3(Length, Width, Height)
intValueToFind = 0
For i = 2 To 7 ' Revise the 500 to include all of your values
If ActiveWorkbook.Worksheets("Backend").Cells(i, 5).Value = intValueToFind Then
'MsgBox ("Found value on row " & i)
ActiveWorkbook.Worksheets("Backend").Cells(i, 7).Value = 600
ActiveWorkbook.Worksheets("Backend").Cells(i, 8).Value = 400
ActiveWorkbook.Worksheets("Backend").Cells(i, 9).Value = 325
Else
'MsgBox ("Value not found in the range!")
'MsgBox ActiveWorkbook.Worksheets("Backend").Cells(i, 5).Value
End If
Next i
Call LWextra(Height, Length, Width)
Call HWextra(Height, Length, Width)
Call LHextra(Height, Length, Width)
Call HLextra(Height, Length, Width)
Call WLextra(Height, Length, Width)
Call WHextra(Height, Length, Width)
newamount = ActiveWorkbook.Worksheets("Backend").Range("Q1").Value
dimensions = ActiveWorkbook.Worksheets("Backend").Range("K13").Value
ActiveWorkbook.Worksheets("Backend").Cells(o, 26).Value = newamount
o = o + 1
ActiveWorkbook.Worksheets("Backend").Cells(r, 27).Value = dimensions
r = r + 1
Next p
End If
End Sub

Resources