读取Excel单元格值而不是计算它的公式-openpyxl

use*_*047 35 python openpyxl

我正在使用openpyxl来读取单元格值(excel addin-webservice更新此列.)

我已经使用data_only = True但它没有显示当前单元格值,而是它是上次Excel读取工作表时存储的值.

wbFile = openpyxl.load_workbook(filename = xxxx,data_only=True)
wsFile = wbFile[c_sSheet]
Run Code Online (Sandbox Code Playgroud)

我如何读取单元格的实际值?

小智 105

wb = openpyxl.load_workbook(filename, data_only=True)
Run Code Online (Sandbox Code Playgroud)

data_only标志帮助.

  • 是.这回答了这个问题.如果你想访问,方程式和值,那么你可能会在两个实例中结束,比如说'wb2 = openpyxl.load_workbook(filename)`.然后在读取相应的索引时,您可以从`wb`获得值,从`wb2`获得等式. (4认同)
  • 对于任何冒险进入这个线程的人都有同样的问题(如何同时获得公式和值),你不能.我发现很难相信这样一个愚蠢的决定可以实现,因为有多少现有的库可以优雅地处理这个问题,但这就是我想的那样.您必须创建工作簿的第二个实例,并将data_only标志设置为True,然后跟踪它们.精神错乱,但无论如何. (4认同)
  • 当 data_only = True 时,cell.value 将返回值(写入文件时 Excel 最后知道的值)。cell.internal_value 将返回公式。 (4认同)
  • 我遇到了一些奇怪的行为:当使用“data_only=True”并尝试使用公式读取单元格时,“cell.value”或“cell.internal_value”都得到“None”(对于静态单元格或没有“data_only”效果很好) =正确`)。任何想法? (2认同)

Cha*_*ark 11

正如@ alex-martelli所说,openpyxl不会评估公式.使用openpyxl打开Excel文件时,您可以选择读取公式或最后计算的值.如果您指出,公式依赖于加载项,则缓存的值永远不会准确.作为文件规范之外的加载项,它们永远不会受到支持.相反,您可能希望查看可以与Excel运行时交互的xlwings之类的内容.

  • 关于此答案的两个问题:(1)如何区分打开 XL 文件来读取论坛与读取最后计算的值?这是通过“data_only=True”参数吗?(2)“最后计算的值”在现实世界中意味着什么?也就是说,如果 XL 文件是在上次(手动/人为)更改后退出时保存的,这是否意味着所有单元格都被重新计算/以其“最后计算值”?通常何时重新计算单元格值?*(我意识到这更像是一个 Excel 问题,而不是 OpenPyXL,但非常感谢您的澄清)* (2认同)
  • 没关系,我想我在这里找到了答案:/sf/ask/2528131371/ (2认同)

Nab*_*bla 11

正如@Charlie Clark 提到的,您可以使用xlwings(如果您有 MS Excel)。这里有一个例子

假设您有一个带有公式的 Excel 表,例如我定义了一个 openpyxl

from openpyxl import Workbook, load_workbook
wb=Workbook()

ws1=wb['Sheet']

ws1['A1']='a'
ws1['A2']='b'
ws1['A3']='c'

ws1['B1']=1
ws1['B2']=2
ws1['B3']='=B1+B2'

wb.save('to_erase.xlsx')
Run Code Online (Sandbox Code Playgroud)

如前所述,如果我们再次加载 excel openpyxl,我们将不会得到评估公式

wb2 = load_workbook(filename='to_erase.xlsx',data_only=True)
wb2['Sheet']['B3'].value
Run Code Online (Sandbox Code Playgroud)

您可以使用xlwings来获取由 excel 评估的公式:

import xlwings as xw
wbxl=xw.Book('to_erase.xlsx')
wbxl.sheets['Sheet'].range('B3').value
Run Code Online (Sandbox Code Playgroud)

它返回 3,即预期值。

我发现它在处理具有非常复杂的公式和工作表之间的引用的电子表格时非常有用。

  • 实际上,这些公式是由 MS excel 评估的。我认为这个解决方案只能在装有这个软件的机器上工作(尽管这个库应该在 mac 上工作) (2认同)

Arp*_*ini 9

data_only :读取甚至公式单元格的值。

keep_vba:仅当您使用启用宏的 excel 时才使用它

file_location = 'C:\Arpan Saini\Monsters\Project_Testing\SecCardGrad\SecCardGrad_Latest_docs\Derived_Test_Cases_Secure_Card_Graduate.xlsm'
wb = load_workbook(file_location, keep_vba=True, data_only=True)
Run Code Online (Sandbox Code Playgroud)


Ale*_*kov 7

我通过以下方式解决了这个问题:

import xlwings
from openpyxl import load_workbook

data = load_workbook('PATH_TO_YOUR_XLSX_FILE')
data['sheet_name']['A1'].value = 1
data.save('PATH_TO_YOUR_XLSX_FILE')

excel_app = xlwings.App(visible=False)
excel_book = excel_app.books.open('PATH_TO_YOUR_XLSX_FILE')
excel_book.save()
excel_book.close()
excel_app.quit()

data = load_workbook('PATH_TO_YOUR_XLSX_FILE', data_only=True)
Run Code Online (Sandbox Code Playgroud)

我希望,这可以帮助你...


krv*_*kir 6

面临同样的问题。无论这些单元格是什么,都需要读取单元格值:标量、带有预计算值的公式或没有它们的公式,容错性优于正确性。

该策略非常简单:

  1. 如果单元格不包含公式,则返回单元格的值;
  2. 如果是公式,则尝试获取其预先计算的值;
  3. 如果不能,请尝试使用pycel;
  4. 如果失败(由于对pycel公式的支持有限或有一些错误),警告并返回 None。

我创建了一个类,它隐藏了所有这些机制,并提供了用于读取单元格值的简单界面。

如果正确性优于容错性,则可以轻松修改该类,以便在第 4 步时引发异常。

希望它会帮助某人。

from traceback import format_exc
from pathlib import Path
from openpyxl import load_workbook
from pycel.excelcompiler import ExcelCompiler
import logging


class MESSAGES:
    CANT_EVALUATE_CELL = ("Couldn't evaluate cell {address}."
                          " Try to load and save xlsx file.")


class XLSXReader:
    """
    Provides (almost) universal interface to read xlsx file cell values.

    For formulae, tries to get their precomputed values or, if none,
    to evaluate them.
    """

    # Interface.

    def __init__(self, path: Path):
        self.__path = path
        self.__book = load_workbook(self.__path, data_only=False)

    def get_cell_value(self, address: str, sheet: str = None):
        # If no sheet given, work with active one.
        if sheet is None:
            sheet = self.__book.active.title

        # If cell doesn't contain a formula, return cell value.
        if not self.__cell_contains_formula(address, sheet):
            return self.__get_as_is(address, sheet)

        # If cell contains formula:
        # If there's precomputed value of the cell, return it.
        precomputed_value = self.__get_precomputed(address, sheet)
        if precomputed_value is not None:
            return precomputed_value

        # If not, try to compute its value from the formula and return it.
        # If failed, report an error and return empty value.
        try:
            computed_value = self.__compute(address, sheet)
        except:
            logging.warning(MESSAGES.CANT_EVALUATE_CELL
                            .format(address=address))
            logging.debug(format_exc())
            return None
        return computed_value                

    # Private part.

    def __cell_contains_formula(self, address, sheet):
        cell = self.__book[sheet][address]
        return cell.data_type is cell.TYPE_FORMULA

    def __get_as_is(self, address, sheet):
        # Return cell value.
        return self.__book[sheet][address].value

    def __get_precomputed(self, address, sheet):
        # If the sheet is not loaded yet, load it.
        if not hasattr(self, '__book_with_precomputed_values'):
            self.__book_with_precomputed_values = load_workbook(
                self.__path, data_only=True)
        # Return precomputed value.
        return self.__book_with_precomputed_values[sheet][address].value

    def __compute(self, address, sheet):
        # If the computation engine is not created yet, create it.
        if not hasattr(self, '__formulae_calculator'):
            self.__formulae_calculator = ExcelCompiler(self.__path)
        # Compute cell value.
        computation_graph = self.__formulae_calculator.gen_graph(
            address, sheet=sheet)
        return computation_graph.evaluate(f"{sheet}!{address}")
Run Code Online (Sandbox Code Playgroud)