2010-12-13 107 views
3

我有一個基於數據透視表的Excel電子數據表,該數據表定期更新(每月)並上傳到我的服務器(由非常猶豫改變輸出內容的組生成) 。我希望能夠編寫一個可以通過cron作業運行的腳本,以便將數據透視表中的原始數據加載並加載到我的數據庫中。在Linux中從Excel數據透視表電子表格中提取數據

但是,我無法弄清楚如何在不手動進入windows的情況下獲取底層數據,在Excel中打開文件,雙擊總計單元格,獲取所有進入的原始數據的新表單填充該單元格,然後將該表格保存爲csv,然後可以通過某種語言(我的情況python)加載到我的數據庫中。看起來他們應該是一些腳本化的方式來提取底層數據。我只有Linux機器(在VM中運行Windows/Office;但我更喜歡不涉及Windows的解決方案)。我熟悉像xls2csv(不訪問原始數據)和使用像python-unoconv這樣的工具從python編輯openoffice文檔的工具。但是,即使手動使用openoffice,我也沒有辦法看到底層數據。

編輯:花了好幾個小時沒有取得任何進展(發佈之前),我沒有開始通過unoconv將其轉換爲ODS,並可能會使用python-odf提取最後一張紙(稱爲'DPCache')。

所以現在的問題是從ODS中獲取一張表格轉換成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] 
>>> 
+0

正確。但是有一個細節:如果數據透視表數據是隱藏的(只有摘要顯示在表中),它可能不在同一張表中,而在數據對象中。在這種情況下,可以很容易地用例如數據提取xml數據。方舟(解壓xlsx) – 2017-08-10 07:47:30

0

我曾經有過同樣的問題。您可以解壓縮xlsx並讀取/解釋xml文件。這兩個更重要的文件就是這些。

  • XL/pivotCache/pivotCacheDefinition1.xml
  • XL/pivotCache/pivotCacheRecords1.xml

第一個,在pivotCacheRecords1.xml原始數據的relationshit,你需要訪問通過索引號,我的意思是,通過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標籤<x>是在CacheDefinition1的<s>標籤的關係,現在如果你明白的話這對於在記錄的迭代中使用它來說並不那麼困難。

 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和列的索引與defdict的密鑰相匹配時,標籤是<x>

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). 

其餘的是歷史,我希望這會幫助你。

快樂編碼!

相關問題