【问题标题】:Extracting data from Excel Pivot Table Spreadsheet in Linux在 Linux 中从 Excel 数据透视表电子表格中提取数据
【发布时间】:2011-05-24 22:52:43
【问题描述】:

我有一个基于数据透视表的 excel 电子表格,它会定期(每月)更新并上传到我的服务器(由一个对更改输出中的任何内容非常犹豫的小组生成)。我希望能够编写一个可以通过 cron 作业运行的脚本,以处理数据透视表中的原始数据并将其加载到我的数据库中。

但是,如果不手动进入窗口、在 excel 中打开文件、双击总计单元格、获取包含所有原始数据的新工作表,我无法弄清楚如何获取基础数据。该单元格,并将该表保存为 csv,然后我可以通过某种语言(在我的情况下为 python)将其加载到我的数据库中。看起来他们应该是一些提取基础数据的脚本方式。

我只有 linux 机器(在 VM 中运行 windows/office;但我更喜欢不涉及 windows 的解决方案)。我熟悉 xls2csv 之类的工具(它不访问原始数据)并使用 python-unoconv 之类的工具从 python 编辑 openoffice 文档。但是,即使手动使用 openoffice,我也看不到获取基础数据的方法。

编辑:花了好几个小时没有取得任何进展(在发布之前),我没有开始通过 unoconv 将其转换为 ODS 并可能能够使用 python-odf 来做一些事情提取最后一张表(称为“DPCache”)。

所以现在的问题是从 ODS 中获取一张转换为 CSV 的表格;这对我来说应该不难弄清楚(尽管非常感谢您的帮助)。

