在Linux中从Excel数据透视表电子表格中提取数据
我有一个基于数据透视表的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格式;这对我来说应该不会太难(尽管非常感谢帮助)。
你试过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]
>>>
我曾经有过同样的问题。您可以解压缩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 "PAMPERS" 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).
其余的是历史,我希望这会帮助你。
快乐编码!
正确。但是有一个细节:如果数据透视表数据是隐藏的(只有摘要显示在表中),它可能不在同一张表中,而在数据对象中。在这种情况下,可以很容易地用例如数据提取xml数据。方舟(解压xlsx) – 2017-08-10 07:47:30