【问题标题】:openpyxl: '@' is inserted to formula when saving to fileopenpyxl:保存到文件时将“@”插入到公式中
【发布时间】:2022-01-10 19:59:28
【问题描述】:

当我将以下公式添加到单元格时,单元格的值在打印到控制台时看起来不错。但是,在我保存文件后,公式在“=”之后插入了“@”(为简单起见,我提供了控制台的输出):

>>> from openpyxl import Workbook
>>> wb = Workbook()
>>> ws = wb.active
>>> ws['A1'] = '=CONCAT("Week ",TEXT(MID(' + get_column_letter(9) + '1,6,2)+ 1, "##"))'
>>> ws['A1'].value
'=CONCAT("Week ",TEXT(MID(I1,6,2)+ 1, "##"))'
>>> wb.save('formula.xlsx')
>>> 

在“formula.xlsx”文件中,公式如下所示:

=@CONCAT("Week ",TEXT(MID(I1,6,2)+ 1, "##"))

但是,如果我指定 '=SUM()' 而不是 '=CONCAT()',例如,它会按预期保存,即没有插入 '@'。

我正在使用 openpyxl 3.0.3 和 Python 3.8。

非常感谢

-------- Udate --------

我查看了“formula.xlsx”的 XML 代码;但在此之前,我在 Excel 中打开它,将单元格 A1 复制到单元格 D1 中,然后从单元格 D1 的公式中删除“@”,之后 D1 开始显示正确的值,而 A1 仍然显示“#NAME?”错误。

因此,在我对单元格 D1 进行更改后,工作表的 XML 代码显示如下:

<row r="1" spans="1:9" x14ac:dyDescent="0.45">
    <c r="A1" t="e"><f ca="1">_xludf.CONCAT("Week ",TEXT(MID(I1,6,2)+ 1, "##"))</f><v>#NAME?</v></c>
    <c r="D1" t="str"><f>_xlfn.CONCAT("Week ",TEXT(MID(I1,6,2)+ 1, "##"))</f><v>Week 68</v></c>
    <c r="I1"><v>12345678</v></c>
</row>

上面单元格 A1 中 openpyxl 用于 CONCAT 的 _xludf 前缀在 https://docs.microsoft.com/en-us/office/client-developer/excel/xludf 上被描述为“用户定义函数”。

这是否意味着该库没有将 CONCAT 识别为标准 Excel 函数,因此使用 _xludf 而不是 _xlfn?

-----更新结束---

【问题讨论】:

  • 嗨,鲍勃,我尝试重新创建您的代码和问题,但它似乎对我来说工作正常。这是完整的相关代码吗?
  • 是的,当然。上面的代码是我在控制台中测试的截图。您使用的是 Windows/Linux 还是 Mac(在我的情况下是 Mac)?也许这会有所不同?让我看看我是否可以在 Windows 中尝试一下...
  • 我用的是win机,openpyxl 3.0.3版本和Python 3.8(带PyCharm)
  • 我在 MS Windows 中打开了相同的“formula.xlsx”文件,但没有显示“@”符号(虽然它显示在 Excel for Mac 中)。但是,在单元格本身中,它仍然显示“#NAME?”错误。只要我删除 '=' 并再次重新键入它,或者如果我在 '=' 和 'CONCAT' 之间键入一个空格并删除它,错误就会消失,并在单元格中计算出正确的值(您需要当然,“I1”中存在正确的值,否则您将立即遇到“#VALUE!”错误)。因此,在 wb.save() 完成期间,在 '=' 和 'CONCAT' 之间插入了一些代码。
  • 试试ws['A1'] = '=_xlfn.CONCAT("Week ",TEXT(MID(' + get_column_letter(9) + '1,6,2)+ 1, "##"))'

标签: excel-formula openpyxl


【解决方案1】:

正如 openpyxl documentation 中指定的那样,只需插入公式名称即可使用已知公式。

可以使用

>>> from openpyxl.utils import FORMULAE
>>> "CONCAT" in FORMULAE
False

检查公式是否是openpyxl中的已知公式。如果公式不是您需要在公式名称之前添加_xlfn.,如下所示:

>>> ws['A1'] = '=_xlfn.CONCAT("Week ",TEXT(MID(' + get_column_letter(9) + '1,6,2)+ 1, "##"))

文档中也提到了:

如果您尝试使用未知的公式,这可能是 因为您使用的公式未包含在初始 规格。此类公式必须以 _xlfn. 为前缀才能起作用。

【讨论】:

  • 谢谢,这很有帮助。我不确定我之前是如何在文档中没有注意到该注释的。我的错......对不起。
  • @bob39722 不用担心!我只是添加它以供将来参考:)
【解决方案2】:

我在使用西班牙语公式时遇到了同样的问题(我来自阿根廷)。 当我尝试将“=SUMA(A1:A20)”之类的内容分配给单元格时,它会显示为“=@SUMA(A1:A20)”。

我尝试了 _xlfn。解决方案,但现在它只是结束了 "=@_xlfn.SUMA(A1:A20)"

如果/当我找到答案时,我会在这里发布。

已解决 如果您使用的是非英文版的 Excel,您仍然需要为单元格分配函数的英文名称,例如“=总和(A1:A20)” 之后,当您检查工作表中单元格的内容时,它会更改为正确的语言,在本例中为西班牙语“=SUMA(A1:A20)”

警告:我只检查了西班牙语版本,但我很确定它适用于所有人。

另外:如果您使用另一组字符作为分隔符,例如小数点用逗号 (,) 而不是点 (.),则在将公式分配给单元格时仍需要使用点,例如“ = E8 * 0.5"。检查单元格时,您将看到一个逗号。在该字符串中使用逗号将导致打开 xlsx 文件时出现文件损坏错误。

【讨论】:

    【解决方案3】:

    在 python 代码中显式指定 _xlfn 前缀可以解决问题:

    >>> ws['A1'] = '=_xlfn.CONCAT("Week ",TEXT(MID(' + get_column_letter(9) + '1,6,2)+ 1, "##"))'
    

    感谢 Dror Av。求指导!

    【讨论】:

      【解决方案4】:

      在我的例子中,我试图输入 =ARRED 公式,而字符 @ 出现在 Excel 文件中,如 =@ARRED

      ARRED 是巴西葡萄牙语前缀,不被识别,所以我用 ROUND 代替,效果很好。

      测试:

      from openpyxl.utils import FORMULAE
      "ARRED" in FORMULAE
      False
      "ROUND" in FORMULAE
      True
      

      【讨论】:

        猜你喜欢
        • 2023-01-27
        • 1970-01-01
        • 1970-01-01
        • 2018-12-23
        • 2016-07-15
        • 1970-01-01
        • 2013-04-23
        • 1970-01-01
        相关资源
        最近更新 更多