Python openpyxl打开有公式的表格,如果直接读取,会出现有公式的单元格为空或零的情况。
参见:
https://blog.csdn.net/weixin_45903952/article/details/105073611?utm_medium=distribute.wap_relevant.none-task-blog-title-3
wb = openpyxl.load_workbook(‘test.xlsx’, data_only=True)
当’test.xlsx’被生成并在Excel程序中打开并保存之后(这个过程Excel会把公式结果计算出来),该文件附带有两套值,一套是公式全都没有计算的(data_only=False(默认)),一套是公式计算了结果的(data_only=True)。(如果没有被Excel打开并保存,则只有一套值(data_only=False的那套,公式没有计算结果的)。
此时,以data_only=True或默认data_only=False打开会得到两种不同的结果,各自独立,即data_only=True状态下打开的,会发现公式结果为None(空值)或者一个计算好的常数,而不会看到它原本的公式是如何。而data_only=False则只会显示公式而已。因此,data_only=True状态下打开,如果最后用save()函数保存了,则原xlsx文件中,公式会被替换为常数结果或空值。而data_only=False状态下打开,最后用save()函数保存了的话,原xlsx文件也会只剩下data_only=False的那套值(即公式),另一套(data_only=True)的值会丢失,如想重新获得两套值,则仍旧需要用Excel程序打开该文件并保存。
def justOpen(strFileName):"""模拟手工打开excel表:param strFileName: 打开的excel文件名(后缀.xlsx格式)"""try:xlApp = Dispatch("Excel.Application")xlApp.Visible = FalsexlBook = xlApp.Workbooks.Open(os.path.join(os.getcwd(), strFileName))xlBook.Save()xlBook.Close()except:print("请手工打开 %s 后,随便修改一个空值并保存" % strFileName)
**
我的完整测试代码如下:
**
"""
================================================
Python模块:Python操作excel(.xlsx)封装类MyPyExcel
================================================
"""import openpyxl
from openpyxl.worksheet.worksheet import Worksheet
import os
from win32com.client import Dispatchclass MyPyExcel:"""Python操作excel(.xlsx)封装类MyPyExcel"""def __init__(self, strOpenFilePath, data_only=True):"""初始化功能,加载excel文件: strOpenFilePath: 要打开的excel(.xlsx)文件路径"""self.strOpenFilePath = strOpenFilePath # 工作簿路径self.workbook = None # 工作簿对象self.worksheet = None # 工作表对象path = os.path.join(os.getcwd() + "\\" + strOpenFilePath)# 文件存在就加载,不存在就创建工作簿。if os.path.exists(path):# 文件存在就加载,加载失败就报错。try:self.workbook = openpyxl.load_workbook(strOpenFilePath, data_only=data_only)except:print("加载excel文件失败!请检查!")raiseelse:print("加载excel文件不存在!自动创建文件!")self.workbook = openpyxl.Workbook() # 创建工作簿def openWorkSheet(self, strSheetName) -> Worksheet: # 表示此函数的返回值,是一个这样的类型,函数注解"""打开工作表功能:param strSheetName: 要打开的工作表名称:return: 返回打开的工作表Worksheet对象"""if strSheetName in self.workbook.sheetnames:self.worksheet = self.workbook[strSheetName]else:print("表单名称在当前excel文件中不存在,请检查表单名称!")return self.worksheetdef getDataByCell(self, nRow, nColumn):"""读取一个单元格的数据功能:param nRow: 行号1,2,...:param nColumn: 列号1,2,...:return: 指定单元格数值"""# 判断行号、列号有效if self.isCheckNumValid(nRow, self.worksheet.max_row) is True and \self.isCheckNumValid(nColumn, self.worksheet.max_column) is True:return self.worksheet.cell(nRow, nColumn).valuedef putDataByCell(self, nRow, nColumn, value):"""写入一个单元格数据功能:param nRow: 行号1,2,...:param nColumn: 列号1,2,...:param value: 写入指定单元格的数值"""self.worksheet.cell(nRow, nColumn).value = valuedef saveWorkBookData(self, strSaveFilePath):"""保存工作簿数据功能:param strSaveFilePath: 保存或另存工作簿的路径"""try:self.workbook.save(strSaveFilePath)except PermissionError:print("要操作的文件,没有写入权限,请检查权限!")raiseexcept FileNotFoundError:print("文件路径不存在,请确保路径正确!")raiseexcept:print("保存写入的数据失败!请检查异常!")raisedef closeWorkBook(self):"""关闭工作簿功能"""self.workbook.close()@staticmethoddef isCheckNumValid(cur_num, max_num):"""检测数据是否有效功能:param cur_num: 当前指定的行号或列号1,2...:param max_num: 当前工作表的最大行号或最大列号1,2...:return: True表示数据有效,否则反"""# 类型检测if type(cur_num) is not int and type(cur_num) is not str:print("cur_num 数据类型错误!请确认为整数类型,或者为字符串类型!")return False# 数字检测if type(cur_num) is str:try:cur_num = int(cur_num)except:print("cur_num参数非法!请确认是输入数据为整数数字!")return False# 数字是否出范围if cur_num in range(1, max_num + 1):return Trueelse:print("行号或者列号,超出了目前最大行号,或者最大列号!!")return False@staticmethoddef justOpen(strFileName):"""模拟手工打开excel表:param strFileName: 打开的excel文件名(后缀.xlsx格式)"""try:xlApp = Dispatch("Excel.Application")xlApp.Visible = FalsexlBook = xlApp.Workbooks.Open(os.path.join(os.getcwd(), strFileName))xlBook.Save()xlBook.Close()except:print("请手工打开 %s 后,随便修改一个空值并保存" % strFileName)"""
========================================
主函数功能测试
========================================
"""
if __name__ == '__main__':# 对自己定义的功能类进行测试# 正常功能测试myExcel = MyPyExcel("test.xlsx") # 加载文件myExcel.openWorkSheet("Sheet") # 选择工作表myExcel.putDataByCell(1, 1, 100) # 写入一个单元格数据myExcel.putDataByCell(2, 1, 400) # 写入一个单元格数据myExcel.putDataByCell(3, 1, "=SUM(A1:A2)") # 写入一个单元格公式myExcel.saveWorkBookData("test.xlsx") # 保存数据myExcel.closeWorkBook() # 关闭工作簿myExcel.justOpen("test.xlsx") # 模拟手工打开excel表"""读取单元格的数值。data_only=True"""myExcel2 = MyPyExcel("test.xlsx") # 加载文件myExcel2.openWorkSheet("Sheet") # 选择工作表print(myExcel2.getDataByCell(3, 1)) # 读取某一个单元格数据myExcel2.closeWorkBook() # 关闭工作簿"""读取单元格的公式。data_only=False"""myExcel3 = MyPyExcel("test.xlsx", False) # 加载文件myExcel3.openWorkSheet("Sheet") # 选择工作表print(myExcel3.getDataByCell(3, 1)) # 读取某一个单元格公式myExcel3.closeWorkBook() # 关闭工作簿
输出结果如下: