如何扩展工作表 class
How to extend the Worksheet class
您好想在 openpyxl
中扩展工作表 - class。但是,由于这是一个二级容器,我不确定如何。通常在 openpyxl 中,你用 wb = Workbook()
实例化,然后用 ws = wb.active
或 wb.create_sheet()
得到一个 Excel-Worksheet。我在这里对如何进行有点困惑。当然可以:
from openpyxl.worksheet.worksheet import Worksheet
class SheetExtended(Worksheet):
def adjust_column_width(self):
for col in self.columns:
max_length = 0
column = col[0].column_letter
for cell in col:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
adjusted_width = (max_length + 2) * 1.2
self.column_dimensions[column].width = adjusted_width
不过我会把它与 Workbook
-class?
结合起来
以下是您可以如何进行“猴子修补”Worksheet
,所以您所做的是有效的:
from openpyxl import load_workbook
from openpyxl.worksheet.worksheet import Worksheet
def adjust_column_width(self):
for col in self.columns:
max_length = 0
column = col[0].column_letter
for cell in col:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
adjusted_width = (max_length + 2) * 1.2
self.column_dimensions[column].width = adjusted_width
# monkey patching the new method onto the existing class
Worksheet.adjust_column_width = adjust_column_width
# an example of using it
wb = load_workbook('wb.xlsx')
wb.active.adjust_column_width()
wb.save('wb.xlsx')
如果您需要 class 方法,您可以这样做:
from types import MethodType
def some_class_method(cls):
print(cls.__name__)
Worksheet.some_class_method = MethodType(some_class_method, Worksheet)
一般来说,解决问题的方法比猴子修补 classes 更好。 Monkey 补丁添加了 class 用户意想不到的行为,特别是因为它仍然是 'is' 原来的 class,不知道它在现有 class 中的新功能.
您所询问的操作可以很容易地成为一个以 Worksheet
作为参数并对其进行修改的函数,这将是一个更好的解决方案。所以这里真正的问题是:为什么你认为修改 class (或你建议的 subclassing )是更好的解决方案?用例是什么?
谢谢@Grismar 的回答。它把我推向了正确的方向。这个问题的问题是我没有在我的问题中包含 use-case。
我的用例是我想创建一个实用程序 class,我可以多次重复使用它来创建我的 Excel-Files。我有几次生成 Excel-Files 并且每一代的逻辑都不同。
因此,我从 this great post 中了解了 RealPython 中继承和组合之间的区别。我从来没有有意识地做过组合class,但是考虑到当你尝试继承时openpyxl
的依赖问题,我认为这是最好的解决方案。
看起来像这样:
class ExcelGeneration:
def __init__(self, workbook=None, sheetname=None) -> None:
self.book = workbook if workbook else Workbook()
self.sheet = self.__set_sheet_name(sheetname)
def __set_sheet_name(self, sheetname):
if sheetname and sheetname in self.book.worksheets:
return self.book[sheetname]
else:
sheet = self.book.active
sheet.title = sheetname
return sheet
这种方法的问题是您现在总是必须使用 self.sheet
而不是 self
,但是对于我的用例,我愿意支付那个价格。
您好想在 openpyxl
中扩展工作表 - class。但是,由于这是一个二级容器,我不确定如何。通常在 openpyxl 中,你用 wb = Workbook()
实例化,然后用 ws = wb.active
或 wb.create_sheet()
得到一个 Excel-Worksheet。我在这里对如何进行有点困惑。当然可以:
from openpyxl.worksheet.worksheet import Worksheet
class SheetExtended(Worksheet):
def adjust_column_width(self):
for col in self.columns:
max_length = 0
column = col[0].column_letter
for cell in col:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
adjusted_width = (max_length + 2) * 1.2
self.column_dimensions[column].width = adjusted_width
不过我会把它与 Workbook
-class?
以下是您可以如何进行“猴子修补”Worksheet
,所以您所做的是有效的:
from openpyxl import load_workbook
from openpyxl.worksheet.worksheet import Worksheet
def adjust_column_width(self):
for col in self.columns:
max_length = 0
column = col[0].column_letter
for cell in col:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
adjusted_width = (max_length + 2) * 1.2
self.column_dimensions[column].width = adjusted_width
# monkey patching the new method onto the existing class
Worksheet.adjust_column_width = adjust_column_width
# an example of using it
wb = load_workbook('wb.xlsx')
wb.active.adjust_column_width()
wb.save('wb.xlsx')
如果您需要 class 方法,您可以这样做:
from types import MethodType
def some_class_method(cls):
print(cls.__name__)
Worksheet.some_class_method = MethodType(some_class_method, Worksheet)
一般来说,解决问题的方法比猴子修补 classes 更好。 Monkey 补丁添加了 class 用户意想不到的行为,特别是因为它仍然是 'is' 原来的 class,不知道它在现有 class 中的新功能.
您所询问的操作可以很容易地成为一个以 Worksheet
作为参数并对其进行修改的函数,这将是一个更好的解决方案。所以这里真正的问题是:为什么你认为修改 class (或你建议的 subclassing )是更好的解决方案?用例是什么?
谢谢@Grismar 的回答。它把我推向了正确的方向。这个问题的问题是我没有在我的问题中包含 use-case。
我的用例是我想创建一个实用程序 class,我可以多次重复使用它来创建我的 Excel-Files。我有几次生成 Excel-Files 并且每一代的逻辑都不同。
因此,我从 this great post 中了解了 RealPython 中继承和组合之间的区别。我从来没有有意识地做过组合class,但是考虑到当你尝试继承时openpyxl
的依赖问题,我认为这是最好的解决方案。
看起来像这样:
class ExcelGeneration:
def __init__(self, workbook=None, sheetname=None) -> None:
self.book = workbook if workbook else Workbook()
self.sheet = self.__set_sheet_name(sheetname)
def __set_sheet_name(self, sheetname):
if sheetname and sheetname in self.book.worksheets:
return self.book[sheetname]
else:
sheet = self.book.active
sheet.title = sheetname
return sheet
这种方法的问题是您现在总是必须使用 self.sheet
而不是 self
,但是对于我的用例,我愿意支付那个价格。