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): 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.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())