Ler arquivo do Excel em Python


88

Eu tenho um arquivo Excel

Arm_id      DSPName        DSPCode          HubCode          PinCode    PPTL
1            JaVAS            01              AGR             282001    1,2
2            JaVAS            01              AGR             282002    3,4
3            JaVAS            01              AGR             282003    5,6

Quero salvar uma string no formulário Arm_id,DSPCode,Pincode. Este formato é configurável, ou seja, pode mudar para DSPCode,Arm_id,Pincode. Eu salvo em uma lista como:

FORMAT = ['Arm_id', 'DSPName', 'Pincode']

Como leio o conteúdo de uma coluna específica com o nome fornecido, visto que o FORMATé configurável?

Isso é o que eu tentei. Atualmente consigo ler todo o conteúdo do arquivo

from xlrd import open_workbook
wb = open_workbook('sample.xls')
for s in wb.sheets():
    #print 'Sheet:',s.name
    values = []
    for row in range(s.nrows):
        col_value = []
        for col in range(s.ncols):
            value  = (s.cell(row,col).value)
            try : value = str(int(value))
            except : pass
            col_value.append(value)
        values.append(col_value)
print values

Minha saída é

[[u'Arm_id', u'DSPName', u'DSPCode', u'HubCode', u'PinCode', u'PPTL'], ['1', u'JaVAS', '1', u'AGR', '282001', u'1,2'], ['2', u'JaVAS', '1', u'AGR', '282002', u'3,4'], ['3', u'JaVAS', '1', u'AGR', '282003', u'5,6']]

Em seguida, faço um loop values[0]tentando descobrir o FORMATconteúdo values[0]e obtendo o índice de Arm_id, DSPname and Pincodeno values[0]e, a partir do próximo loop, conheço o índice de todos os FORMATfatores e, assim, fico sabendo qual valor preciso obter.

Mas esta é uma solução tão ruim.

Como faço para obter os valores de uma coluna específica com nome no arquivo excel?


Você deve usar dict()ou criar sua própria classe de dados.
tamasgal

Tipo, como? você pode fornecer um código de amostra?
PythonEnthusiast

Respostas:


70

Esta é uma abordagem:

from xlrd import open_workbook

class Arm(object):
    def __init__(self, id, dsp_name, dsp_code, hub_code, pin_code, pptl):
        self.id = id
        self.dsp_name = dsp_name
        self.dsp_code = dsp_code
        self.hub_code = hub_code
        self.pin_code = pin_code
        self.pptl = pptl

    def __str__(self):
        return("Arm object:\n"
               "  Arm_id = {0}\n"
               "  DSPName = {1}\n"
               "  DSPCode = {2}\n"
               "  HubCode = {3}\n"
               "  PinCode = {4} \n"
               "  PPTL = {5}"
               .format(self.id, self.dsp_name, self.dsp_code,
                       self.hub_code, self.pin_code, self.pptl))

wb = open_workbook('sample.xls')
for sheet in wb.sheets():
    number_of_rows = sheet.nrows
    number_of_columns = sheet.ncols

    items = []

    rows = []
    for row in range(1, number_of_rows):
        values = []
        for col in range(number_of_columns):
            value  = (sheet.cell(row,col).value)
            try:
                value = str(int(value))
            except ValueError:
                pass
            finally:
                values.append(value)
        item = Arm(*values)
        items.append(item)

for item in items:
    print item
    print("Accessing one single value (eg. DSPName): {0}".format(item.dsp_name))
    print

Você não precisa usar uma classe personalizada, você pode simplesmente fazer um dict(). Se você usar uma classe, no entanto, poderá acessar todos os valores por meio da notação de ponto, como pode ser visto acima.

Aqui está o resultado do script acima:

Arm object:
  Arm_id = 1
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282001 
  PPTL = 1
Accessing one single value (eg. DSPName): JaVAS

Arm object:
  Arm_id = 2
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282002 
  PPTL = 3
Accessing one single value (eg. DSPName): JaVAS

Arm object:
  Arm_id = 3
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282003 
  PPTL = 5
Accessing one single value (eg. DSPName): JaVAS

90

Uma resposta um tanto tardia, mas com o pandas, é possível obter diretamente uma coluna de um arquivo excel:

import pandas

df = pandas.read_excel('sample.xls')
#print the column names
print df.columns
#get the values for a given column
values = df['Arm_id'].values
#get a data frame with selected columns
FORMAT = ['Arm_id', 'DSPName', 'Pincode']
df_selected = df[FORMAT]

