Tutorial

Leer documentos de Excel con Python

Este tutorial tiene como finalidad, aprender a leer nuestros documentos Excel con Python, por lo que otras operaciones como la escritura y modificación serán parte de otro post.

Como sabemos, los archivos xlsx/xlsm son creados con Microsoft Excel, esto representa un problema para múltiples lenguajes que tienen un enfoque "libre", ya que Microsoft solo proporciona APIs para sus plataformas de desarrollo. Entonces aquí es donde Python queda sin soporte oficial ante un formato de archivo privativo, pero gracias a la gran comunidad de desarrollo se ha creado una librería (no oficial) para la manipulación casi total de estos archivos y se llama OpenPyxl.

Entonces lo primero que debemos hacer, es instalar la libreria openpyxl en nuestro interprete Python, lo podemos hacer mediante pip o directamente desde el source code.

$pip install openpyxl

Una vez instalada la librería podemos comenzar a escribir codigo, recomiendo descargar el siguiente documento de Excel para seguir el tutorial (puedes usar uno propio, si lo deseas).

Apertura de archivo Excel.

>>> import openpyxl
>>> doc = openpyxl.load_workbook('address.xls') #suponiendo que el archivo esta en el mismo directorio del script

En la primera linea importamos la libreria openpyxl y posteriormente abrimos el archivo excel con el método load_workbook, este tiene un argumento de tipo string que hace referencia a el path o ruta completa (no relativa) donde hemos almacenado nuestro archivo, por ejemplo:

  • 'C:\\Users\aaron\Documents\address.xls' (Windows)
  • '/home/aaron/Documentos/address.xls' (Linux)

Lectura de hojas de calculo

Una vez almacenado nuestro archivo dentro de la variable doc podemos realizar las operaciones mas comunes de los archivos, la primera es la obtención de las distintas hojas de calculo que puedan encontrarse disponibles dentro de nuestro archivo, de la siguiente forma:

>>> doc.get_sheet_names()
['Sheet1', 'Sheet2', 'Sheet3']
>>> hoja = doc.get_sheet_by_name('Sheet1')
>>> hoja.title
'Sheet1'

El metodo get_sheet_names nos devuelve una lista de strings, los cuales corresponden a todas las hojas disponibles en el archivo. Posteriormente debemos elegir que hoja vamos a mantener en memoria para leer sus filas y columnas, mediante el metodo get_sheet_by_name y su argumento de tipo string, indicamos la hoja de calculo que vamos operar.

Lectura de Celdas

Si abrimos el documento que mencione anteriormente, nos encontramos la información de la siguiente manera:

Excel Sheet Tutorial

Como la hoja de este ejemplo es pequeña, podemos obtener todas las filas y columnas utilizadas o que tengan valor alguno, de la siguiente manera:

>>> hoja.rows
((<Cell Sheet1.A1>, <Cell Sheet1.B1>, <Cell Sheet1.C1>, <Cell Sheet1.D1>, <Cell Sheet1.E1>, <Cell Sheet1.F1>), (<Cell Sheet1.A2>, <Cell Sheet1.B2>, <Cell Sheet1.C2>, <Cell Sheet1.D2>, <Cell Sheet1.E2>, <Cell Sheet1.F2>), (<Cell Sheet1.A3>, <Cell Sheet1.B3>, <Cell Sheet1.C3>, <Cell Sheet1.D3>, <Cell Sheet1.E3>, <Cell Sheet1.F3>), (<Cell Sheet1.A4>, <Cell Sheet1.B4>, <Cell Sheet1.C4>, <Cell Sheet1.D4>, <Cell Sheet1.E4>, <Cell Sheet1.F4>), (<Cell Sheet1.A5>, <Cell Sheet1.B5>, <Cell Sheet1.C5>, <Cell Sheet1.D5>, <Cell Sheet1.E5>, <Cell Sheet1.F5>), (<Cell Sheet1.A6>, <Cell Sheet1.B6>, <Cell Sheet1.C6>, <Cell Sheet1.D6>, <Cell Sheet1.E6>, <Cell Sheet1.F6>), (<Cell Sheet1.A7>, <Cell Sheet1.B7>, <Cell Sheet1.C7>, <Cell Sheet1.D7>, <Cell Sheet1.E7>, <Cell Sheet1.F7>), (<Cell Sheet1.A8>, <Cell Sheet1.B8>, <Cell Sheet1.C8>, <Cell Sheet1.D8>, <Cell Sheet1.E8>, <Cell Sheet1.F8>), (<Cell Sheet1.A9>, <Cell Sheet1.B9>, <Cell Sheet1.C9>, <Cell Sheet1.D9>, <Cell Sheet1.E9>, <Cell Sheet1.F9>), (<Cell Sheet1.A10>, <Cell Sheet1.B10>, <Cell Sheet1.C10>, <Cell Sheet1.D10>, <Cell Sheet1.E10>, <Cell Sheet1.F10>), (<Cell Sheet1.A11>, <Cell Sheet1.B11>, <Cell Sheet1.C11>, <Cell Sheet1.D11>, <Cell Sheet1.E11>, <Cell Sheet1.F11>), (<Cell Sheet1.A12>, <Cell Sheet1.B12>, <Cell Sheet1.C12>, <Cell Sheet1.D12>, <Cell Sheet1.E12>, <Cell Sheet1.F12>), (<Cell Sheet1.A13>, <Cell Sheet1.B13>, <Cell Sheet1.C13>, <Cell Sheet1.D13>, <Cell Sheet1.E13>, <Cell Sheet1.F13>))

