319 lines
12 KiB
Python
319 lines
12 KiB
Python
import os, re, openpyxl
|
|
from openpyxl.cell import MergedCell
|
|
from openpyxl.utils import get_column_letter, column_index_from_string
|
|
|
|
|
|
def col_index_from_string(string):
|
|
return column_index_from_string(string) - 1
|
|
|
|
|
|
def row_index_from_string(string):
|
|
return int(string) - 1
|
|
|
|
|
|
class Excel:
|
|
__readonly__ = None
|
|
__autosave__ = None
|
|
__filename__ = None
|
|
__workbook__ = None
|
|
__workshet__ = None
|
|
|
|
def open(self, filename=None, sheet=None, read_only=False, auto_save=False):
|
|
"""打开Excel文档 | Open Excel document.
|
|
:param filename: 将要打开的Excel文档的文件路径 | The file path of the Excel document that will be opened.
|
|
:param sheet: 将要打开的工作表名称或索引,默认为当前活动工作表 | The name or index of the worksheet to open, defaults to the currently active worksheet.
|
|
:param read_only: 只读模式 | Read-only mode.
|
|
:param auto_save: 自动保存 | Auto save when modified.
|
|
:return:
|
|
"""
|
|
self.__readonly__ = read_only
|
|
if self.__workbook__:
|
|
raise Exception('文件已经打开 | File has been opened.')
|
|
if filename:
|
|
self.__filename__ = os.path.abspath(filename)
|
|
self.__workbook__ = openpyxl.load_workbook(filename, read_only=False)
|
|
self.__autosave__ = auto_save
|
|
self.select(sheet)
|
|
else:
|
|
self.__workbook__ = openpyxl.Workbook()
|
|
self.__readonly__ = False
|
|
self.__autosave__ = False
|
|
self.select(None)
|
|
self.sheetRename('Sheet1')
|
|
return self
|
|
|
|
def select(self, sheet):
|
|
"""选择活动工作表 | Select active worksheet.
|
|
:param sheet: 工作表名称或索引或工作表对象,默认为当前活动工作表 | Sheet name or index or sheet object, defaults to the currently active sheet.
|
|
:return:
|
|
"""
|
|
if isinstance(sheet, int):
|
|
self.__workshet__ = self.__workbook__[self.sheetList()[sheet]]
|
|
elif isinstance(sheet, str):
|
|
self.__workshet__ = self.__workbook__[sheet]
|
|
elif not sheet:
|
|
self.__workshet__ = self.__workbook__.active
|
|
else:
|
|
self.__workshet__ = sheet
|
|
if not self.__readonly__:
|
|
self.__workbook__.active = self.__workshet__
|
|
return self
|
|
|
|
def sheetName(self):
|
|
"""返回当前工作表名称 | Returns the current sheet name.
|
|
:return:
|
|
"""
|
|
return self.__workshet__.title
|
|
|
|
def sheetList(self):
|
|
"""返回当前工作簿的工作表名称列表 | Returns a list of sheet names for the current workbook.
|
|
:return:
|
|
"""
|
|
return self.__workbook__.sheetnames
|
|
|
|
def sheetNrow(self):
|
|
"""获取当前工作表的最大有效行 | Get the maximum valid number of rows for the current worksheet.
|
|
:return:
|
|
"""
|
|
return self.__workshet__.max_row
|
|
|
|
def sheetNcol(self):
|
|
"""获取当前工作表的最大有效列 | Get the maximum valid number of cols for the current worksheet.
|
|
:return:
|
|
"""
|
|
return self.__workshet__.max_column
|
|
|
|
def sheetRename(self, name=None):
|
|
if not name:
|
|
name = 'Sheet'
|
|
self.__workshet__.title = name
|
|
self.saveAuto()
|
|
return True
|
|
|
|
def sheetCreate(self, name=None):
|
|
if not name:
|
|
currentList = self.sheetList()
|
|
nextNo = len(currentList) + 1
|
|
for i in range(0, 99):
|
|
name = 'Sheet' + str(nextNo)
|
|
if name in currentList:
|
|
nextNo = nextNo + 1
|
|
continue
|
|
else:
|
|
break
|
|
self.__workbook__.create_sheet(name)
|
|
self.select(name)
|
|
self.saveAuto()
|
|
return self
|
|
|
|
def sheetDelete(self):
|
|
self.__workbook__.remove(self.__workshet__)
|
|
self.select(0)
|
|
self.saveAuto()
|
|
return self
|
|
|
|
def cellSelect(self, cell):
|
|
"""设置活动单元格 | Set active cell.
|
|
:param cell:
|
|
:return:
|
|
"""
|
|
if not self.__readonly__:
|
|
try:
|
|
cell_letter = cell.column_letter + str(cell.row)
|
|
self.__workshet__.sheet_view.selection[0].activeCell = cell_letter
|
|
self.__workshet__.sheet_view.selection[0].sqref = cell_letter
|
|
except:
|
|
pass
|
|
|
|
def cellGet(self, row: int = None, col: int = None, cell: str = None):
|
|
if cell:
|
|
cell_object = self.__workshet__[cell]
|
|
else:
|
|
if row < 0 or col < 0:
|
|
raise Exception('行或列值必须大于等于0 | Row or column values must be at least 0.')
|
|
cell_object = self.__workshet__.cell(row=row + 1, column=col + 1)
|
|
cell_object = self._parseMergedCell(cell_object)
|
|
self.cellSelect(cell=cell_object)
|
|
return cell_object.value
|
|
|
|
def cellPut(self, row: int = None, col: int = None, cell: str = None, value=None):
|
|
if cell:
|
|
cell_object = self.__workshet__[cell]
|
|
else:
|
|
if row < 0 or col < 0:
|
|
raise Exception('行或列值必须大于等于0 | Row or column values must be at least 0.')
|
|
cell_object = self.__workshet__.cell(row=row + 1, column=col + 1)
|
|
cell_object = self._parseMergedCell(cell_object)
|
|
self.cellSelect(cell=cell_object)
|
|
cell_object.value = value
|
|
self.saveAuto()
|
|
return True
|
|
|
|
def cellGetView(self, area='', from_col=0, from_row=0, to_col=0, to_row=0, ocell=False):
|
|
cellList = self._viewGetOfCell(area=area, from_col=from_col, from_row=from_row, to_col=to_col, to_row=to_row)
|
|
result = []
|
|
for lineList in cellList:
|
|
lineResult = []
|
|
for cellObject in lineList:
|
|
lineResult.append(cellObject if ocell else cellObject.value)
|
|
result.append(lineResult)
|
|
return result
|
|
|
|
def cellPutView(self, area='', from_col=0, from_row=0, to_col=0, to_row=0, value=None):
|
|
if not value or not isinstance(value, list):
|
|
return False
|
|
values = self._viewGetOfCell(area=area, from_col=from_col, from_row=from_row, to_col=to_col, to_row=to_row)
|
|
valuesLen = len(values)
|
|
for i in range(0, valuesLen):
|
|
online = values[i]
|
|
onlineLen = len(online)
|
|
for j in range(0, onlineLen):
|
|
oncell = online[j]
|
|
try:
|
|
oncell.value = value[i][j]
|
|
except:
|
|
pass
|
|
self.saveAuto()
|
|
return True
|
|
|
|
def save(self, filename=None):
|
|
"""保存 | Save.
|
|
:param filename: 另存为的文件路径,默认为保存文件 | The file path to save as, the default is to save the file.
|
|
:return:
|
|
"""
|
|
if filename is None and self.__readonly__:
|
|
raise Exception('只读模式 | Read-only')
|
|
self.__workbook__.save(filename or self.__filename__)
|
|
return True
|
|
|
|
def saveAuto(self):
|
|
if self.__autosave__:
|
|
return self.save()
|
|
|
|
def saveExit(self):
|
|
"""保存并退出 | Save and exit.
|
|
:return:
|
|
"""
|
|
self.save()
|
|
self.exit()
|
|
return True
|
|
|
|
def exit(self):
|
|
"""退出 | Close the workbook and exit.
|
|
:return:
|
|
"""
|
|
self.__workbook__.close()
|
|
self.__workshet__ = None
|
|
self.__workbook__ = None
|
|
self.__filename__ = None
|
|
self.__autosave__ = None
|
|
self.__readonly__ = None
|
|
return True
|
|
|
|
def _viewGetOfCell(self, area='', from_col=0, from_row=0, to_col=0, to_row=0):
|
|
minCol = from_col
|
|
minRow = from_row
|
|
maxCol = to_col
|
|
maxRow = to_row
|
|
if area:
|
|
area = area + ':'
|
|
area = area.upper()
|
|
area = area.split(':')
|
|
minCell = area[0]
|
|
maxCell = area[1]
|
|
minColList = re.findall('([A-Z]+)', minCell)
|
|
minRowList = re.findall('([0-9]+)', minCell)
|
|
maxColList = re.findall('([A-Z]+)', maxCell)
|
|
maxRowList = re.findall('([0-9]+)', maxCell)
|
|
minColString = (minColList and minColList[0]) or ''
|
|
minRowString = (minRowList and minRowList[0]) or ''
|
|
maxColString = (maxColList and maxColList[0]) or ''
|
|
maxRowString = (maxRowList and maxRowList[0]) or ''
|
|
ncols = self.sheetNcol()
|
|
nrows = self.sheetNrow()
|
|
if minCell:
|
|
minCol = minColString or 'A'
|
|
minCol = column_index_from_string(minCol) - 1
|
|
minRow = minRowString or '1'
|
|
minRow = int(minRow) - 1
|
|
if maxCell:
|
|
if minColString and minRowString:
|
|
maxCol = maxColString or get_column_letter(ncols)
|
|
maxCol = column_index_from_string(maxCol) - 1
|
|
maxRow = maxRowString or nrows
|
|
maxRow = int(maxRow) - 1
|
|
elif minColString and minRowString == '':
|
|
maxCol = column_index_from_string(maxColString) - 1
|
|
maxRow = nrows - 1
|
|
elif minRowString and minColString == '':
|
|
maxCol = ncols - 1
|
|
maxRow = int(maxRowString) - 1
|
|
else:
|
|
if minColString and minRowString:
|
|
maxCol = minCol
|
|
maxRow = minRow
|
|
elif minColString and minRowString == '':
|
|
maxCol = minCol
|
|
maxRow = nrows - 1
|
|
elif minRowString and minColString == '':
|
|
maxCol = ncols - 1
|
|
maxRow = minRow
|
|
cellList = self.__workshet__._cells_by_row(min_col=minCol + 1, min_row=minRow + 1,
|
|
max_col=maxCol + 1, max_row=maxRow + 1)
|
|
result = []
|
|
for lineList in cellList:
|
|
lineResult = []
|
|
for cellObject in lineList:
|
|
lineResult.append(self._parseMergedCell(cellObject))
|
|
result.append(lineResult)
|
|
return result
|
|
|
|
def _parseMergedCell(self, cell):
|
|
if isinstance(cell, MergedCell):
|
|
for mergeArea in self.__workshet__.merged_cells.ranges:
|
|
if cell.coordinate in mergeArea:
|
|
cell = self.__workshet__.cell(row=mergeArea.min_row, column=mergeArea.min_col)
|
|
return cell
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Example.
|
|
# 创建新的Excel文件
|
|
# excel = Excel().open()
|
|
# 打开现有Excel文件
|
|
# excel = Excel().open(filename='./example.xlsx')
|
|
excel = Excel().open(filename='./example.xlsx', read_only=False, auto_save=False)
|
|
print(excel.sheetList())
|
|
excel.select(0)
|
|
excel.select('Sheet1')
|
|
print(excel.cellGet(cell='A1'))
|
|
print(excel.cellPut(cell='A1', value='标题'))
|
|
print(excel.cellGetView(area='A1:F5'))
|
|
print(excel.cellGetView(area='A:C'))
|
|
print(excel.cellGetView(area='1:5'))
|
|
print(excel.cellGetView(area='A1'))
|
|
print(excel.cellGetView(area='A'))
|
|
print(excel.cellGetView(area='1'))
|
|
print(excel.cellPutView(area='A1:Z256', value=
|
|
[
|
|
['1', '2', '3', '4', '5'],
|
|
['A', 'B', 'C', 'D', 'E'],
|
|
['A', 'B', 'C', 'D', 'E'],
|
|
['A', 'B', 'C', 'D', 'E']
|
|
]
|
|
))
|
|
print(excel.sheetRename('表一'))
|
|
print(excel.sheetCreate('表二'))
|
|
print(excel.sheetCreate('表三'))
|
|
print(excel.sheetCreate('表四'))
|
|
print(excel.sheetCreate('表五'))
|
|
print(excel.sheetCreate('测试'))
|
|
print(excel.select('测试').sheetDelete())
|
|
print(excel.sheetList())
|
|
print(excel.sheetName())
|
|
print(excel.sheetNrow())
|
|
print(excel.sheetNcol())
|
|
print(excel.save())
|
|
print(excel.save('./example_backup.xlsx'))
|
|
print(excel.exit())
|