TL;DR — A border is a property of an edge, not of a cell. A range has eight addressable borders: the four outer edges (
xlEdgeLeft,xlEdgeRight,xlEdgeTop,xlEdgeBottom), the two interior gridline sets (xlInsideVertical,xlInsideHorizontal), and two diagonals. The bareRange("A1:D10").Borderscollection means all of them, so.Borders.LineStyle = xlContinuousboxes every cell in the block, not just the outline. UseRange("A1:D10").BorderAround LineStyle:=xlContinuous, Weight:=xlThinwhen you want only the outer frame.
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Report")
' Outline the block, then a thin rule under the header row - two different jobs.
ws.Range("A1:D10").BorderAround LineStyle:=xlContinuous, Weight:=xlMedium
ws.Range("A1:D1").Borders(xlEdgeBottom).LineStyle = xlContinuous
Adding borders is one of the first things people automate, and it is also where a small
misunderstanding produces the most head-scratching result in the whole formatting toolkit: you asked
for "a border" and Excel drew a grid around every cell. This guide is built on one idea that makes
the rest predictable: Borders is a collection of edges, and touching the collection touches every
edge. Once you see borders as per-edge, the outline-versus-grid confusion disappears.
What you'll learn
- The mental model — a border belongs to an edge, and
Bordersis the whole set of them - The rule that matters most —
.Bordersboxes every cell,.BorderArounddraws only the frame - The three properties that make a line visible —
LineStyle,WeightandColor - Addressing one edge at a time with
xlEdgeBottom,xlInsideVerticaland the rest - Clearing borders cleanly with
xlLineStyleNone - Why borders are decoration, not structure — and what to reach for instead
The mental model: a border is a property of an edge
This is the sibling of the appearance cluster — Font styles the text, Interior
fills behind it, and borders draw the lines around it. But borders differ from those in one
important way: a cell does not have "a border," it has up to eight of them, and VBA reaches each
through the Borders collection indexed by an XlBordersIndex constant:
' The eight addressable edges of any range:
' xlEdgeLeft, xlEdgeRight, xlEdgeTop, xlEdgeBottom - the four outer sides
' xlInsideVertical, xlInsideHorizontal - gridlines BETWEEN cells
' xlDiagonalDown, xlDiagonalUp - corner-to-corner
ws.Range("B2").Borders(xlEdgeBottom).LineStyle = xlContinuous ' just the bottom of B2
Hold that picture — eight edges, each independently addressable — and every later rule is a
consequence of it. The interior borders only exist when the range spans more than one cell (a single
cell has no "between"), which is exactly why the same line of code behaves differently on B2 versus
B2:E20.
The rule that matters most: .Borders is every edge, .BorderAround is only the frame
Here is the one line that catches everyone. On a multi-cell range, setting the collection applies to all edges at once — outer sides and the gridlines between cells:
' Boxes EVERY cell in the block - outline plus all the interior gridlines.
ws.Range("A1:D10").Borders.LineStyle = xlContinuous
That is rarely what people mean when they say "put a border on it." If you want a single rectangle
around the whole block and nothing inside, use the BorderAround method, which only ever touches
the four outer edges:
' Just the outer frame - no interior lines.
ws.Range("A1:D10").BorderAround LineStyle:=xlContinuous, Weight:=xlThick
The distinction is the crux of the topic: .Borders = the grid, .BorderAround = the outline.
If you genuinely want both — a boxed block with lighter interior lines — do it in two passes: set
.Borders.LineStyle for the interior, then BorderAround for a heavier frame on top. Reaching for
.Borders when you meant .BorderAround is the number-one reason a "single border" comes out as a
full cage.
The three properties that make a line: LineStyle, Weight, Color
A border edge is invisible until it has a LineStyle. That is the property that turns a line on; the
other two refine it. Because you usually set all three together, With keeps it
readable:
With ws.Range("A1:D10").Borders(xlEdgeBottom)
.LineStyle = xlContinuous ' turns the line ON - without this, nothing shows
.Weight = xlMedium ' xlHairline, xlThin, xlMedium, xlThick
.Color = RGB(0, 32, 96) ' 24-bit RGB, same as Font.Color
End With
Three things worth knowing. LineStyle is the on/off switch — xlContinuous, xlDash, xlDot,
xlDashDot, xlDouble, xlSlantDashDot, and so on — and setting it is what makes the border
appear. Weight is one of four constants (xlHairline, xlThin, xlMedium, xlThick), not a point
number. And not every LineStyle/Weight pair is legal: xlHairline implies a continuous thin
line, and xlDouble ignores Weight entirely — so if a weight seems to have no effect, the line
style is overriding it. For color, use .Color = RGB(r, g, b) (the same 24-bit space as Font.Color,
covered in VBA Font); avoid .ColorIndex unless you are matching a legacy palette.
One edge at a time
Most real borders are not "all or nothing." A rule under a header, a divider between two sections, a thick left margin — each is a single edge:
' A heavy line under the header, a light divider between columns B and C.
ws.Range("A1:D1").Borders(xlEdgeBottom).Weight = xlThick
ws.Range("A1:D1").Borders(xlEdgeBottom).LineStyle = xlContinuous
ws.Range("C2:C20").Borders(xlEdgeLeft).LineStyle = xlDot
xlInsideVertical and xlInsideHorizontal give you the gridlines between cells without the outer
frame — the inverse of BorderAround. Address the edges you want and leave the rest untouched; each
Borders(index) is independent, so setting the bottom never disturbs the top.
Clearing borders
To remove borders, set the line style to none. On the collection it clears everything; on one index it clears just that edge:
ws.Range("A1:D10").Borders.LineStyle = xlLineStyleNone ' remove all borders in the block
ws.Range("A1:D1").Borders(xlEdgeBottom).LineStyle = xlLineStyleNone ' remove just the header rule
xlLineStyleNone and xlNone are interchangeable here. Note that clearing borders on a range does
not touch borders that Excel draws as part of a Table style or Conditional Formatting — those are
owned by the object that created them, not by the cell, so if a line refuses to disappear, look for a
Table or a format rule rather than a stray Borders call.
Borders are decoration, not structure
Worth saying plainly, because it saves rework: a border is purely visual. It does not group rows, does
not define a range, and is invisible to every formula. If you are drawing borders to make a block
look like a table so you can refer to it later, convert it to a real Excel Table (ListObject)
instead — you get the boxed look and a named range, structured references, and automatic banding.
Use hand-drawn borders for the finishing touches on a report you are about to print or export, not as
a way to give data a shape your code can read. The shape has to live in the data, the way it does in
VBA Range; the border is just the paint on top.
How ExcelMaster helps
Borders hide more decisions than they look like they should: collection versus BorderAround, which
of eight edges you actually meant, a Weight that a LineStyle quietly overrides, and a line that
will not clear because a Table owns it. Each wrong turn is silent — a grid where you wanted an
outline, or no change at all.
ExcelMaster lets you describe the
result instead. Say "box the summary block with a thick outline and a thin line under the header," and
it uses BorderAround for the frame and Borders(xlEdgeBottom) for the rule — setting LineStyle
first so the line actually shows, and picking Weight and Color to match. You keep the workbook and
the code; you skip the pass where .Borders caged every cell you only wanted to outline.
Frequently asked questions
How do I add a border to a range in Excel VBA?
For a single outline around the whole range, use Range("A1:D10").BorderAround LineStyle:=xlContinuous, Weight:=xlThin — it draws only the outer frame. For one specific edge, set
it on the collection index, for example Range("A1:D1").Borders(xlEdgeBottom).LineStyle = xlContinuous. Always set LineStyle (not just Weight), because the line style is what makes a
border visible.
Why does Range.Borders.LineStyle box every cell instead of drawing one outline?
Because Range.Borders is the whole collection of edges — the four outer sides and the interior
gridlines between cells. Setting LineStyle on the collection applies to all of them, so a multi-cell
range gets a border around every cell. Use BorderAround to touch only the outer frame, or address
individual edges like Borders(xlEdgeTop) for one side at a time.
What is the difference between Borders and BorderAround in VBA?
Borders(index) is a collection you index by edge (xlEdgeLeft, xlInsideVertical, and so on), and
setting the bare collection affects every edge. BorderAround is a method that draws only the four
outer edges of the range in one call, leaving interior gridlines alone. Use BorderAround for an
outline and the Borders collection when you need interior lines or a single edge.
How do I remove borders from a range in VBA?
Set the line style to none: Range("A1:D10").Borders.LineStyle = xlLineStyleNone clears every border
in the block, and Range("A1:D1").Borders(xlEdgeBottom).LineStyle = xlLineStyleNone clears just one
edge. If a border refuses to clear, it is probably drawn by an Excel Table style or a Conditional
Formatting rule, which own their own borders.
What LineStyle and Weight values can I use for VBA borders?
LineStyle accepts xlContinuous, xlDash, xlDot, xlDashDot, xlDashDotDot, xlDouble,
xlSlantDashDot and xlLineStyleNone. Weight is one of four constants — xlHairline, xlThin,
xlMedium, xlThick — not a point size. Some combinations are constrained: xlDouble ignores
Weight, so if a weight seems to have no effect, the line style is the reason.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-14.
Related guides: VBA Merge Cells · VBA Cell Color · VBA Font · VBA With · VBA Range