La propiedad row nos devuelve una tupla con las multiples filas y columnas de nuestra hoja, si deseamos verlo de otra forma, haciendo uso de un for, podemos recorrer fila por fila:

>>> for filas in hoja.rows:
...     print filas
... 
(<Cell Sheet1.A1>, <Cell Sheet1.B1>, <Cell Sheet1.C1>, <Cell Sheet1.D1>, <Cell Sheet1.E1>, <Cell Sheet1.F1>)
(<Cell Sheet1.A2>, <Cell Sheet1.B2>, <Cell Sheet1.C2>, <Cell Sheet1.D2>, <Cell Sheet1.E2>, <Cell Sheet1.F2>)
(<Cell Sheet1.A3>, <Cell Sheet1.B3>, <Cell Sheet1.C3>, <Cell Sheet1.D3>, <Cell Sheet1.E3>, <Cell Sheet1.F3>)
(<Cell Sheet1.A4>, <Cell Sheet1.B4>, <Cell Sheet1.C4>, <Cell Sheet1.D4>, <Cell Sheet1.E4>, <Cell Sheet1.F4>)
(<Cell Sheet1.A5>, <Cell Sheet1.B5>, <Cell Sheet1.C5>, <Cell Sheet1.D5>, <Cell Sheet1.E5>, <Cell Sheet1.F5>)
(<Cell Sheet1.A6>, <Cell Sheet1.B6>, <Cell Sheet1.C6>, <Cell Sheet1.D6>, <Cell Sheet1.E6>, <Cell Sheet1.F6>)
(<Cell Sheet1.A7>, <Cell Sheet1.B7>, <Cell Sheet1.C7>, <Cell Sheet1.D7>, <Cell Sheet1.E7>, <Cell Sheet1.F7>)
(<Cell Sheet1.A8>, <Cell Sheet1.B8>, <Cell Sheet1.C8>, <Cell Sheet1.D8>, <Cell Sheet1.E8>, <Cell Sheet1.F8>)
(<Cell Sheet1.A9>, <Cell Sheet1.B9>, <Cell Sheet1.C9>, <Cell Sheet1.D9>, <Cell Sheet1.E9>, <Cell Sheet1.F9>)
(<Cell Sheet1.A10>, <Cell Sheet1.B10>, <Cell Sheet1.C10>, <Cell Sheet1.D10>, <Cell Sheet1.E10>, <Cell Sheet1.F10>)
(<Cell Sheet1.A11>, <Cell Sheet1.B11>, <Cell Sheet1.C11>, <Cell Sheet1.D11>, <Cell Sheet1.E11>, <Cell Sheet1.F11>)
(<Cell Sheet1.A12>, <Cell Sheet1.B12>, <Cell Sheet1.C12>, <Cell Sheet1.D12>, <Cell Sheet1.E12>, <Cell Sheet1.F12>)
(<Cell Sheet1.A13>, <Cell Sheet1.B13>, <Cell Sheet1.C13>, <Cell Sheet1.D13>, <Cell Sheet1.E13>, <Cell Sheet1.F13>)

Ahora supongamos que deseamos obtener el valor A1 de nuestra hoja, lo haríamos de la siguiente manera:

>>> hoja['A1'].value
u'Last'

Nos retorna un tipo de dato según el contenido de la celda, en este caso como el primer valor es un string, la propiedad nos devuelve una cadena unicode (compatibilidad con caracteres especiales). Veamos como nos retorna la celda F2 que contiene un entero.

>>> hoja['F2'].value
33040
>>> type(hoja['F2'].value)
<type 'int'>

Ahora podemos darnos cuenta que la libreria nos retorna los valores formateados en tipos de python ¿Muy útil no? :D

