forked from Alsan/Post_finder
125 lines
3.0 KiB
Python
125 lines
3.0 KiB
Python
# Copyright (c) 2010-2024 openpyxl
|
|
|
|
from itertools import chain
|
|
|
|
from openpyxl.descriptors.serialisable import Serialisable
|
|
from openpyxl.descriptors import (
|
|
MinMax,
|
|
Typed,
|
|
String,
|
|
Strict,
|
|
)
|
|
from openpyxl.worksheet.worksheet import Worksheet
|
|
from openpyxl.utils import (
|
|
get_column_letter,
|
|
range_to_tuple,
|
|
quote_sheetname
|
|
)
|
|
|
|
|
|
class DummyWorksheet:
|
|
|
|
|
|
def __init__(self, title):
|
|
self.title = title
|
|
|
|
|
|
class Reference(Strict):
|
|
|
|
"""
|
|
Normalise cell range references
|
|
"""
|
|
|
|
min_row = MinMax(min=1, max=1000000, expected_type=int)
|
|
max_row = MinMax(min=1, max=1000000, expected_type=int)
|
|
min_col = MinMax(min=1, max=16384, expected_type=int)
|
|
max_col = MinMax(min=1, max=16384, expected_type=int)
|
|
range_string = String(allow_none=True)
|
|
|
|
def __init__(self,
|
|
worksheet=None,
|
|
min_col=None,
|
|
min_row=None,
|
|
max_col=None,
|
|
max_row=None,
|
|
range_string=None
|
|
):
|
|
if range_string is not None:
|
|
sheetname, boundaries = range_to_tuple(range_string)
|
|
min_col, min_row, max_col, max_row = boundaries
|
|
worksheet = DummyWorksheet(sheetname)
|
|
|
|
self.worksheet = worksheet
|
|
self.min_col = min_col
|
|
self.min_row = min_row
|
|
if max_col is None:
|
|
max_col = min_col
|
|
self.max_col = max_col
|
|
if max_row is None:
|
|
max_row = min_row
|
|
self.max_row = max_row
|
|
|
|
|
|
def __repr__(self):
|
|
return str(self)
|
|
|
|
|
|
def __str__(self):
|
|
fmt = u"{0}!${1}${2}:${3}${4}"
|
|
if (self.min_col == self.max_col
|
|
and self.min_row == self.max_row):
|
|
fmt = u"{0}!${1}${2}"
|
|
return fmt.format(self.sheetname,
|
|
get_column_letter(self.min_col), self.min_row,
|
|
get_column_letter(self.max_col), self.max_row
|
|
)
|
|
|
|
|
|
__str__ = __str__
|
|
|
|
|
|
|
|
def __len__(self):
|
|
if self.min_row == self.max_row:
|
|
return 1 + self.max_col - self.min_col
|
|
return 1 + self.max_row - self.min_row
|
|
|
|
|
|
def __eq__(self, other):
|
|
return str(self) == str(other)
|
|
|
|
|
|
@property
|
|
def rows(self):
|
|
"""
|
|
Return all rows in the range
|
|
"""
|
|
for row in range(self.min_row, self.max_row+1):
|
|
yield Reference(self.worksheet, self.min_col, row, self.max_col, row)
|
|
|
|
|
|
@property
|
|
def cols(self):
|
|
"""
|
|
Return all columns in the range
|
|
"""
|
|
for col in range(self.min_col, self.max_col+1):
|
|
yield Reference(self.worksheet, col, self.min_row, col, self.max_row)
|
|
|
|
|
|
def pop(self):
|
|
"""
|
|
Return and remove the first cell
|
|
"""
|
|
cell = "{0}{1}".format(get_column_letter(self.min_col), self.min_row)
|
|
if self.min_row == self.max_row:
|
|
self.min_col += 1
|
|
else:
|
|
self.min_row += 1
|
|
return cell
|
|
|
|
|
|
@property
|
|
def sheetname(self):
|
|
return quote_sheetname(self.worksheet.title)
|