Извлечение данных из электронной таблицы Excel Pivot Table в Linux - PullRequest
3 голосов
/ 14 декабря 2010

У меня есть таблица Excel, основанная на сводной таблице, которая периодически обновляется (ежемесячно) и загружается на мой сервер (генерируется группой, которая не решается что-либо изменить в выходных данных). Я хотел бы иметь возможность написать скрипт, который я мог бы запустить через задание cron для обработки и загрузки необработанных данных из сводной таблицы в мою базу данных.

Однако я не могу понять, как получить базовые данные, не заходя вручную в окна, открывая файл в Excel, дважды щелкая по ячейке итогов, получая новый лист со всеми необработанными данными, которые попали в заполнение. эту ячейку и сохраняя этот лист как CSV, который я затем могу загрузить в свою базу данных с помощью некоторого языка (в моем случае Python). Кажется, что они должны быть каким-то сценарием способ извлечения основных данных.

У меня есть только машины Linux (работающие под управлением windows / office на виртуальной машине; но я бы предпочел решение, не включающее windows). Я знаком с такими инструментами, как xls2csv (который не имеет доступа к необработанным данным) и использую такие инструменты, как python-unoconv, для редактирования документов openoffice из python. Однако даже вручную, используя openoffice, я не вижу способа получить доступ к базовым данным.

РЕДАКТИРОВАТЬ: потратив добрых несколько часов, не делая никаких успехов (до публикации), я не начну делать некоторые, преобразовав их в ODS через unoconv и, вероятно, смогу использовать что-то с python-odf для извлеките последний лист (называется «DPCache»).

Итак, теперь проблема в том, чтобы получить лист из СОД, преобразованный в CSV; это не должно быть слишком трудно для меня, чтобы понять (хотя помощь очень ценится).

Ответы [ 2 ]

1 голос
/ 14 декабря 2010

Вы пробовали xlrd ? См. Также учебное пособие, доступное на веб-сайте python-excel .

Это так просто:

>>> 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 голосов
/ 12 января 2018

Раньше у меня была такая же проблема. Вы можете решить, распаковав xlsx и прочитав / интерпретировав xml-файлы. Два файла, которые являются более важными, - это.

  • х / pivotCache / pivotCacheDefinition1.xml
  • х / pivotCache / pivotCacheRecords1.xml

Первый из них имеет отношение к исходным данным в pivotCacheRecords1.xml, к которым вам нужно обращаться по номеру индекса, что я имею в виду под каждым из столбцов в pivotCacheRecords1.xml, имеющих тег <x> вам нужно получить данные в pivotCacheDefinition1.xml по порядковому номеру тега <x>, для лучшего понимания вам нужно просмотреть файлы 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>

Обратите внимание, что тег <x> в CacheRecords1 является отношением для тега <s> в CacheDefinition1, и теперь, если вы понимаете это, не так уж сложно сделать диктат для использования его в итерациях записей.

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

Остальное уже история, я бы хотел, чтобы это помогло вам.

Счастливое кодирование !!!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...