使用Python查找Excel单元格引用

时间:2016-08-13 17:53:02

标签: python excel match cell

Here is the Excel file in question:

上下文:我正在编写一个程序,它可以从PDF中提取值并将它们放在Excel文件中的相应单元格中。

问题:我想编写一个函数,它将一个列值(例如2014)和一个行值(例如' COGS')作为参数,并返回那两个相交的单元格引用(例如&# 39; C3' 2014年COGS)。

def find_correct_cell(year=2014, item='COGS'):
    #do something similar to what the =match function in Excel does
    return cell_reference #returns 'C3'

I have already tried using openpyxl like this to change the values of some random empty cells where I can store these values:

    col_num = '=match(2014, A1:E1)'
    row_num = '=match("COGS", A1:A5)'

但我想抓住这些值,而不必随意写入那些随机的空单元格。另外,即使使用这种方法,当我读取这些单元格(F5和F6)时,它会读取这些单元格中的公式而不是3的面值。

感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:1)

使用openpyxl以这种方式操作Excel文件所需的细节数量惊人。首先,值得知道xlsx文件包含每个单元格的两个表示 - 公式和公式的当前值。 openpyxl也可以返回,如果你想要值,你应该在打开文件时指定data_only=True。此外,更改单元格的公式时,openpyxl无法计算新值 - 只有Excel本身才能这样做。因此,插入MATCH()工作表函数不会解决您的问题。

下面的代码可以满足您的需求,主要是在Python中。它使用" A1"引用样式,并进行一些计算以将列号转换为列字母。如果超过Z列,这将不会很好。在这种情况下,您可能希望切换到行和列的编号引用。有关herehere的更多信息。但希望这会让你顺利上路。

注意:此代码假设您正在阅读名为' test.xlsx'的工作簿,以及' COGS'是在' Sheet1!A2:A5'中的项目列表中。和2014年的年份列表在Sheet1!B1:E1'。

import openpyxl

def get_xlsx_region(xlsx_file, sheet, region):
    """ Return a rectangular region from the specified file.
    The data are returned as a list of rows, where each row contains a list 
    of cell values"""

    # 'data_only=True' tells openpyxl to return values instead of formulas
    # 'read_only=True' makes openpyxl much faster (fast enough that it 
    # doesn't hurt to open the file once for each region).
    wb = openpyxl.load_workbook(xlsx_file, data_only=True, read_only=True)  

    reg = wb[sheet][region]

    return [[cell.value for cell in row] for row in reg]

# cache the lists of years and items
# get the first (only) row of the 'B1:F1' region
years = get_xlsx_region('test.xlsx', 'Sheet1', 'B1:E1')[0]
# get the first (only) column of the 'A2:A6' region
items = [r[0] for r in get_xlsx_region('test.xlsx', 'Sheet1', 'A2:A5')]

def find_correct_cell(year, item):
    # find the indexes for 'COGS' and 2014
    year_col = chr(ord('B') + years.index(year))   # only works in A:Z range
    item_row = 2 + items.index(item)

    cell_reference = year_col + str(item_row)

    return cell_reference

print find_correct_cell(year=2014, item='COGS')
# C3

答案 1 :(得分:1)

考虑翻译的VBA解决方案,因为Match功能可以充分满足您的需求。 Python可以使用带有win32com模块的COM接口访问Excel VBA对象库。请注意,此解决方案假定您使用的是Excel for PC。下面包括对应的VBA功能。

VBA 功能(原生界面)

如果以下功能放在Excel标准模块中,则可以在电子表格单元格=FindCell(..., ###)

中调用该功能
' MATCHES ROW AND COL INPUT FOR CELL ADDRESS OUTPUT
Function FindCell(item As String, year As Integer) As String    
    FindCell = Cells(Application.Match(item, Range("A1:A5"), 0), _
                     Application.Match(year, Range("A1:E1"), 0)).Address    
End Function

debug.Print FindCell("COGS", 2014) 
' $C$3

Python 脚本(外部接口,要求声明所有对象)

Try / Except / Finally用于正确关闭Excel进程,无论脚本成功还是失败。

import win32com.client

# MATCHES ROW AND COL INPUT FOR CELL ADDRESS OUTPUT
def FindCell(item, year):
    return(xlWks.Cells(xlApp.WorksheetFunction.Match(item, xlWks.Range("A1:A5"), 0), 
                       xlApp.WorksheetFunction.Match(year, xlWks.Range("A1:E1"), 0)).Address)

try:
    xlApp = win32com.client.Dispatch("Excel.Application")
    xlWbk = xlApp.Workbooks.Open('C:/Path/To/Workbook.xlsx')
    xlWks = xlWbk.Worksheets("SHEETNAME")

    print(FindCell("COGS", 2014))
    # $C$3

except Exception as e:
    print(e)

finally:    
    xlWbk.Close(False)
    xlApp.Quit

    xlWks = None
    xlWbk = None
    xlApp = None