Certifique-se de ter instalado o xlrd e o pandas:

pip install pandas xlrd

2
Adicione import xlrdno topo para fazer este trabalho. read_excelrequer xlrd. Se conseguir ImportError: No module named 'xlrd', façapip install xlrd
nishant

9
importar o xlrd não é necessário, apenas certifique-se de que o xlrd esteja instalado, o pandas irá importá-lo e usá-lo.
Vaibhav Vishal,

12

Portanto, as partes principais são pegar o cabeçalho ( col_names = s.row(0)) e, ao iterar pelas linhas, pular a primeira linha que não é necessária for row in range(1, s.nrows)- feito usando intervalo de 1 em diante (não o 0 implícito). Em seguida, use zip para percorrer as linhas que contêm 'nome' como cabeçalho da coluna.

from xlrd import open_workbook

wb = open_workbook('Book2.xls')
values = []
for s in wb.sheets():
    #print 'Sheet:',s.name
    for row in range(1, s.nrows):
        col_names = s.row(0)
        col_value = []
        for name, col in zip(col_names, range(s.ncols)):
            value  = (s.cell(row,col).value)
            try : value = str(int(value))
            except : pass
            col_value.append((name.value, value))
        values.append(col_value)
print values


2

Aqui está o código para ler um arquivo Excel e imprimir todas as células presentes na coluna 1 (exceto a primeira célula, ou seja, o cabeçalho):

import xlrd

file_location="C:\pythonprog\xxx.xlsv"
workbook=xlrd.open_workbook(file_location)
sheet=workbook.sheet_by_index(0)
print(sheet.cell_value(0,0))

for row in range(1,sheet.nrows):
     print(sheet.cell_value(row,0))

1

A abordagem que usei lê as informações do cabeçalho da primeira linha para determinar os índices das colunas de interesse.

Você mencionou na pergunta que também deseja a saída dos valores em uma string. Eu construo dinamicamente uma string de formato para a saída da lista de colunas FORMAT. As linhas são anexadas à string de valores separada por um novo caractere de linha.

A ordem das colunas de saída é determinada pela ordem dos nomes das colunas na lista FORMAT.

No meu código abaixo, o caso do nome da coluna na lista FORMAT é importante. Na pergunta acima, você tem 'Pincode' em sua lista de FORMAT, mas 'PinCode' em seu Excel. Abaixo, isso não funcionaria, precisaria ser 'PinCode'.

from xlrd import open_workbook
wb = open_workbook('sample.xls')

FORMAT = ['Arm_id', 'DSPName', 'PinCode']
values = ""

for s in wb.sheets():
    headerRow = s.row(0)
    columnIndex = [x for y in FORMAT for x in range(len(headerRow)) if y == firstRow[x].value]
    formatString = ("%s,"*len(columnIndex))[0:-1] + "\n"

    for row in range(1,s.nrows):
        currentRow = s.row(row)
        currentRowValues = [currentRow[x].value for x in columnIndex]
        values += formatString % tuple(currentRowValues)

print values

Para a entrada de amostra que você forneceu acima, este código resulta:

>>> 1.0,JaVAS,282001.0
2.0,JaVAS,282002.0
3.0,JaVAS,282003.0

E porque sou um python noob, os adereços sejam: esta resposta , esta resposta , esta pergunta , esta pergunta e esta resposta .


Acho que firstRow[x].valuedeveria serheaderRow[x].value
TSeymour

0

Embora quase sempre use apenas o pandas para isso, minha pequena ferramenta atual está sendo compactada em um executável e incluir o pandas é um exagero. Portanto, criei uma versão da solução de poida que resultou em uma lista de tuplas nomeadas. Seu código com essa mudança ficaria assim:

from xlrd import open_workbook
from collections import namedtuple
from pprint import pprint

wb = open_workbook('sample.xls')

FORMAT = ['Arm_id', 'DSPName', 'PinCode']
OneRow = namedtuple('OneRow', ' '.join(FORMAT))
all_rows = []

for s in wb.sheets():
    headerRow = s.row(0)
    columnIndex = [x for y in FORMAT for x in range(len(headerRow)) if y == headerRow[x].value]

    for row in range(1,s.nrows):
        currentRow = s.row(row)
        currentRowValues = [currentRow[x].value for x in columnIndex]
        all_rows.append(OneRow(*currentRowValues))

pprint(all_rows)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.