| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- # Copyright (C) 2008 Agustin Henze -> agustinhenze at gmail.com
- #
- # This is free software. You may redistribute it under the terms
- # of the Apache license and the GNU General Public License Version
- # 2 or at your option any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public
- # License along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- #
- # Contributor(s):
- #
- # Søren Roug
- #
- # Oct 2014: Georges Khaznadar <georgesk@debian.org>
- # - ported to Python3
- # - imlemented the missing switch -c / --encoding, with an extra
- # feature for POSIX platforms which can guess encoding.
- from odf.opendocument import OpenDocumentSpreadsheet
- from odf.style import Style, TextProperties, ParagraphProperties, TableColumnProperties
- from odf.text import P
- from odf.table import Table, TableColumn, TableRow, TableCell
- from optparse import OptionParser
- import sys,csv,re, os, codecs
- if sys.version_info[0]==3: unicode=str
- if sys.version_info[0]==2:
- class UTF8Recoder:
- """
- Iterator that reads an encoded stream and reencodes the input to UTF-8
- """
- def __init__(self, f, encoding):
- self.reader = codecs.getreader(encoding)(f)
- def __iter__(self):
- return self
- def next(self):
- return self.reader.next().encode("utf-8")
- class UnicodeReader:
- """
- A CSV reader which will iterate over lines in the CSV file "f",
- which is encoded in the given encoding.
- """
- def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
- f = UTF8Recoder(f, encoding)
- self.reader = csv.reader(f, dialect=dialect, **kwds)
- def next(self):
- row = self.reader.next()
- return [unicode(s, "utf-8") for s in row]
- def __iter__(self):
- return self
- def csvToOds( pathFileCSV, pathFileODS, tableName='table',
- delimiter=',', quoting=csv.QUOTE_MINIMAL,
- quotechar = '"', escapechar = None,
- skipinitialspace = False, lineterminator = '\r\n',
- encoding="utf-8"):
- textdoc = OpenDocumentSpreadsheet()
- # Create a style for the table content. One we can modify
- # later in the word processor.
- tablecontents = Style(name="Table Contents", family="paragraph")
- tablecontents.addElement(ParagraphProperties(numberlines="false", linenumber="0"))
- tablecontents.addElement(TextProperties(fontweight="bold"))
- textdoc.styles.addElement(tablecontents)
- # Start the table
- table = Table( name=tableName )
- if sys.version_info[0]==3:
- reader = csv.reader(open(pathFileCSV, encoding=encoding),
- delimiter=delimiter,
- quoting=quoting,
- quotechar=quotechar,
- escapechar=escapechar,
- skipinitialspace=skipinitialspace,
- lineterminator=lineterminator)
- else:
- reader = UnicodeReader(open(pathFileCSV),
- encoding=encoding,
- delimiter=delimiter,
- quoting=quoting,
- quotechar=quotechar,
- escapechar=escapechar,
- skipinitialspace=skipinitialspace,
- lineterminator=lineterminator)
- fltExp = re.compile('^\s*[-+]?\d+(\.\d+)?\s*$')
- for row in reader:
- tr = TableRow()
- table.addElement(tr)
- for val in row:
- if fltExp.match(val):
- tc = TableCell(valuetype="float", value=val.strip())
- else:
- tc = TableCell(valuetype="string")
- tr.addElement(tc)
- p = P(stylename=tablecontents,text=val)
- tc.addElement(p)
- textdoc.spreadsheet.addElement(table)
- textdoc.save( pathFileODS )
- if __name__ == "__main__":
- usage = "%prog -i file.csv -o file.ods -d"
- parser = OptionParser(usage=usage, version="%prog 0.1")
- parser.add_option('-i','--input', action='store',
- dest='input', help='File input in csv')
- parser.add_option('-o','--output', action='store',
- dest='output', help='File output in ods')
- parser.add_option('-d','--delimiter', action='store',
- dest='delimiter', help='specifies a one-character string to use as the field separator. It defaults to ",".')
- parser.add_option('-c','--encoding', action='store',
- dest='encoding', help='specifies the encoding the file csv. It defaults to utf-8')
- parser.add_option('-t','--table', action='store',
- dest='tableName', help='The table name in the output file')
- parser.add_option('-s','--skipinitialspace',
- dest='skipinitialspace', help='''specifies how to interpret whitespace which
- immediately follows a delimiter. It defaults to False, which
- means that whitespace immediately following a delimiter is part
- of the following field.''')
- parser.add_option('-l','--lineterminator', action='store',
- dest='lineterminator', help='''specifies the character sequence which should
- terminate rows.''')
- parser.add_option('-q','--quoting', action='store',
- dest='quoting', help='''It can take on any of the following module constants:
- 0 = QUOTE_MINIMAL means only when required, for example, when a field contains either the quotechar or the delimiter
- 1 = QUOTE_ALL means that quotes are always placed around fields.
- 2 = QUOTE_NONNUMERIC means that quotes are always placed around fields which do not parse as integers or floating point numbers.
- 3 = QUOTE_NONE means that quotes are never placed around fields.
- It defaults is QUOTE_MINIMAL''')
- parser.add_option('-e','--escapechar', action='store',
- dest='escapechar', help='''specifies a one-character string used to escape the delimiter when quoting is set to QUOTE_NONE.''')
- parser.add_option('-r','--quotechar', action='store',
- dest='quotechar', help='''specifies a one-character string to use as the quoting character. It defaults to ".''')
- (options, args) = parser.parse_args()
- if options.input:
- pathFileCSV = options.input
- else:
- parser.print_help()
- exit( 0 )
- if options.output:
- pathFileODS = options.output
- else:
- parser.print_help()
- exit( 0 )
- if options.delimiter:
- delimiter = options.delimiter
- else:
- delimiter = ","
- if options.skipinitialspace:
- skipinitialspace = True
- else:
- skipinitialspace=False
- if options.lineterminator:
- lineterminator = options.lineterminator
- else:
- lineterminator ="\r\n"
- if options.escapechar:
- escapechar = options.escapechar
- else:
- escapechar=None
- if options.tableName:
- tableName = options.tableName
- else:
- tableName = "table"
- if options.quotechar:
- quotechar = options.quotechar
- else:
- quotechar = "\""
- encoding = "utf-8" # default setting
- ###########################################################
- ## try to guess the encoding; this is implemented only with
- ## POSIX platforms. Can it be improved?
- output = os.popen('/usr/bin/file ' + pathFileCSV).read()
- m=re.match(r'^.*: ([-a-zA-Z0-9]+) text$', output)
- if m:
- encoding=m.group(1)
- if 'ISO-8859' in encoding:
- encoding="latin-1"
- else:
- encoding="utf-8"
- ############################################################
- # when the -c or --coding switch is used, it takes precedence
- if options.encoding:
- encoding = options.encoding
- csvToOds( pathFileCSV=unicode(pathFileCSV),
- pathFileODS=unicode(pathFileODS),
- delimiter=delimiter, skipinitialspace=skipinitialspace,
- escapechar=escapechar,
- lineterminator=unicode(lineterminator),
- tableName=tableName, quotechar=quotechar,
- encoding=encoding)
- # Local Variables: ***
- # mode: python ***
- # End: ***
|