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 = False
xlBook = 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 Dispatch
class 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文件失败!请检查!")
raise
else:
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.worksheet
def 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).value
def putDataByCell(self, nRow, nColumn, value):
"""
写入一个单元格数据功能
:param nRow: 行号1,2,...
:param nColumn: 列号1,2,...
:param value: 写入指定单元格的数值
"""
self.worksheet.cell(nRow, nColumn).value = value
def saveWorkBookData(self, strSaveFilePath):
"""
保存工作簿数据功能
:param strSaveFilePath: 保存或另存工作簿的路径
"""
try:
self.workbook.save(strSaveFilePath)
except PermissionError:
print("要操作的文件,没有写入权限,请检查权限!")
raise
except FileNotFoundError:
print("文件路径不存在,请确保路径正确!")
raise
except:
print("保存写入的数据失败!请检查异常!")
raise
def closeWorkBook(self):
"""
关闭工作簿功能
"""
self.workbook.close()
@staticmethod
def 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 True
else:
print("行号或者列号,超出了目前最大行号,或者最大列号!!")
return False
@staticmethod
def justOpen(strFileName):
"""
模拟手工打开excel表
:param strFileName: 打开的excel文件名(后缀.xlsx格式)
"""
try:
xlApp = Dispatch("Excel.Application")
xlApp.Visible = False
xlBook = 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() # 关闭工作簿