【问题讨论】:

    标签: python linux excel csv


    【解决方案1】:

    你试过xlrd吗?另请参阅python-excel website 提供的教程。

    就这么简单:

    >>> import xlrd
    >>> book = xlrd.open_workbook('pivot_table_demo.xls')
    >>> sheet = book.sheet_by_name('Summary')
    >>> for row_index in xrange(sheet.nrows):
    ...     print sheet.row_values(row_index)
    ...
    [u'Sum of sales', u'qtr', '', '', '', '']
    [u'person', 1.0, 2.0, 3.0, 4.0, u'Grand Total']
    [u'dick', 100.0, 99.0, 95.0, 90.0, 384.0]
    [u'harriet', 100.0, 110.0, 121.0, 133.1, 464.1]
    [u'tom', 100.0, 101.0, 102.0, 103.0, 406.0]
    [u'Grand Total', 300.0, 310.0, 318.0, 326.1, 1254.1]
    >>>
    

    【讨论】:

    • 正确。但是有一个细节:如果数据透视表数据被隐藏(工作表中仅显示摘要),则可能无法在同一工作表中找到它,而是在数据对象中找到它。在这种情况下,使用例如提取 xml 数据可能很容易。方舟(解压xlsx)
    【解决方案2】:

    我以前也有同样的问题。您可以通过解压缩 xlsx 并阅读/解释 xml 文件来解决。更重要的两个文件是这些。

    • xl/pivotCache/pivotCacheDefinition1.xml
    • xl/pivotCache/pivotCacheRecords1.xml

    第一个,有pivotCacheRecords1.xml中原始数据的关系,你需要通过索引号访问,我的意思是,pivotCacheRecords1.xml中的每一列都有标签<x>需要通过标签<x>的索引号来获取pivotCacheDefinition1.xml中的数据,为了更好的理解,需要查看xml文件。

    pivotCacheDefinition1.xml

        <?xml version="1.0" encoding="UTF-8"?>
    <pivotCacheDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId1" refreshedBy="ADNLatam" refreshedDate="42972.64919178241" createdVersion="5" refreshedVersion="6" recordCount="1923161">
       <cacheSource type="external" connectionId="1" />
       <cacheFields count="26">
          <cacheField name="C - Cadenas" numFmtId="0" sqlType="-9">
             <sharedItems count="3">
                <s v="superA" />
                <s v="superB" />
                <s v="superC" u="1" />
             </sharedItems>
          </cacheField>
          <cacheField name="C - Locales" numFmtId="0" sqlType="-9"><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
             <sharedItems count="80">
                <s v="Itaugua" />
                <s v="Denis Roa" />
                <s v="Total" />
                <s v="Los Laureles" />
                <s v="CDE" />
                <s v="S6 Fdo." />
                <s v="Central" u="1" />
                <s v="Unicompra" u="1" />
                <s v="San Lorenzo Centro" u="1" />
             </sharedItems>
          </cacheField>
       </cacheFields>
    </pivotCacheDefinition>
    </xml>
    

    pivotCacheRecords1.xml

    <pivotCacheRecords
    xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" count="246209">
    <r>
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <s v="PAÐAL &quot;PAMPERS&quot; BABYSAN REGULAR GDE 9UN"/> #Z - Sku / Descripcion
        <s v="07501006720341"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <n v="1"/> 
        <n v="11990"/> 
        <n v="2.3199999999999998"/> 
        <n v="10900"/> 
        <n v="11990"/> 
        <n v="1"/> 
        <d v="2012-02-03T00:00:00"/> 
        <x v="0"/> 
        <x v="0"/> 
        <n v="3"/> 
        <n v="6"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
        <x v="0"/> 
    </r>
    

    看到 CacheRecords1 标记中的&lt;x&gt; 是 CacheDefinition1 中&lt;s&gt; 标记的关系,现在如果你理解了这一点,那么在记录的迭代中使用它并不难。

          definitions = '/tmp/scantrack_tmp/xl/pivotCache/pivotCacheDefinition1.xml'
          defdict = {}
          columnas = []
          e = xml.etree.ElementTree.parse(definitions).getroot()
          for fields in e.findall('{http://schemas.openxmlformats.org/spreadsheetml/2006/main}cacheFields'):
              for cidx, field in enumerate(fields.getchildren()):
                  columna = field.attrib.get('name')
                  defdict[cidx] = []
                  columnas.append(columna)
                  for value in field.getchildren()[0].getchildren():
                      tagname = value.tag
                      defdict[cidx].append(value.attrib.get('v', 0))
    

    我们最终得到了这个字典。

    {
      0: ['supera', 'superb', u'superc'],
      1: ['Terminal',
         'CDE',
         'Brasilia',
         ]
      3: ['PANTENE', 'DOVE']
      ...
    }
    

    然后你要做的就是遍历 CacheRecords1 并在标签为 &lt;x&gt; 时将列的索引与 defdict 中的键匹配

      dfdata = []
    
    
      bdata = '/tmp/scantrack_tmp/xl/pivotCache/pivotCacheRecords1.xml'
    
      for event, elem in xml.etree.ElementTree.iterparse(bdata, events=('start', 'end')):
        if elem.tag == '{http://schemas.openxmlformats.org/spreadsheetml/2006/main}r' and event == 'start':
           tmpdata = []
           for cidx, valueobj in enumerate(elem.getchildren()):
               tagname = valueobj.tag
               vattrib = valueobj.attrib.get('v')
               rdata = vattrib
               if tagname == '{http://schemas.openxmlformats.org/spreadsheetml/2006/main}x':
                    try:
                      rdata = defdict[cidx][int(vattrib)]
                    except:
                      logging.error('this it not should happen index cidx = {} vattrib = {} defaultidcts = {} tmpdata for the time = {} xml raw {}'.format(
                                                                                                                                                    cidx, vattrib, defdict, tmpdata,
                                                                                                                                                    xml.etree.ElementTree.tostring(elem, encoding='utf8', method='xml')
                                                                                                                                                    ))
               tmpdata.append(rdata)
           if tmpdata:
               dfdata.append(tmpdata)
           elem.clear()
    

    然后你可以把 dfdata 放到一个数据框里

    df = pd.DataFrame(dfdata).
    

    剩下的就是历史了,希望对你有所帮助。

    编码愉快!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      相关资源
      最近更新 更多