Python 从openpyxl中的坐标值获取行数和列数

Python 从openpyxl中的坐标值获取行数和列数,python,openpyxl,Python,Openpyxl,我试图将excel中的坐标值转换为openpyxl中的行号和列号 例如,如果我的单元格坐标为D4,我希望找到相应的行号和列号,以便在row=3,column=3的情况下用于将来的操作。我可以使用ws.cell('D4')轻松获得行号。row返回4,然后只需减去1即可。但是一个类似的参数ws.cell('D4')。column返回D,我不知道如何轻松地将其转换为int形式以用于后续操作。所以我向你们这些聪明的斯塔克沃夫人求助。你能帮我吗?你可以使用纯Python: cell = "D4" col

我试图将excel中的坐标值转换为openpyxl中的行号和列号


例如,如果我的单元格坐标为D4,我希望找到相应的行号和列号,以便在row=3,column=3的情况下用于将来的操作。我可以使用
ws.cell('D4')轻松获得行号。row
返回
4
,然后只需减去1即可。但是一个类似的参数
ws.cell('D4')。column
返回
D
,我不知道如何轻松地将其转换为int形式以用于后续操作。所以我向你们这些聪明的斯塔克沃夫人求助。你能帮我吗?

你可以使用纯Python:

cell = "D4"
col = ord(cell[0]) - 65
row = int(cell[1:]) - 1

这使用
ord
函数,该函数接受一个字符并返回其ASCII码。ASCII中的字母
A
是65,
B
是66,依此类推。

您需要的是
openpyxl.utils.coordinate\u from_string()
openpyxl.utils.column\u index\u from_string()


这是基于内森的回答。基本上,当行和/或列的宽度超过一个字符时,他的答案不能正常工作。对不起,我有点过火了。以下是完整的脚本:

def main():
    from sys import argv, stderr

    cells = None

    if len(argv) == 1:
        cells = ['Ab102', 'C10', 'AFHE3920']
    else:
        cells = argv[1:]

    from re import match as rematch

    for cell in cells:
        cell = cell.lower()

        # generate matched object via regex (groups grouped by parentheses)
        m = rematch('([a-z]+)([0-9]+)', cell)

        if m is None:
            from sys import stderr
            print('Invalid cell: {}'.format(cell), file=stderr)
        else:
            row = 0
            for ch in m.group(1):
                # ord('a') == 97, so ord(ch) - 96 == 1
                row += ord(ch) - 96
            col = int(m.group(2))

            print('Cell: [{},{}] '.format(row, col))

if __name__ == '__main__':
    main()
Tl;博士和一堆评论。。。
openpyxl有一个名为“获取列字母”的函数,该函数将数字转换为列字母

from openpyxl.utils import get_column_letter
print(get_column_letter(1))
1-->A

50-->AX

1234--奥尔

我一直在使用它,就像:

from openpyxl import Workbook
from openpyxl.utils import get_column_letter

#create excel type item
wb = Workbook()
# select the active worksheet
ws = wb.active

counter = 0
for column in range(1,6):
    column_letter = get_column_letter(column)
    for row in range(1,11):
        counter = counter +1
        ws[column_letter + str(row)] = counter

wb.save("sample.xlsx")

老话题,但答案不正确

dylnmc方法是一种很好的方法,但也有一些错误。“AA1”或“AAB1”等单元格坐标的计算行不正确

下面是作为一个函数的更正版本

注意:此函数返回实际坐标。例如,如果您想在ExcelWriter中使用它,则行和列都应减去1。因此,将最后一行替换为返回(第1行,第1列)

例如,“AA1”是[1,27],而“AAA1”是[1703];但是python必须将它们命名为[0,26]和[0702]

import re

def coord2num(coord):
    cell = coord.lower()

    # generate matched object via regex (groups grouped by parentheses)
    m = re.match('([a-z]+)([0-9]+)', cell)

    if m is None:
        print('Invalid cell: {}'.format(cell))
        return [None,None]
    else:
        col = 0
        for i,ch in enumerate(m.group(1)[::-1]):
            n = ord(ch)-96
            col+=(26**i)*(n)

        row = int(m.group(2))

    return[row,col]

它看起来像是较新版本的support
cell.col_idx
,它为相关单元格提供了一个基于1的列号


因此,
ws.cell('D4')。col_idx
应该为您提供4,而不是
D

这将提供列号

col = "BHF"
num = 0
for i in range(len(col)):
    num = num + (ord(col[i]) - 64) * pow(26, len(col) - 1 - i)
print(num)

如果要在不使用任何库的情况下执行此操作:

def col_row(s):
    """ 'AA13' -> (27, 13) """

    def col_num(col):
        """ 'AA' -> 27 """
        s = 0
        for i, char in enumerate(reversed(col)):
            p = (26 ** i)
            s += (1 + ord(char.upper()) - ord('A')) * p
        return s

    def split_A1(s):
        """ 'AA13' -> (AA, 13) """
        for i, char in enumerate(s):
            if char.isdigit():
                return s[:i], int(s[i:])

    col, row = split_A1(s)
    return col_num(col), row

col_row('ABC13')
# Out[124]: (731, 13)

感谢您的回复,不幸的是,对于大于Z的列(例如AD),这不起作用。还有一个问题Adam,我在哪里可以找到这些不同的命令?我能找到的在线文档非常稀少,并且没有包含您列出的函数。文档中没有太多内容-它是在phpexcel的基础上构建的-并且有明显的重叠。对于python项目,代码的结构非常好——只要查看源代码中的单元测试,就可以找到很多代码。对于使用openpyxl最新版本(大约在2015年11月20日版本2.3.1)的任何人,请记住,一些函数定义已经移到包的不同部分。“coordinate_from_string”和“column_index_from_string”现在必须“从openpyxl.utils”导入。请参阅文档,不确定这是何时开始的,但至少从
openpyxl utilities==0.5
(从2019年起),您可以使用
从openpyxl.utils.cell导入坐标从字符串导入,从字符串导入列索引从字符串导入,但反过来更难,也不那么明显。处理该问题的最佳解决方案是简洁明了。这对于跨Excel列范围设置列宽和其他列维度属性非常有用,因为openpyxl列维度[x]。宽度似乎只接受列的字符串字母值,而不是整数。可能过火,但这是一种通过重新匹配分割坐标的干净方法。肯定是其他坐标转换问题的基础。
col = "BHF"
num = 0
for i in range(len(col)):
    num = num + (ord(col[i]) - 64) * pow(26, len(col) - 1 - i)
print(num)
def col_row(s):
    """ 'AA13' -> (27, 13) """

    def col_num(col):
        """ 'AA' -> 27 """
        s = 0
        for i, char in enumerate(reversed(col)):
            p = (26 ** i)
            s += (1 + ord(char.upper()) - ord('A')) * p
        return s

    def split_A1(s):
        """ 'AA13' -> (AA, 13) """
        for i, char in enumerate(s):
            if char.isdigit():
                return s[:i], int(s[i:])

    col, row = split_A1(s)
    return col_num(col), row

col_row('ABC13')
# Out[124]: (731, 13)