Skip to content

Commit

Permalink
autofilter: fix range clash with table autofilter
Browse files Browse the repository at this point in the history
Fix issue where a worksheet and table filter could overlap and
create a corrupt file.

Closes #1102
  • Loading branch information
jmcnamara committed Jan 1, 2025
1 parent efd0718 commit 6b698c2
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
18 changes: 18 additions & 0 deletions xlsxwriter/test/workbook/test_overlap_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,21 @@ def test_overlaps08(self):

with self.assertRaises(OverlappingRange):
worksheet.merge_range("B3:C3", "")

def test_overlaps09(self):
"""Test Worksheet range overlap exceptions"""
worksheet = self.workbook.add_worksheet()

worksheet.add_table("A1:C5", {"autofilter": True})

with self.assertRaises(OverlappingRange):
worksheet.autofilter("A1:C5")

def test_overlaps10(self):
"""Test Worksheet range overlap exceptions"""
worksheet = self.workbook.add_worksheet()

worksheet.autofilter("A1:C5")

with self.assertRaises(OverlappingRange):
worksheet.add_table("A1:C5", {"autofilter": True})
24 changes: 21 additions & 3 deletions xlsxwriter/worksheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -2390,7 +2390,7 @@ def autofilter(self, first_row, first_col, last_row, last_col):
if last_col < first_col:
(first_col, last_col) = (last_col, first_col)

# Build up the print area range "Sheet1!$A$1:$C$13".
# Build up the autofilter area range "Sheet1!$A$1:$C$13".
area = self._convert_name_area(first_row, first_col, last_row, last_col)
ref = xl_range(first_row, first_col, last_row, last_col)

Expand All @@ -2400,7 +2400,16 @@ def autofilter(self, first_row, first_col, last_row, last_col):

# Store the filter cell positions for use in the autofit calculation.
for col in range(first_col, last_col + 1):
self.filter_cells[(first_row, col)] = True
# Check that the autofilter doesn't overlap a table filter.
if self.filter_cells.get((first_row, col)):
filter_type, filter_range = self.filter_cells.get((first_row, col))
if filter_type == "table":
raise OverlappingRange(
f"Worksheet autofilter range '{ref}' overlaps previous "
f"Table autofilter range '{filter_range}'."
)

self.filter_cells[(first_row, col)] = ("worksheet", ref)

def filter_column(self, col, criteria):
"""
Expand Down Expand Up @@ -3591,7 +3600,16 @@ def add_table(self, first_row, first_col, last_row, last_col, options=None):
# Store the filter cell positions for use in the autofit calculation.
if options["autofilter"]:
for col in range(first_col, last_col + 1):
self.filter_cells[(first_row, col)] = True
# Check that the table autofilter doesn't overlap a worksheet filter.
if self.filter_cells.get((first_row, col)):
filter_type, filter_range = self.filter_cells.get((first_row, col))
if filter_type == "worksheet":
raise OverlappingRange(
f"Table autofilter range '{cell_range}' overlaps previous "
f"Worksheet autofilter range '{filter_range}'."
)

self.filter_cells[(first_row, col)] = ("table", cell_range)

return 0

Expand Down

0 comments on commit 6b698c2

Please sign in to comment.