使用Python pandas从Excel文件中读取子/上标

时间:2017-12-01 00:33:58

标签: python excel pandas unicode

我正在尝试从Excel文件中读取格式化文本。它由一系列反应组成,一些反应物有下标,而其他反应物有上标。我正在努力区分上标和下标。

例如,反应物是:

O2+ 

我想区别于

O2+

这里有一个相关的问题: Usage of unicode() and encode() functions in Python

由此,我想也许我应该将字符串转换为unicode,但是pandas似乎根本不会读取上标/下标。

1 个答案:

答案 0 :(得分:0)

Pandas使用xlrd读取Excel文件,遗憾的是xlrd不解析单元格中使用的格式。

openpyxl包可以处理字符串格式,但仅适用于较旧的.xls格式。您可能需要编写一个查看基础XML数据的自定义解析器。

.xlsx文件只是一个包含xml文件集合的zip存档。你需要看的两个是

  • file.xlsx / XL / sharedStrings.xml
  • file.xlsx / xl / worksheets / sheet1.xml(或无论您的工作表名称是什么)

第一个文件包含字符串及其格式。第二个文件包含工作表中的单元格以及它们引用的字符串。字符串在sharedStrings.xml中按顺序引用。

以下是excel表示例的屏幕截图:

enter image description here

示例sharedStrings.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3">
  <si>
    <r>
      <t>O</t>
    </r>
    <r>
      <rPr>
        <vertAlign val="subscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
      </rPr>
      <t>2</t>
    </r>
    <r>
      <rPr>
        <vertAlign val="superscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
      </rPr>
      <t>+</t>
    </r>
  </si>
  <si>
    <r>
      <t>H</t>
    </r>
    <r>
      <rPr>
        <vertAlign val="subscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
      </rPr>
      <t>2</t>
    </r>
    <r>
      <rPr>
        <sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
      </rPr>
      <t>O</t>
    </r>
  </si>
  <si>
    <r>
      <t>O</t>
    </r>
    <r>
      <rPr>
        <vertAlign val="superscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
      </rPr>
      <t>2+</t>
    </r>
  </si>
</sst>

每个<si>元素都是一堆文本。 <r>元素是一组字符和格式。 <t>元素是实际字符,前面的<rPr>元素是样式/格式。您可以区分上标和下标何时出现在<vertAlign>元素中。

sheet1.xml的示例:

<?xml version="1.0" encoding="UTF-8"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac">
  <dimension ref="A1:A3" />
  <sheetViews>
    <sheetView tabSelected="1" workbookViewId="0">
      <selection activeCell="A4" sqref="A4" />
    </sheetView>
  </sheetViews>
  <sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25" />
  <sheetData>
    <row r="1" spans="1:1" ht="18.75" x14ac:dyDescent="0.35">
      <c r="A1" t="s">
        <v>0</v>
      </c>
    </row>
    <row r="2" spans="1:1" ht="18" x14ac:dyDescent="0.35">
      <c r="A2" t="s">
        <v>1</v>
      </c>
    </row>
    <row r="3" spans="1:1" ht="17.25" x14ac:dyDescent="0.25">
      <c r="A3" t="s">
        <v>2</v>
      </c>
    </row>
  </sheetData>
  <pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3" />
  <pageSetup orientation="portrait" r:id="rId1" />
</worksheet>

单元格元素<c>包含在<row>元素中。 <v>的值是对共享字符串的顺序/索引的引用。因此,单元格A1具有第0个sharedString的值,该值为0,后跟下标2,后跟上标+

<si>
<r>
  <t>O</t>
</r>
<r>
  <rPr>
    <vertAlign val="subscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
  </rPr>
  <t>2</t>
</r>
<r>
  <rPr>
    <vertAlign val="superscript"/><sz val="11"/><color theme="1"/><rFont val="Calibri"/><family val="2"/><scheme val="minor" />
  </rPr>
  <t>+</t>
</r>
</si>

要开始解析Excel文件,您可以使用:

import zipfile
from lxml import etree

z = zipfile.ZipFile('file.xlsx')

with z.open('xl/sharedStrings.xml') as fp:
    ss = etree.fromstring(fp.read())

with z.open('xl/worksheets/sheet1.xml') as fp:
    sh1 = etree.fromstring(fp.read())

z.close()

# get the namespaces
ssns = ss.nsmap
if None in ssns:
    ssns['none'] = ssns.pop(None)

sh1ns = sh1.nsmap
if None in sh1ns:
    sh1ns['none'] = sh1ns.pop(None)

text_list = ss.xpath('//none:si', namespaces=ssns)
cell_list = sh1.xpath('//none:c', namespaces=sh1ns)

您必须编写一个解析器来将格式转换为您想要的格式。