【问题标题】:Finding Excel cell reference using Python使用 Python 查找 Excel 单元格引用
【发布时间】:2016-12-20 12:00:54
【问题描述】:

Here is the Excel file in question:

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

问题:我想编写一个函数,它以列值(例如 2014)和行值(例如“COGS”)作为参数并返回这两者相交的单元格引用(例如 2014 COGS 的“C3”) .

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 的面值。

感谢您的帮助。

【问题讨论】:

  • 您是否有 Python 变量显示您尝试匹配的列表?例如,如果dates = [2014, 2015, 2016] 那么dates.index(2014) 将给出0。但我们需要更多关于您的数据现在处于何种形式的信息才能回答这个问题。
  • 什么意思?我只是想拿一个电子表格,找出某一年的列和某一项目的行,这样我就知道我应该在哪一年为该项目放置数据的位置。这样更有意义吗?
  • 这将有助于更明确地了解数据的存储位置、组织方式以及您使用的工具,例如,“年份列在 Excel 工作簿的单元格 A1:E1 中,和产品列在单元格 A1:A5 中。我正在使用 openpyxl 读取和写入工作簿,我需要为行与指定产品匹配且列与指定年份匹配的单元格创建一个 'A1' 样式的引用。 (我必须在字里行间阅读才能意识到您正在使用 openpyxl,并且查找列表位于 Excel 工作簿中的特定范围内。)我在下面发布了一个答案。
  • (抱歉,我可能应该查看您的示例电子表格来弄清楚您的要求!这就是我在喝咖啡之前发表评论的结果!)

标签: python excel match cell


【解决方案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

【讨论】:

    【解决方案2】:

    要正确使用 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
    

    【讨论】: