Search code examples
xlrdopenpyxlxlwtxlsxwriterxlutils

OpenPyXL always return None for a cell with hyperlink


(My ultimate purpose is to append clickable cells to existing XLSX.)

I use the code below to extract the cell's display value and the hyperlink.

from openpyxl import load_workbook

xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)
wsheet1= wbook.get_sheet_by_name('mysheet')
cell1 = wsheet1.cell('A1')

print cell1.value
print cell1.hyperlink
print wsheet1['A1'].value
print wsheet1['A1'].hyperlink

But it returns the following things:

URL1
None
URL1
None

Why the hyperlink always None? I did add hyperlink manually for cell A1 and the hyperlink works in Excel 2013.


Solution

  • Unfortunately, it's a bug.

    It's a bug in 2012...

    Some related thread:

    Extracting Hyperlinks From Excel (.xlsx) with Python

    Some details of my experiment with hyperlink. I am using OpenPyXL 2.3.3.

    1. I can add hyperlink to cells.
    from openpyxl import load_workbook
    
    xlsFile='hello.xlsx'
    wbook = load_workbook(xlsFile)
    wsheet1= wbook.get_sheet_by_name('mysheet')
    cell1 = wsheet1.cell('A1')
    cell1.hyperlink = r'http://www.example.com'
    cell1.value=r'XXX'
    wbook.save(xlsFile)
    
    1. But I cannot load the XLSX file and read the hyperlink just as my question said.

    2. And If I just load and re-save the XLSX file, ALL existing hyperlinks will be lost. Yeah!

    from openpyxl import load_workbook
    
    xlsFile='hello.xlsx'
    wbook = load_workbook(xlsFile)
    wbook.save(xlsFile)
    

    A workaround!

    Use the formula with OpenPyXL.

    My purpose is to append clickable cells to existing XLSX file. Since hyperlink doesn't work. I use the formula =HYPERLINK(url, displayText) instead. And luckily, the formula is not lost like previous experiment 3.

    from openpyxl import load_workbook
    
    xlsFile='hello.xlsx'
    wbook = load_workbook(xlsFile)
    wsheet1= wbook.get_sheet_by_name('mysheet')
    cell1 = wsheet1.cell('A2')
    cell1.value=r'=HYPERLINK("http://www.example.com","XXX")'
    wbook.save(xlsFile)
    

    Other (failed) options I tried:

    I looked into the XlsxWriter. But it explicitly says it cannot modify existing XLSX file. So it cannot be used for appending.

    I also looked into the xlrd/xlwt/xlutils, unfortunately, if you want to edit an existing excel, you have to use xlrd to load it as a read-only workbook, and then use xlutils to convert(copy) it into a writable workbook. And BANG! during the copy, something will be lost which includes the HYPERLINK formula. According to its doc string, this is a known limitation:

    # Copyright (c) 2009-2012 Simplistix Ltd
    #
    # This Software is released under the MIT License:
    # http://www.opensource.org/licenses/mit-license.html
    # See license.txt for more details.
    
    from xlutils.filter import process,XLRDReader,XLWTWriter
    
        def copy(wb):
            """
            Copy an :class:`xlrd.Book` into an :class:`xlwt.Workbook` preserving as much
            information from the source object as possible.
    
            See the :doc:`copy` documentation for an example.
            """
            w = XLWTWriter()
            process(
                XLRDReader(wb,'unknown.xls'),
                w
                )
            return w.output[0][1]
    

    And also, xlwt doesn't support XLSX, only supports XLS. That's another reason I decided not to use it.