Python:使用OpenPyXL模拟CSV.DictReader

时间:2016-06-24 21:17:09

标签: python excel openpyxl

我有一个Excel(.xlsx)文件,我试图逐行解析。我有一个标题(第一行),有一堆列标题,如学校,名字,姓氏,电子邮件等。

当我遍历每一行时,我希望能够说出类似的内容:

row['School']

并使用' School'获取当前行和列中单元格的值。作为标题。

我查看了OpenPyXL文档,但似乎找不到任何有用的东西。

有什么建议吗?

4 个答案:

答案 0 :(得分:0)

Excel工作表比CSV文件更灵活,因此使用像DictReader这样的东西是没有意义的。

只需从相关的列标题创建一个辅助字典。

如果您有"School", "First Name", "Last Name", "EMail"之类的列,则可以像这样创建字典。

keys = dict((value, idx) for (idx, value) in enumerate(values))
for row in ws.rows[1:]:
    school = row[keys['School'].value

答案 1 :(得分:0)

我对OpenPyXL并不十分熟悉,但是据我所知,它没有任何字典阅读器/迭代器帮助器。但是,迭代工作表行以及从两个值列表创建dict都是很容易的。

def iter_worksheet(worksheet):
    # It's necessary to get a reference to the generator, as 
    # `worksheet.rows` returns a new iterator on each access.
    rows = worksheet.rows

    # Get the header values as keys and move the iterator to the next item
    keys = [c.value for c in next(rows)]
    for row in rows:
        values = [c.value for c in row]
        yield dict(zip(keys, values))

答案 2 :(得分:0)

我基于openpyxl编写了DictReader。将第二个清单保存到文件“ excel.py”,并将其用作csv.DictReader。请参阅第一个清单中的用法示例。

with open('example01.xlsx', 'rb') as source_data:
    from excel import DictReader

    for row in DictReader(source_data, sheet_index=0):
        print(row)

excel.py:

__all__ = ['DictReader']

from openpyxl import load_workbook
from openpyxl.cell import Cell

Cell.__init__.__defaults__ = (None, None, '', None)   # Change the default value for the Cell from None to `` the same way as in csv.DictReader


class DictReader(object):
    def __init__(self, f, sheet_index,
                 fieldnames=None, restkey=None, restval=None):
        self._fieldnames = fieldnames   # list of keys for the dict
        self.restkey  = restkey         # key to catch long rows
        self.restval  = restval         # default value for short rows
        self.reader   = load_workbook(f, data_only=True).worksheets[sheet_index].iter_rows(values_only=True)
        self.line_num = 0

    def __iter__(self):
        return self

    @property
    def fieldnames(self):
        if self._fieldnames is None:
            try:
                self._fieldnames = next(self.reader)
                self.line_num += 1
            except StopIteration:
                pass

        return self._fieldnames

    @fieldnames.setter
    def fieldnames(self, value):
        self._fieldnames = value

    def __next__(self):
        if self.line_num == 0:
            # Used only for its side effect.
            self.fieldnames

        row = next(self.reader)
        self.line_num += 1

        # unlike the basic reader, we prefer not to return blanks,
        # because we will typically wind up with a dict full of None
        # values
        while row == ():
            row = next(self.reader)

        d = dict(zip(self.fieldnames, row))
        lf = len(self.fieldnames)
        lr = len(row)

        if lf < lr:
            d[self.restkey] = row[lf:]
        elif lf > lr:
            for key in self.fieldnames[lr:]:
                d[key] = self.restval

        return d

答案 3 :(得分:0)

以下内容似乎对我有用。

    header = True
    headings = []
    for row in ws.rows:
        if header:
            for cell in row:
                headings.append(cell.value)
            header = False
            continue
        rowData = dict(zip(headings, row))
        wantedValue = rowData['myHeading'].value