allow conversion/processing of CSV file to XLSX upon download
This commit is contained in:
parent
7f7a2af25f
commit
516eda33d1
4 changed files with 53 additions and 15 deletions
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2017 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,13 +22,18 @@ View classes for export of report results.
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
import os
|
||||||
|
import time
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.i18n import translate
|
from zope.i18n import translate
|
||||||
|
from zope.traversing.api import getName
|
||||||
|
|
||||||
|
from cybertools.meta.interfaces import IOptions
|
||||||
|
from cybertools.util.date import formatTimeStamp
|
||||||
from loops.common import normalizeName
|
from loops.common import normalizeName
|
||||||
from loops.expert.browser.report import ResultsConceptView
|
from loops.expert.browser.report import ResultsConceptView
|
||||||
from loops.interfaces import ILoopsObject
|
from loops.interfaces import ILoopsObject
|
||||||
from loops.util import _
|
from loops.util import _, getVarDirectory
|
||||||
|
|
||||||
|
|
||||||
class ResultsConceptCSVExport(ResultsConceptView):
|
class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
|
@ -55,10 +60,34 @@ class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
lang = self.languageInfo.language
|
lang = self.languageInfo.language
|
||||||
return translate(_(field.title), target_language=lang)
|
return translate(_(field.title), target_language=lang)
|
||||||
|
|
||||||
|
def getFilepaths(self, name):
|
||||||
|
repName = getName(self.report.context)
|
||||||
|
ts = formatTimeStamp(None, format='%y%m%d%H%M%S')
|
||||||
|
name = '-'.join((ts, repName))
|
||||||
|
return (name + '.csv',
|
||||||
|
name + '.xlsx',
|
||||||
|
repName + '.ods')
|
||||||
|
|
||||||
|
def renderCsv(self, name, src, tgt, tpl):
|
||||||
|
callable = os.path.join('~', 'bin', name)
|
||||||
|
command = ' '.join((callable, src, tgt, tpl))
|
||||||
|
#print '***', command
|
||||||
|
os.popen(command).read()
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
fields = self.displayedColumns
|
fields = self.displayedColumns
|
||||||
fieldNames = [f.name for f in fields]
|
fieldNames = [f.name for f in fields]
|
||||||
output = StringIO()
|
csvRenderer = IOptions(self.report)('csv_renderer')
|
||||||
|
if not csvRenderer:
|
||||||
|
csvRenderer = self.globalOptions('csv_renderer')
|
||||||
|
if csvRenderer:
|
||||||
|
csvRenderer = csvRenderer[0]
|
||||||
|
outfn, inpfn, tplfn = self.getFilepaths(csvRenderer)
|
||||||
|
outpath = os.path.join(getVarDirectory(), 'export', 'excel', outfn)
|
||||||
|
inpath = os.path.join(getVarDirectory(), 'export', 'excel', inpfn)
|
||||||
|
output = open(outpath, 'w')
|
||||||
|
else:
|
||||||
|
output = StringIO()
|
||||||
writer = csv.DictWriter(output, fieldNames, delimiter=self.delimiter)
|
writer = csv.DictWriter(output, fieldNames, delimiter=self.delimiter)
|
||||||
output.write(self.delimiter.join(
|
output.write(self.delimiter.join(
|
||||||
[self.getColumnTitle(f) for f in fields]) + '\n')
|
[self.getColumnTitle(f) for f in fields]) + '\n')
|
||||||
|
@ -73,18 +102,28 @@ class ResultsConceptCSVExport(ResultsConceptView):
|
||||||
value = encode(value, self.encoding)
|
value = encode(value, self.encoding)
|
||||||
data[f.name] = value
|
data[f.name] = value
|
||||||
writer.writerow(data)
|
writer.writerow(data)
|
||||||
text = output.getvalue()
|
if csvRenderer:
|
||||||
self.setDownloadHeader(text)
|
output.close()
|
||||||
|
self.renderCsv(csvRenderer, outfn, inpfn, tplfn)
|
||||||
|
input = open(inpath, 'rb')
|
||||||
|
text = input.read()
|
||||||
|
input.close()
|
||||||
|
self.setDownloadHeader(text)
|
||||||
|
#'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
#'xlsx')
|
||||||
|
else:
|
||||||
|
text = output.getvalue()
|
||||||
|
self.setDownloadHeader(text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def setDownloadHeader(self, text):
|
def setDownloadHeader(self, text, ctype='text/csv', ext='csv'):
|
||||||
response = self.request.response
|
response = self.request.response
|
||||||
response.setHeader('Content-Disposition',
|
response.setHeader('Content-Disposition',
|
||||||
'attachment; filename=%s.csv' %
|
'attachment; filename=%s.%s' %
|
||||||
self.getFileName())
|
(self.getFileName(), ext))
|
||||||
response.setHeader('Cache-Control', '')
|
response.setHeader('Cache-Control', '')
|
||||||
response.setHeader('Pragma', '')
|
response.setHeader('Pragma', '')
|
||||||
response.setHeader('Content-Type', 'text/csv')
|
response.setHeader('Content-Type', ctype)
|
||||||
response.setHeader('Content-Length', len(text))
|
response.setHeader('Content-Length', len(text))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
<!-- $Id$ -->
|
|
||||||
|
|
||||||
<configure
|
<configure
|
||||||
xmlns="http://namespaces.zope.org/zope"
|
xmlns="http://namespaces.zope.org/zope"
|
||||||
xmlns:browser="http://namespaces.zope.org/browser"
|
xmlns:browser="http://namespaces.zope.org/browser"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2017 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,6 +35,7 @@ from cybertools.composer.report.interfaces import IReportParams
|
||||||
from cybertools.composer.report.result import ResultSet, Row
|
from cybertools.composer.report.result import ResultSet, Row
|
||||||
from cybertools.util.jeep import Jeep
|
from cybertools.util.jeep import Jeep
|
||||||
from loops.common import AdapterBase
|
from loops.common import AdapterBase
|
||||||
|
from loops.expert.concept import IQueryConcept, QueryConcept
|
||||||
from loops.interfaces import ILoopsAdapter
|
from loops.interfaces import ILoopsAdapter
|
||||||
from loops.type import TypeInterfaceSourceList
|
from loops.type import TypeInterfaceSourceList
|
||||||
from loops import util
|
from loops import util
|
||||||
|
@ -43,7 +44,7 @@ from loops.util import _
|
||||||
|
|
||||||
# interfaces
|
# interfaces
|
||||||
|
|
||||||
class IReport(ILoopsAdapter, IReportParams):
|
class IReport(ILoopsAdapter, IReportParams, IQueryConcept):
|
||||||
""" The report adapter for the persistent object (concept) that stores
|
""" The report adapter for the persistent object (concept) that stores
|
||||||
the report in the concept map.
|
the report in the concept map.
|
||||||
"""
|
"""
|
||||||
|
@ -66,7 +67,7 @@ class IReportInstance(IBaseReport):
|
||||||
|
|
||||||
# report concept adapter and instances
|
# report concept adapter and instances
|
||||||
|
|
||||||
class Report(AdapterBase):
|
class Report(QueryConcept):
|
||||||
|
|
||||||
implements(IReport)
|
implements(IReport)
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ First we have to make sure that there is a report concept type available.
|
||||||
In addition we need a predicate that connects one or more tasks with a report.
|
In addition we need a predicate that connects one or more tasks with a report.
|
||||||
|
|
||||||
>>> from loops.expert.report import IReport, Report
|
>>> from loops.expert.report import IReport, Report
|
||||||
>>> component.provideAdapter(Report)
|
>>> component.provideAdapter(Report, provides=IReport)
|
||||||
>>> tReport = addAndConfigureObject(concepts, Concept, 'report',
|
>>> tReport = addAndConfigureObject(concepts, Concept, 'report',
|
||||||
... title=u'Report', conceptType=concepts.getTypeConcept(),
|
... title=u'Report', conceptType=concepts.getTypeConcept(),
|
||||||
... typeInterface=IReport)
|
... typeInterface=IReport)
|
||||||
|
|
Loading…
Add table
Reference in a new issue