Consider the following illustrative example
Private Sub drawBorders(listOfBorders)
For Each Item In listOfBorders
With .Borders(Item)
.LineStyle = xlContinious
.ColorIndex = xlAutomatic
.Weight = xlThin
End With
Next Item
End Sub
Sub main()
Dim TopBottom() as Variant
Dim myRange As Range
TopBottom = Array(xlEdgeTop, xlEdgeBottom)
myRange = Range("A1")
With myRange
.value = a
Call DrawBorders(topBottom)
End With
End Sub
I have a sequence of With statements where some of the code is pretty repeating.
I get an error at the DrawBorders sub :
Invalid or unqualified reference
Is it possible to import the reference from the With statement into the Sub?
You should always specify the type of the argument in your Sub or Function.
The error in DrawBordersyou get is because of this With .Borders(Item) which hasn't any object to be referenced to (no With Object before).
My guess is that you wanted to pass the reference inside of your call and that is why you need to pass an object, because the With from the main code won't follow when you call a function or sub!
Here is my proposition for your code :
Private Sub DrawBorders(ListOfBorders As Variant, RangeToFormat As Range)
For Each Item In ListOfBorders
With RangeToFormat.Borders(Item)
.LineStyle = xlContinuous
.ColorIndex = xlAutomatic
.Weight = xlThin
End With
Next Item
End Sub
Sub main()
Dim TopBottom() As Variant, _
Ws As Worksheet, _
MyRange As Range
Set Ws = ActiveSheet
Set MyRange = Ws.Range("A1:J10")
MyRange.Value = A
TopBottom = Array(xlEdgeTop, xlEdgeBottom)
With Ws
Call DrawBorders(TopBottom, .Range("A1:J10"))
End With
'----Or
'Call DrawBorders(TopBottom, MyRange)
End Sub
This should work
Private Sub DrawBorders(listOfBorders() as Variant, r As Range)
For Each Item In listOfBorders
With r.Borders(Item)
.LineStyle = xlContinuous
.ColorIndex = xlAutomatic
.Weight = xlThin
End With
Next Item
End Sub
Dim TopBottom() As Variant
Dim myRange As Range
TopBottom = Array(xlEdgeTop, xlEdgeBottom)
myRange = Range("A1")
With myRange
.Value = a
End With
Call DrawBorders(TopBottom, myRange)
Related
I'll try to get all the info out here... I have a query table (A1:E120 w/headers) on one sheet, and a nicely formatted table (B1:F120 w/headers) on another, I have a macro that updates the formatted table from the query table by this subroutine:
Module 1:
Sub UpdateLedger()
Dim Lgr1 As ListObject
Dim LgrSource As ListObject
Dim UniqueRowEntry As String
Dim n As Long
UniqueRowEntry = Cells(2, 6).Value
n = Sheets(5).UsedRange.Find(UniqueRowEntry, LookIn:=xlValues).Row - 2
Application.EnableEvents = False *I have a row highlight selection event
Set Lgr1 = Sheets(4).ListObjects(1)
Set LgrSource = Sheets(5).ListObjects(1)
For i = 1 To n
If Not Lgr1.ListRows(i).Range.Cells(1).Value = LgrSource.ListRows(i).Range.Cells(1).Value Then
If Not Lgr1.ListRows(i).Range.Cells(5).Value = LgrSource.ListRows(i).Range.Cells(5).Value Then
Lgr1.ListRows.Add (i)
Lgr1.ListRows(i).Range.Value = LgrSource.ListRows(i).Range.Value
End If
End If
Next i
Application.EnableEvents = True
End Sub
This Sub works great! but, when I was debugging it kept jumping over to these when it added the row! :
Module 2:
Global CText As Range
Global SText As String
Global SWks As Integer
Private Function TextFind(wks As Integer, SearchText As String) As String
Dim SearchResult As Range
Set SearchResult = Worksheets(wks).UsedRange.Find(SearchText)
Set CText = SearchResult
SText = SearchText
SWks = wks
TextFind = SearchResult.Address
Debug.Print SearchResult.Address
End Function
Private Function NextText() As String
Dim SearchNext As Range
Dim ContinueBox As Variant
Set SearchNext = Worksheets(SWks).UsedRange.Find(What:=SText, After:=CText, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If SearchNext Is Nothing Then
ContinueBox = MsgBox("Clear Search Settings?", vbYesNo, "Next " & SText & " not found!")
If ContinueBox = vbYes Then
Set CText = Nothing: SText = "": SWks = Empty
ElseIf ContinueBox = vbNo Then
NextText = ""
End If
Else
NextText = SearchNext.Address
'Debug.Print SearchNext.Address
Set CText = SearchNext
End If
End Function
Private Function ReadCell(RType As String, RCell As Range, SheetNum As Long) As Variant
Dim addr As String
Select Case True
Case InStr(UCase(RType), UCase("row")) > 0
ReadCell = Worksheets(SheetNum).Range(RCell.Value).Row
Case InStr(UCase(RType), UCase("col")) > 0
ReadCell = Worksheets(SheetNum).Range(RCell.Text).Column
Case InStr(UCase(RType), UCase("val")) > 0
ReadCell = Worksheets(SheetNum).Range(RCell.Text).Value
Case Else
ReadCell = Error
End Select
End Function
Sub FindSomeText()
MsgBox InStr("Look in this string", "in")
End Sub
When I disable one of these functions with 's then it just jumps to a different one! So I have to disable ALL of them for the subroutine to function! It just doesn't make any sense to me... the function names are not accidentally sneaking into the code for the table update (and I would prefer to know WHY this is happening, instead of just "Well, those were one time practice functions, so I guess I'll delete them and go on with life"
I don't know if it helps any but here is the highlight selection event that is on the formatted table's sheet code:
Sheet4:
Sub worksheet_selectionchange(ByVal Target As Range)
Dim x, y, i, j, n As Long
Dim rng1, cell As Range
If Target.Column > 5 Or Target.Column < 2 Then Exit Sub
If tgb1.Value = False Then Exit Sub
x = UsedRange.Rows.Count
y = UsedRange.Find("Amount").Column - 1
Set cell = Range(Cells(2, 2), Cells(x, y))
Set rng1 = Application.Union(Target, cell)
If Range(Cells(2, 2), Cells(x, y)).Cells.Count = Application.Union(Target, cell).Cells.Count Then
Setformats
If Cells(Target.Row, UsedRange.Find("amount").Column) < 0 Then
With Range(Cells(Target.Row, 2), Cells(Target.Row, y))
.Font.FontStyle = "Bold"
With .Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.ColorIndex = 3
.TintAndShade = 0
.Weight = xlThin
End With
With .Borders(xlEdgeTop)
.LineStyle = xlContinuous
.ColorIndex = 3
.TintAndShade = 0
.Weight = xlThin
End With
End With
Cells(Target.Row, 1).Select
ElseIf Cells(Target.Row, UsedRange.Find("amount").Column) > 0 Then
With Range(Cells(Target.Row, 2), Cells(Target.Row, y))
With .Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.ColorIndex = 4
.TintAndShade = 0
.Weight = xlHairline
End With
With .Borders(xlEdgeTop)
.LineStyle = xlContinuous
.ColorIndex = 4
.TintAndShade = 0
.Weight = xlHairline
End With
End With
Cells(Target.Row, 1).Select
End If
End If
End Sub
Public Sub Setformats()
Dim x, y, i, j, n As Long
x = ActiveSheet.UsedRange.Rows.Count - 1
y = ActiveSheet.UsedRange.Columns.Count - 1
With Worksheets("USBank").Range(Cells(2, 2), Cells(x, y))
.Borders(xlDiagonalDown).LineStyle = xlNone
.Borders(xlDiagonalUp).LineStyle = xlNone
.Borders(xlEdgeLeft).LineStyle = xlNone
.Borders(xlEdgeTop).LineStyle = xlNone
.Borders(xlEdgeBottom).LineStyle = xlNone
.Borders(xlEdgeRight).LineStyle = xlNone
.Borders(xlInsideVertical).LineStyle = xlNone
.Borders(xlInsideHorizontal).LineStyle = xlNone
.Font.FontStyle = "regular"
End With
End Sub
Note: It's a bank statement(so can't show ya), 5 columns: Date, Action(debit or credit), Transaction(purchase, deposit, fee..), Vendor(Joe's Coffee),Amount(+/- $2.14) ...the scope of this project is just to increase skills in VBA
I have been trying to add borders to two ranges on two different worksheets.
In my case, sheet one has 14 rows whereas the second worksheet has 30 rows. Each worksheet has the same amount of columns. When I run my code, the first worksheet works fine but the second worksheet only has 14 rows that are bordered and the other 16 are left without a border. Why isn't my code bordering the last 16 columns of my second worksheet?
Sub lines()
Dim wb As Worksheet
Dim wb2 As Worksheet
Dim arrBorders As Variant, vBorder As Variant
Set wb = Worksheets("wb Summary")
Set wb2 = Worksheets("wb2 Summary")
arrBorders = Array(xlEdgeLeft, xlEdgeTop, xlEdgeBottom, _
xlEdgeRight, xlInsideVertical, xlInsideHorizontal)
With wb.Range("A2:H" & Cells(Rows.Count, "H").End(xlUp).Row)
For Each vBorder In arrBorders
With .Borders(vBorder)
.LineStyle = xlContinuous
.Weight = xlThin
End With
Next
End With
With wb2.Range("A2:H" & Cells(Rows.Count, "H").End(xlUp).Row)
For Each vBorder In arrBorders
With .Borders(vBorder)
.LineStyle = xlContinuous
.Weight = xlThin
End With
Next
End With
End Sub
You need to fully reference the sheets. I think you can also shorten your code by avoiding the loops.
Sub lines()
Dim wb As Worksheet
Dim wb2 As Worksheet
Set wb = Worksheets("wb Summary")
Set wb2 = Worksheets("wb2 Summary")
With wb.Range("A2:H" & wb.Cells(wb.Rows.Count, "H").End(xlUp).Row)
.Borders.LineStyle = xlContinuous
.Borders.Weight = xlThin
End With
With wb2.Range("A2:H" & wb2.Cells(wb2.Rows.Count, "H").End(xlUp).Row)
.Borders.LineStyle = xlContinuous
.Borders.Weight = xlThin
End With
End Sub
I have the below code and I want to do the following:
Go through a specific column based on its name (example "Company") and to change the border based on the values in that column (example "CompanyA","CompanyB", "CompanyC" etc.) to be Thick Box Border. This means "Company A" (50 rows) would get a border and "Company B" (5 rows) would get a border and so on.
Can this be done? Ty in advance!
Sub DrawBorders()
Dim rCell As Range
Dim rRange As Range
Set rRange = Range("A1", Range("A65536").End(xlUp))
For Each rCell In rRange
If Not IsEmpty(rCell) And _
Not IsEmpty(rCell.Offset(1, 0)) Then
With rCell
If .Value <> .Offset(1, 0).Value Then
With .EntireRow.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With
End If
End With
End If
Next rCell
End Sub
I have adjusted my code to fit your request. This will only put borders around desired company types. You may need to add further error catching to the IF-Statements depending on your data you're processing.
Sub DrawBoarders()
Dim rCell As Range
Dim rRange As Range
Dim Prev As String
Dim MyCell As String
Prev = ""
Set rRange = Range("A2", Range("A65536").End(xlUp))
Dim SpecificCompany(3) As String 'Using 3 companies (Company A, B, & C)
'Array of desired company names
SpecificCompany(0) = "CompanyA"
SpecificCompany(1) = "CompanyB"
SpecificCompany(2) = "CompanyC"
If IsInArray(Range("A1"), SpecificCompany) Then 'Check 1st row
With Range("A1").EntireRow.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With
End If
For Each rCell In rRange
If IsInArray(rCell.Value, SpecificCompany) And rCell.Value <> rCell.Offset(-1, 0).Value Then
With rCell.EntireRow.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With
End If
If Not IsEmpty(rCell) And _
Not IsEmpty(rCell.Offset(1, 0)) Then
If rCell.Value <> rCell.Offset(1, 0).Value Then
With rCell.EntireRow.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With
End If
End If
Next rCell
End Sub
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
I have a table conditional formatting macro (thanks Jeeped) that I would like to expand to loop through all tables across a range of worksheets. I suspect this is not the most efficient approach but the its the best I could cobble together, and even then it's not working. So far I'm stuck at two points below. Any assistance is greatly appreciated!
1) Setting ws to equal multiple worksheet codenames (e.g. Set ws = Worksheets(5,6,7))
2) Setting the range w/o a run-time error Set myRange = ws.ListObjects.DataBodyRange produces "Run-time error '438': Object doesn't support this property or method"
Current code is:
Sub ConditionalFormatting()
Dim ws As Excel.Worksheet
Dim lo As Excel.ListObject
Dim myRange As Range
Set ws = Worksheet(5) 'Would like to expand to include multiple worksheets!
Set myRange = ws.ListObjects.DataBodyRange
For Each lo In ws.ListObjects
With lo.FormatConditions
.FormatConditions.Delete
Call FormatRange(myRange, 10, "$E5=INDEX(Location,1,1)") 'Warehouse1
Call FormatRange(myRange, 10, "$E5=INDEX(Location,2,1)") 'Warehouse2
Call FormatRange(myRange, 10, "$E5=INDEX(Location,3,1)") 'Warehouse3
End With
Next lo
End Sub
Public Sub FormatRange(r As Range, clr As Integer, frml As String)
r.FormatConditions.Add Type:=xlExpression, Formula1:=frml
r.FormatConditions(r.FormatConditions.Count).Font.colorindex = clr
With r.FormatConditions(1).Borders(xlTop)
.LineStyle = xlContinuous
.Color = color
.TintAndShade = 0
.Weight = xlThin
End With
With r.FormatConditions(1).Borders(xlBottom)
.LineStyle = xlContinuous
.Color = color
.TintAndShade = 0
.Weight = xlThin
End With
r.FormatConditions(1).StopIfTrue = False
End Sub
Untested:
Sub ConditionalFormatting()
Dim ws As Excel.Worksheet
Dim lo As Excel.ListObject
Dim myRange As Range
Dim i
For Each i in Array(5, 6, 7)
Set ws = Worksheets(i)
For Each lo In ws.ListObjects
Set myRange = lo.DataBodyRange
myRange.FormatConditions.Delete
FormatRange myRange, 10, "$E5=INDEX(Location,1,1)" 'Warehouse1
FormatRange myRange, 10, "$E5=INDEX(Location,2,1)" 'Warehouse2
FormatRange myRange, 10, "$E5=INDEX(Location,3,1)" 'Warehouse3
Next lo
Next i
End Sub
Just like you loop over the listobject collection "Listobjects", you can loop over the Worksheet collection "WorkSheets"
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
'...
Next ws
used this sample for my code to reset filter of all my tables
Dim ws As Worksheet
Dim lo As ListObject
For Each ws In ThisWorkbook.Worksheets
For Each lo In ws.ListObjects
If lo.ShowAutoFilter Then
If lo.AutoFilter.FilterMode Then
lo.AutoFilter.ShowAllData
End If
End If
Next lo
Next ws
Hi i have the following code but it prommpts an error range of object_worksheet failed. I'm not sure what i'm doing wrong (i've found the vba code using record macro and simply copy and pasted except i've replaced all of selection to ws.range(emptyrow) to indicate the range is up to the last cell with values. Also, if i were to change the sub to sub highlightemptycell_change() and have if statement as such: "if any cells are changed then do the following" how would i write that in a vba language?
sub highlightemptycell()
Dim ws As Worksheet
Dim r As Range
Dim emptyrow As Long
Dim err As Range
Set ws = Worksheets("Master")
emptyrow = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1 '<<< safer....
ws.Range(emptyrow).FormatConditions(1).StopIfTrue = False
ws.Range(emptyrow).FormatConditions.Add Type:=xlExpression, Formula1:= _
"=ISBLANK(ws.range(emptyrow)"
ws.Range(emptyrow).FormatConditions(ws.Range(emptyrow).FormatConditions.Count).SetFirstPriority
With ws.Range(emptyrow).FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
End With
I'm not sure exactly what you are doing. In particular, I'm not sure of the significance of this line,
ws.Range(emptyrow).FormatConditions(1).StopIfTrue = False
especially when there are no conditional formats in the cell at the time it is executed.
But the following macro seems to do what yours would do if it were cleaned up a bit and written with proper syntax
Option Explicit
Sub highlightemptycell()
Dim ws As Worksheet
Dim r As Range
Dim emptyrow As Long
Dim err As Range
Dim rEmptyRow As Range '<-- range object added to use below
Set ws = Worksheets("Master")
Set rEmptyRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(rowoffset:=1) '<<< safer....
With rEmptyRow.FormatConditions
If .Count > 0 Then .Item(1).StopIfTrue = False
.Add Type:=xlExpression, Formula1:= _
"=ISBLANK(" & rEmptyRow.Address & ")"
.Item(.Count).SetFirstPriority
With .Item(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
End With
End With
End Sub