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

时间:2012-10-15 19:26:23

标签: python openpyxl

我正在尝试将excel中的坐标值转换为openpyxl中的行号和列号。

例如,如果我的单元格坐标为D4,我想找到用于将来操作的相应行号和列号,在行= 3,列= 3的情况下,我可以使用{{1}轻松获取行号返回ws.cell('D4').row然后它只是减去1的问题。但是类似的参数4返回ws.cell('D4').column并且我不知道如何轻松地将其转换为int形式以用于后续操作。所以我向你转向stackoverflow的聪明人。你能救我吗?

8 个答案:

答案 0 :(得分:42)

您想要的是openpyxl.utils.coordinate_from_string()openpyxl.utils.column_index_from_string()

from openpyxl.utils.cell import coordinate_from_string, column_index_from_string
xy = coordinate_from_string('A4') # returns ('A',4)
col = column_index_from_string(xy[0]) # returns 1
row = xy[1]

答案 1 :(得分:36)

openpyxl有一个名为 get_column_letter 的函数,可以将数字转换为列字母。

from openpyxl.utils import get_column_letter
print(get_column_letter(1))

1 - >甲

50 - > AX

1234-- AUL

我一直在使用它:

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")

enter image description here

答案 2 :(得分:3)

这是建立在内森的回答之上的。基本上,当行和/或列超过一个字符宽时,他的答案无法正常工作。对不起 - 我去了一点。这是完整的脚本:

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;博士带着一堆评论......

# make cells with multiple characters in length for row/column
# feel free to change these values
cells = ['Ab102', 'C10', 'AFHE3920']

# import regex
from re import match as rematch

# run through all the cells we made
for cell in cells:
    # make sure the cells are lower-case ... just easier
    cell = cell.lower()

    # generate matched object via regex (groups grouped by parentheses)
    ############################################################################
    # [a-z] matches a character that is a lower-case letter
    # [0-9] matches a character that is a number
    # The + means there must be at least one and repeats for the character it matches
    # the parentheses group the objects (useful with .group())
    m = rematch('([a-z]+)([0-9]+)', cell)

    # if m is None, then there was no match
    if m is None:
        # let's tell the user that there was no match because it was an invalid cell
        from sys import stderr
        print('Invalid cell: {}'.format(cell), file=stderr)
    else:
        # we have a valid cell!
        # let's grab the row and column from it

        row = 0

        # run through all of the characters in m.group(1) (the letter part)
        for ch in m.group(1):
            # ord('a') == 97, so ord(ch) - 96 == 1
            row += ord(ch) - 96
        col = int(m.group(2))

        # phew! that was a lot of work for one cell ;)
        print('Cell: [{},{}] '.format(row, col))

print('I hope that helps :) ... of course, you could have just used Adam\'s answer,\
but that isn\'t as fun, now is it? ;)')

答案 3 :(得分:0)

旧话题,但答案不正确!

dylnmc 方法是一种很好的方法,但是存在一些错误。像“ AA1”或“ AAB1”这样的单元格坐标的计算行不正确。

下面是作为功能的更正版本。

注意::此函数返回实坐标。例如,如果要在ExcelWriter中使用它,则ROW和COL都应减一。因此,将最后一行替换为 return(row-1,col-1)

例如,“ AA1”为[1,27],而“ AAA1”为[1,703];但是python必须将它们分别设置为[0,26]和[0,702]。

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]

答案 4 :(得分:0)

新版本的 openpyxl 似乎支持 cell.col_idx,它为相关单元格提供了一个从 1 开始的列号。

所以 ws.cell('D4').col_idx 应该给你 4 而不是 D

答案 5 :(得分:0)

这将给出列号

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

答案 6 :(得分:0)

如果你想在不使用任何库的情况下做到这一点:

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)

答案 7 :(得分:-4)

你可以使用纯Python:

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

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