Existe otra manera de obtener los valores de nuestras celdas, de forma explicita, indicando la fila y columna mediante el metodo cell, de la siguiente manera:

>>> hoja.cell(row=1,column=1).value
u'Last'

Si nos damos cuenta, ahora no utilice ['A1'] para obtener el valor de la celda, si no que especifique row=1 (Fila 1) y column=1 (Columna 1).

Ahora vamos a recorrer los valores de nuestra hoja de forma básica (no es la mas optima):

>>> for fila in hoja.rows:
...     for columna in fila:
...             print columna.value,
...     print ""
... 
Last First Address City State ZIP 
Buffet Jimmy Somewhere on the Beach Key West FL 33040 
Bush George 1600 Pennsylvania Ave Washington DC 20500 
Cartman Eric 84 Bigboned Way South Park CO 84214 
Crockett Davey The Alamo San Antonio TX 78210 
Doe Jane 821 Zimbabwe Ave Washington DC 20021 
Gates Bill 1 Microsoft Way Redmond WA 98052 
Jefferson George 194 Deelux Apartments In the Sky NY 10041 
Kong King Empire State Building New York NY 10118 
Munster Herman 1313 Mockingbird Lane Fargo ND 58102 
Rockne Knute 146 Keenan Hall Notre Dame IN 46556 
Simpson Homer 742 Evergreen Terrace Springfield US 12345 
Smith Bob 12 Main Street Anytown IN 46001 

La forma de recorrer las celdas dependerá del formato de nuestra hoja de excel, en lo personal utilizo esta librería para automatizar registros de bases de datos (hay que tener cuidado), generar reportes o algún tipo de información estrictamente organizada (Simetría entre Filas y Columnas).

Existen algunos metodos utiles como get_highest_row el cual nos devuelve el ultimo numero de fila utilizado, por su parte el metodo get_highest_column nos devuelve el ultimo numero de columna.

>>> hoja.get_highest_row()
13L
>>> hoja.get_highest_column()
6

Si usas el metodo get_highest_column te estarás preguntando ¿A que letra corresponden los números de las columnas? Bien pues para saberlo tenemos otros métodos que nos proporciona la librería.

>>> from openpyxl.cell import get_column_letter
>>> get_column_letter(hoja.get_highest_column())
'F'

Como podemos apreciar el método get_column_letter nos retorna un string con el valor correspondiente a la letra de la columna.

Recorrido de Filas y Columnas

Hasta aquí hemos trabajado con las filas y columnas directamente, ahora vamos a realizar otra forma de recorrido en la hoja de calculo.

>>> for fila in hoja.rows:
...     for columna in fila:
...             print columna.coordinate,columna.value
...     print "----Final de Fila---"
... 
A1 Last
B1 First
C1 Address
D1 City
E1 State
F1 ZIP
----Final de Fila---
A2 Buffet
B2 Jimmy
C2 Somewhere on the Beach
D2 Key West
E2 FL
F2 33040
----Final de Fila---

Ahora vamos hacer un recorrido mas complicado pero bastante común en este tipo de documentos y es la selección rectangular o de área, como el de la siguiente imagen:

Excel Example 2

En codigo python lo hariamos asi:

>>> seleccion = hoja['A1':'F5']
>>> for filas in seleccion:
...     for columnas in filas:
...             print columnas.coordinate, columnas.value
...     print "--Final de fila--"
... 
A1 Last
B1 First
C1 Address
D1 City
E1 State
F1 ZIP
--Final de fila--
A2 Buffet
B2 Jimmy
C2 Somewhere on the Beach
D2 Key West
E2 FL
F2 33040
--Final de fila--
A3 Bush
B3 George
C3 1600 Pennsylvania Ave
D3 Washington
E3 DC
F3 20500
--Final de fila--
A4 Cartman
B4 Eric
C4 84 Bigboned Way
D4 South Park
E4 CO
F4 84214
--Final de fila--
A5 Crockett
B5 Davey
C5 The Alamo
D5 San Antonio
E5 TX
F5 78210
--Final de fila--

Hasta aquí hemos visto las operaciones de lectura mas relevantes de openpyxl, recordemos que la librería esta hecha a base de hacks, por lo tanto tiene ciertas limitaciones, pero sin dudas es la mas completa en cuanto a opciones de manipulación de datos.

Compartelo en:    

Acerca del Autor

Aarón Díaz R Software Developer

Soy desarrollador de software con experiencia en bases de datos y lenguajes de programación como Python, Java SE, Javascript, C y PHP.

  Comentarios



"El ser de las cosas, no su verdad, es la causa de la verdad en el entendimiento."

- Santo Tomás de Aquino