检查Python字符串是否是有效的Excel单元格

3

在Python中给出一些字母数字字符串,例如:

  • A9
  • B44B
  • C101
  • 4D4

如何检查字符串是否为有效的Excel单元格(即字符位于数字之前)?

我尝试使用.isalpha.isdigit方法“收集”字母和数字,然后使用.index检查所有字母是否都出现在数字之前,但我的逻辑变得太复杂了,我觉得我没有考虑到所有可能性。

有没有简单的方法来实现这个目标?

预期结果:

>>> is_valid_excel_cell('A9')
True
>>> is_valid_excel_cell('B44B')
False
>>> is_valid_excel_cell('C101')
True
>>> is_valid_excel_cell('4D4')
False

2
注意:请记住,有效性可能取决于Excel版本。例如:Excel2003仅具有256列和65536行,而更新的版本具有16384列和1048676行。 - JvdV
1
正则表达式可能是最好的选择:re.match("[A-Z]+\d+$",cellcontent) - Jean-François Fabre
你是否认为仅关注检测字母直接跟在数字后面是公平的? - pip install frisbee
@JvdV 你说得对,虽然这对我的使用情况不应该是个问题。我没有解释清楚,但我的意思并不是将Excel文件写回内存,只是读取它的值(openpyxl允许访问超出Excel限制的单元格,尽管它们都存储为None值)。 - jfaccioni
@pipinstallMonica 大部分是的,不过我想检查一下它是否为实际的Excel单元格(即'1''A'应该返回False,因为它们是Excel的列/行,而不是单元格)。 - jfaccioni
openpyxl实际上在utils模块中提供了必要的函数。 - Charlie Clark
3个回答

5
根据我的评论,有效性取决于Excel版本。 新版本具有A-XDF列范围和1-1048576行。这在您的项目中可能不是必需的,但对于将来的参考可能会很方便:
正则表达式模式: ^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([1-9]\d{0,6})$
为了可视化这个:
第一组捕获Excel 2010及更高版本的列引用,即A-XDF,第二组捕获数字部分,应始终以1-9开头,后跟0到6个字符,但不能超过1048576。
因此,完全生效时,您可以考虑:
import re
def is_valid_excel_cell(c):
    m = re.match(r'^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([1-9]\d{0,6})$',c)
    return bool(m) and int(m.group(2)) < 1048577

虽然我现在不需要这个功能,但我同意这是对我的问题更通用的答案。谢谢! - jfaccioni

3
我会使用正则表达式,这很适合该任务:
import re

def is_valid_excel_cell(c):
    m = re.match("[A-Z]+\d+$",c)
    return bool(m)

这段代码检查单元格内容是否以大写字母开头,以数字结尾。

如果需要对数字进行范围检查,则需要多一步操作,可以提取数字并将其转换为整数,然后与范围进行比较(我不是excel专家,读者可以自行调整范围)。

def is_valid_excel_cell(c):
    m = re.match("[A-Z]+(\d+)$",c)
    return bool(m) and m.group(1).isdigit() and 0 < int(m.group(1)) < 16384

非常感谢,这正如预期的那样完美地工作。当然,答案涉及到正则表达式... :) - jfaccioni
1
如果您不介意的话,我已经将一些更加复杂的正则表达式模式添加到了您的优秀答案中。 - JvdV

1
import re

def is_valid_excel_cell(addr):
    m = re.match(r'^([A-Z]{1,3})([1-9]\d*)$', addr)
    if not m:
        return False
    letters, numbers = m.groups()
    if len(letters) == 3 and letters > 'XFD':
        return False
    if int(numbers) > 1048576:
        return False
    return True

仅适用于Python 3.8+的半压缩版本(由于使用了海象运算符(:=)):

def is_valid_excel_cell(addr):
    return (bool(m := re.match(r'^([A-Z]{1,3})([1-9]\d*)$', addr)) and
        (len(m.group(1)) < 3 or m.group(1) <= 'XFD') and 
        int(m.group(2)) <= 1048576)

非常巧妙地使用了检查字母对 XFD 的方法,加号。看起来 OP 可以使用答案的组合:m = re.match(r'^([A-Z]{1,3})([1-9]\d{0,6})$',c) >> return bool(m) and m.group(1) < 'XFE' and int(m.group(2)) < 1048577 - JvdV
1
@JvdV:当第1组长度为3时,'ZZ' < 'XFE'是错误的,因此应该仅在检查时进行。一旦我在你的答案中看到它,我非常喜欢缩短它的想法,但最终我决定保持原样,以使逻辑对OP明显。 - Steven Rumbalski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接