File indexing completed on 2025-01-19 13:27:34

0001 /*
0002  * This file is part of Office 2007 Filters for Calligra
0003  * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com>
0004  * Copyright (C) 2003 David Faure <faure@kde.org>
0005  * Copyright (C) 2002, 2003, 2004 Nicolas GOUTTE <goutte@kde.org>
0006  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
0007  *
0008  * Contact: Suresh Chande suresh.chande@nokia.com
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Lesser General Public License
0012  * version 2.1 as published by the Free Software Foundation.
0013  *
0014  * This library is distributed in the hope that it will be useful, but
0015  * WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0017  * Lesser General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Lesser General Public
0020  * License along with this library; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0022  * 02110-1301 USA
0023  *
0024  */
0025 
0026 #include "XlsxUtils.h"
0027 #include "XlsxImport.h"
0028 #include "XlsxXmlDocumentReader.h"
0029 #include "XlsxXmlSharedStringsReader.h"
0030 #include "XlsxXmlStylesReader.h"
0031 #include "XlsxXmlCommentsReader.h"
0032 
0033 #include <MsooXmlUtils.h>
0034 #include <MsooXmlSchemas.h>
0035 #include <MsooXmlContentTypes.h>
0036 #include <MsooXmlRelationships.h>
0037 #include "MsooXmlThemesReader.h"
0038 
0039 #include <memory>
0040 
0041 #include <QColor>
0042 #include <QFile>
0043 #include <QFont>
0044 #include <QPen>
0045 #include <QRegExp>
0046 #include <QImage>
0047 
0048 #include <kpluginfactory.h>
0049 
0050 #include <KoEmbeddedDocumentSaver.h>
0051 #include <KoDocumentInfo.h>
0052 #include <KoDocument.h>
0053 #include <KoFilterChain.h>
0054 #include <KoPageLayout.h>
0055 #include <KoXmlWriter.h>
0056 
0057 K_PLUGIN_FACTORY_WITH_JSON(XlsxImportFactory, "calligra_filter_xlsx2ods.json", registerPlugin<XlsxImport>();)
0058 
0059 Q_LOGGING_CATEGORY(lcXlsxImport, "calligra.filter.xlsx2ods")
0060 
0061 enum XlsxDocumentType {
0062     XlsxDocument,
0063     XlsxTemplate,
0064     XlsxMacroDocument
0065 };
0066 
0067 class XlsxImport::Private
0068 {
0069 public:
0070     Private() : type(XlsxDocument), macrosEnabled(false) {
0071     }
0072 
0073     const char* mainDocumentContentType() const
0074     {
0075         if (type == XlsxMacroDocument)
0076             return MSOOXML::ContentTypes::spreadsheetMacroDocument;
0077         if (type == XlsxTemplate)
0078             return MSOOXML::ContentTypes::spreadsheetTemplate;
0079         return MSOOXML::ContentTypes::spreadsheetDocument;
0080     }
0081 
0082     XlsxDocumentType type;
0083     bool macrosEnabled;
0084 };
0085 
0086 XlsxImport::XlsxImport(QObject* parent, const QVariantList &)
0087         : MSOOXML::MsooXmlImport(QLatin1String("spreadsheet"), parent), d(new Private)
0088 {
0089 }
0090 
0091 XlsxImport::~XlsxImport()
0092 {
0093     delete d;
0094 }
0095 
0096 bool XlsxImport::acceptsSourceMimeType(const QByteArray& mime) const
0097 {
0098     qCDebug(lcXlsxImport) << "Entering XLSX Import filter: from " << mime;
0099     if (mime == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
0100         d->type = XlsxDocument;
0101         d->macrosEnabled = false;
0102     }
0103     else if (mime == "application/vnd.openxmlformats-officedocument.spreadsheetml.template") {
0104         d->type = XlsxTemplate;
0105         d->macrosEnabled = false;
0106     }
0107     else if (mime == "application/vnd.ms-excel.sheet.macroEnabled") {
0108         d->type = XlsxMacroDocument;
0109         d->macrosEnabled = true;
0110     }
0111     else if (mime == "application/vnd.ms-excel.sheet.macroEnabled.12") {
0112         d->type = XlsxDocument;
0113         d->macrosEnabled = true;
0114     }
0115     else if (mime == "application/vnd.ms-excel.template.macroEnabled.12") {
0116         d->type = XlsxTemplate;
0117         d->macrosEnabled = true;
0118     }
0119     else {
0120         return false;
0121     }
0122     return true;
0123 }
0124 
0125 bool XlsxImport::acceptsDestinationMimeType(const QByteArray& mime) const
0126 {
0127     qCDebug(lcXlsxImport) << "Entering XLSX Import filter: to " << mime;
0128     return mime == "application/vnd.oasis.opendocument.spreadsheet";
0129 }
0130 
0131 KoFilter::ConversionStatus XlsxImport::parseParts(KoOdfWriters *writers,
0132         MSOOXML::MsooXmlRelationships *relationships, QString& errorMessage)
0133 {
0134     // more here...
0135     // 0. temporary styles
0136 //! @todo create styles in XlsxXmlDocumentReader (XLSX defines styles in workbook.xml)
0137 
0138     writers->mainStyles->insertRawOdfStyles(
0139         KoGenStyles::DocumentStyles,
0140         "    <!-- COPIED -->"
0141         "\n    <style:default-style style:family=\"table-cell\">"
0142         "\n      <style:table-cell-properties />"
0143         "\n      <style:paragraph-properties style:tab-stop-distance=\"1.27cm\"/>"
0144         "\n      <style:text-properties style:font-name=\"Albany AMT\" fo:language=\"en\" fo:country=\"US\" style:font-name-asian=\"Arial\" style:language-asian=\"zxx\" style:country-asian=\"none\" style:font-name-complex=\"Tahoma\" style:language-complex=\"zxx\" style:country-complex=\"none\"/>"
0145         "\n    </style:default-style>"
0146         "\n    <number:number-style style:name=\"N0\">"
0147         "\n      <number:number number:min-integer-digits=\"1\"/>"
0148         "\n    </number:number-style>"
0149         "\n    <number:currency-style style:name=\"N104P0\" style:volatile=\"true\">"
0150         "\n      <number:currency-symbol number:language=\"en\" number:country=\"US\">$</number:currency-symbol>"
0151         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0152         "\n    </number:currency-style>"
0153         "\n    <number:currency-style style:name=\"N104\">"
0154         "\n      <style:text-properties fo:color=\"#ff0000\"/>"
0155         "\n      <number:text>-</number:text>"
0156         "\n      <number:currency-symbol number:language=\"en\" number:country=\"US\">$</number:currency-symbol>"
0157         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0158         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N104P0\"/>"
0159         "\n    </number:currency-style>"
0160         "\n    <number:number-style style:name=\"N5000\" number:language=\"en\" number:country=\"US\">"
0161         "\n      <number:number number:min-integer-digits=\"1\"/>"
0162         "\n    </number:number-style>"
0163         "\n    <number:currency-style style:name=\"N5116P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0164         "\n      <number:currency-symbol/>"
0165         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0166         "\n      <number:text> </number:text>"
0167         "\n    </number:currency-style>"
0168         "\n    <number:currency-style style:name=\"N5116\" number:language=\"en\" number:country=\"US\">"
0169         "\n      <number:text>(</number:text>"
0170         "\n      <number:currency-symbol/>"
0171         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0172         "\n      <number:text>)</number:text>"
0173         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5116P0\"/>"
0174         "\n    </number:currency-style>"
0175         "\n    <number:currency-style style:name=\"N5117P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0176         "\n      <number:currency-symbol/>"
0177         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0178         "\n      <number:text> </number:text>"
0179         "\n    </number:currency-style>"
0180         "\n    <number:currency-style style:name=\"N5117\" number:language=\"en\" number:country=\"US\">"
0181         "\n      <style:text-properties fo:color=\"#ff0000\"/>"
0182         "\n      <number:text>(</number:text>"
0183         "\n      <number:currency-symbol/>"
0184         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0185         "\n      <number:text>)</number:text>"
0186         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5117P0\"/>"
0187         "\n    </number:currency-style>"
0188         "\n    <number:currency-style style:name=\"N5118P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0189         "\n      <number:currency-symbol/>"
0190         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0191         "\n      <number:text> </number:text>"
0192         "\n    </number:currency-style>"
0193         "\n    <number:currency-style style:name=\"N5118\" number:language=\"en\" number:country=\"US\">"
0194         "\n      <number:text>(</number:text>"
0195         "\n      <number:currency-symbol/>"
0196         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0197         "\n      <number:text>)</number:text>"
0198         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5118P0\"/>"
0199         "\n    </number:currency-style>"
0200         "\n    <number:currency-style style:name=\"N5119P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0201         "\n      <number:currency-symbol/>"
0202         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0203         "\n      <number:text> </number:text>"
0204         "\n    </number:currency-style>"
0205         "\n    <number:currency-style style:name=\"N5119\" number:language=\"en\" number:country=\"US\">"
0206         "\n      <style:text-properties fo:color=\"#ff0000\"/>"
0207         "\n      <number:text>(</number:text>"
0208         "\n      <number:currency-symbol/>"
0209         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0210         "\n      <number:text>)</number:text>"
0211         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5119P0\"/>"
0212         "\n    </number:currency-style>"
0213         "\n    <number:date-style style:name=\"N5120\" number:language=\"en\" number:country=\"US\">"
0214         "\n      <number:month/>"
0215         "\n      <number:text>/</number:text>"
0216         "\n      <number:day/>"
0217         "\n      <number:text>/</number:text>"
0218         "\n      <number:year number:style=\"long\"/>"
0219         "\n    </number:date-style>"
0220         "\n    <number:date-style style:name=\"N5121\" number:language=\"en\" number:country=\"US\">"
0221         "\n      <number:day/>"
0222         "\n      <number:text>-</number:text>"
0223         "\n      <number:month number:textual=\"true\"/>"
0224         "\n      <number:text>-</number:text>"
0225         "\n      <number:year/>"
0226         "\n    </number:date-style>"
0227         "\n    <number:date-style style:name=\"N5122\" number:language=\"en\" number:country=\"US\">"
0228         "\n      <number:day/>"
0229         "\n      <number:text>-</number:text>"
0230         "\n      <number:month number:textual=\"true\"/>"
0231         "\n    </number:date-style>"
0232         "\n    <number:date-style style:name=\"N5123\" number:language=\"en\" number:country=\"US\">"
0233         "\n      <number:month number:textual=\"true\"/>"
0234         "\n      <number:text>-</number:text>"
0235         "\n      <number:year/>"
0236         "\n    </number:date-style>"
0237         "\n    <number:time-style style:name=\"N5124\" number:language=\"en\" number:country=\"US\">"
0238         "\n      <number:hours/>"
0239         "\n      <number:text>:</number:text>"
0240         "\n      <number:minutes number:style=\"long\"/>"
0241         "\n      <number:text> </number:text>"
0242         "\n      <number:am-pm/>"
0243         "\n    </number:time-style>"
0244         "\n    <number:time-style style:name=\"N5125\" number:language=\"en\" number:country=\"US\">"
0245         "\n      <number:hours/>"
0246         "\n      <number:text>:</number:text>"
0247         "\n      <number:minutes number:style=\"long\"/>"
0248         "\n      <number:text>:</number:text>"
0249         "\n      <number:seconds number:style=\"long\"/>"
0250         "\n      <number:text> </number:text>"
0251         "\n      <number:am-pm/>"
0252         "\n    </number:time-style>"
0253         "\n    <number:time-style style:name=\"N5126\" number:language=\"en\" number:country=\"US\">"
0254         "\n      <number:hours/>"
0255         "\n      <number:text>:</number:text>"
0256         "\n      <number:minutes number:style=\"long\"/>"
0257         "\n    </number:time-style>"
0258         "\n    <number:time-style style:name=\"N5127\" number:language=\"en\" number:country=\"US\">"
0259         "\n      <number:hours/>"
0260         "\n      <number:text>:</number:text>"
0261         "\n      <number:minutes number:style=\"long\"/>"
0262         "\n      <number:text>:</number:text>"
0263         "\n      <number:seconds number:style=\"long\"/>"
0264         "\n    </number:time-style>"
0265         "\n    <number:date-style style:name=\"N5128\" number:language=\"en\" number:country=\"US\">"
0266         "\n      <number:month/>"
0267         "\n      <number:text>/</number:text>"
0268         "\n      <number:day/>"
0269         "\n      <number:text>/</number:text>"
0270         "\n      <number:year number:style=\"long\"/>"
0271         "\n      <number:text> </number:text>"
0272         "\n      <number:hours/>"
0273         "\n      <number:text>:</number:text>"
0274         "\n      <number:minutes number:style=\"long\"/>"
0275         "\n    </number:date-style>"
0276         "\n    <number:number-style style:name=\"N5129P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0277         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0278         "\n      <number:text> </number:text>"
0279         "\n    </number:number-style>"
0280         "\n    <number:number-style style:name=\"N5129\" number:language=\"en\" number:country=\"US\">"
0281         "\n      <number:text>(</number:text>"
0282         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0283         "\n      <number:text>)</number:text>"
0284         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5129P0\"/>"
0285         "\n    </number:number-style>"
0286         "\n    <number:number-style style:name=\"N5130P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0287         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0288         "\n      <number:text> </number:text>"
0289         "\n    </number:number-style>"
0290         "\n    <number:number-style style:name=\"N5130\" number:language=\"en\" number:country=\"US\">"
0291         "\n      <style:text-properties fo:color=\"#ff0000\"/>"
0292         "\n      <number:text>(</number:text>"
0293         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0294         "\n      <number:text>)</number:text>"
0295         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5130P0\"/>"
0296         "\n    </number:number-style>"
0297         "\n    <number:number-style style:name=\"N5131P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0298         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0299         "\n      <number:text> </number:text>"
0300         "\n    </number:number-style>"
0301         "\n    <number:number-style style:name=\"N5131\" number:language=\"en\" number:country=\"US\">"
0302         "\n      <number:text>(</number:text>"
0303         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0304         "\n      <number:text>)</number:text>"
0305         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5131P0\"/>"
0306         "\n    </number:number-style>"
0307         "\n    <number:number-style style:name=\"N5132P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0308         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0309         "\n      <number:text> </number:text>"
0310         "\n    </number:number-style>"
0311         "\n    <number:number-style style:name=\"N5132\" number:language=\"en\" number:country=\"US\">"
0312         "\n      <style:text-properties fo:color=\"#ff0000\"/>"
0313         "\n      <number:text>(</number:text>"
0314         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0315         "\n      <number:text>)</number:text>"
0316         "\n      <style:map style:condition=\"value()&gt;=0\" style:apply-style-name=\"N5132P0\"/>"
0317         "\n    </number:number-style>"
0318         "\n    <number:number-style style:name=\"N5133P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0319         "\n      <number:text> </number:text>"
0320         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0321         "\n      <number:text> </number:text>"
0322         "\n    </number:number-style>"
0323         "\n    <number:number-style style:name=\"N5133P1\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0324         "\n      <number:text> (</number:text>"
0325         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0326         "\n      <number:text>)</number:text>"
0327         "\n    </number:number-style>"
0328         "\n    <number:number-style style:name=\"N5133P2\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0329         "\n      <number:text> - </number:text>"
0330         "\n    </number:number-style>"
0331         "\n    <number:text-style style:name=\"N5133\" number:language=\"en\" number:country=\"US\">"
0332         "\n      <number:text> </number:text>"
0333         "\n      <number:text-content/>"
0334         "\n      <number:text> </number:text>"
0335         "\n      <style:map style:condition=\"value()&gt;0\" style:apply-style-name=\"N5133P0\"/>"
0336         "\n      <style:map style:condition=\"value()&lt;0\" style:apply-style-name=\"N5133P1\"/>"
0337         "\n      <style:map style:condition=\"value()=0\" style:apply-style-name=\"N5133P2\"/>"
0338         "\n    </number:text-style>"
0339         "\n    <number:currency-style style:name=\"N5134P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0340         "\n      <number:text> </number:text>"
0341         "\n      <number:currency-symbol/>"
0342         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0343         "\n      <number:text> </number:text>"
0344         "\n    </number:currency-style>"
0345         "\n    <number:currency-style style:name=\"N5134P1\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0346         "\n      <number:text> </number:text>"
0347         "\n      <number:currency-symbol/>"
0348         "\n      <number:text>(</number:text>"
0349         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0350         "\n      <number:text>)</number:text>"
0351         "\n    </number:currency-style>"
0352         "\n    <number:currency-style style:name=\"N5134P2\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0353         "\n      <number:text> </number:text>"
0354         "\n      <number:currency-symbol/>"
0355         "\n      <number:text>- </number:text>"
0356         "\n    </number:currency-style>"
0357         "\n    <number:text-style style:name=\"N5134\" number:language=\"en\" number:country=\"US\">"
0358         "\n      <number:text> </number:text>"
0359         "\n      <number:text-content/>"
0360         "\n      <number:text> </number:text>"
0361         "\n      <style:map style:condition=\"value()&gt;0\" style:apply-style-name=\"N5134P0\"/>"
0362         "\n      <style:map style:condition=\"value()&lt;0\" style:apply-style-name=\"N5134P1\"/>"
0363         "\n      <style:map style:condition=\"value()=0\" style:apply-style-name=\"N5134P2\"/>"
0364         "\n    </number:text-style>"
0365         "\n    <number:number-style style:name=\"N5135P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0366         "\n      <number:text> </number:text>"
0367         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0368         "\n      <number:text> </number:text>"
0369         "\n    </number:number-style>"
0370         "\n    <number:number-style style:name=\"N5135P1\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0371         "\n      <number:text> (</number:text>"
0372         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0373         "\n      <number:text>)</number:text>"
0374         "\n    </number:number-style>"
0375         "\n    <number:number-style style:name=\"N5135P2\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0376         "\n      <number:text> -</number:text>"
0377         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"0\"/>"
0378         "\n      <number:text> </number:text>"
0379         "\n    </number:number-style>"
0380         "\n    <number:text-style style:name=\"N5135\" number:language=\"en\" number:country=\"US\">"
0381         "\n      <number:text> </number:text>"
0382         "\n      <number:text-content/>"
0383         "\n      <number:text> </number:text>"
0384         "\n      <style:map style:condition=\"value()&gt;0\" style:apply-style-name=\"N5135P0\"/>"
0385         "\n      <style:map style:condition=\"value()&lt;0\" style:apply-style-name=\"N5135P1\"/>"
0386         "\n      <style:map style:condition=\"value()=0\" style:apply-style-name=\"N5135P2\"/>"
0387         "\n    </number:text-style>"
0388         "\n    <number:currency-style style:name=\"N5136P0\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0389         "\n      <number:text> </number:text>"
0390         "\n      <number:currency-symbol/>"
0391         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0392         "\n      <number:text> </number:text>"
0393         "\n    </number:currency-style>"
0394         "\n    <number:currency-style style:name=\"N5136P1\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0395         "\n      <number:text> </number:text>"
0396         "\n      <number:currency-symbol/>"
0397         "\n      <number:text>(</number:text>"
0398         "\n      <number:number number:decimal-places=\"2\" number:min-integer-digits=\"1\" number:grouping=\"true\"/>"
0399         "\n      <number:text>)</number:text>"
0400         "\n    </number:currency-style>"
0401         "\n    <number:currency-style style:name=\"N5136P2\" style:volatile=\"true\" number:language=\"en\" number:country=\"US\">"
0402         "\n      <number:text> </number:text>"
0403         "\n      <number:currency-symbol/>"
0404         "\n      <number:text>-</number:text>"
0405         "\n      <number:number number:decimal-places=\"0\" number:min-integer-digits=\"0\"/>"
0406         "\n      <number:text> </number:text>"
0407         "\n    </number:currency-style>"
0408         "\n    <number:text-style style:name=\"N5136\" number:language=\"en\" number:country=\"US\">"
0409         "\n      <number:text> </number:text>"
0410         "\n      <number:text-content/>"
0411         "\n      <number:text> </number:text>"
0412         "\n      <style:map style:condition=\"value()&gt;0\" style:apply-style-name=\"N5136P0\"/>"
0413         "\n      <style:map style:condition=\"value()&lt;0\" style:apply-style-name=\"N5136P1\"/>"
0414         "\n      <style:map style:condition=\"value()=0\" style:apply-style-name=\"N5136P2\"/>"
0415         "\n    </number:text-style>"
0416         "\n    <number:time-style style:name=\"N5137\" number:language=\"en\" number:country=\"US\">"
0417         "\n      <number:minutes number:style=\"long\"/>"
0418         "\n      <number:text>:</number:text>"
0419         "\n      <number:seconds number:style=\"long\"/>"
0420         "\n    </number:time-style>"
0421         "\n    <number:time-style style:name=\"N5138\" number:language=\"en\" number:country=\"US\" number:truncate-on-overflow=\"false\">"
0422         "\n      <number:hours/>"
0423         "\n      <number:text>:</number:text>"
0424         "\n      <number:minutes number:style=\"long\"/>"
0425         "\n      <number:text>:</number:text>"
0426         "\n      <number:seconds number:style=\"long\"/>"
0427         "\n    </number:time-style>"
0428         "\n    <number:time-style style:name=\"N5139\" number:language=\"en\" number:country=\"US\">"
0429         "\n      <number:minutes number:style=\"long\"/>"
0430         "\n      <number:text>:</number:text>"
0431         "\n      <number:seconds number:style=\"long\" number:decimal-places=\"1\"/>"
0432         "\n    </number:time-style>"
0433         "\n    <number:number-style style:name=\"N5140\" number:language=\"en\" number:country=\"US\">"
0434         "\n      <number:scientific-number number:decimal-places=\"1\" number:min-integer-digits=\"3\" number:min-exponent-digits=\"1\"/>"
0435         "\n    </number:number-style>"
0436         "\n    <style:style style:name=\"Default\" style:family=\"table-cell\"/>"
0437         "\n    <style:style style:name=\"Result\" style:family=\"table-cell\" style:parent-style-name=\"Default\">"
0438         "\n      <style:text-properties fo:font-style=\"italic\" style:text-underline-style=\"solid\" style:text-underline-width=\"auto\" style:text-underline-color=\"font-color\" fo:font-weight=\"bold\"/>"
0439         "\n    </style:style>"
0440         "\n    <style:style style:name=\"Result2\" style:family=\"table-cell\" style:parent-style-name=\"Result\" style:data-style-name=\"N104\"/>"
0441         "\n    <style:style style:name=\"Heading\" style:family=\"table-cell\" style:parent-style-name=\"Default\">"
0442         "\n      <style:table-cell-properties style:text-align-source=\"fix\" style:repeat-content=\"false\"/>"
0443         "\n      <style:paragraph-properties fo:text-align=\"center\"/>"
0444         "\n      <style:text-properties fo:font-size=\"16pt\" fo:font-style=\"italic\" fo:font-weight=\"bold\"/>"
0445         "\n    </style:style>"
0446         "\n    <style:style style:name=\"Heading1\" style:family=\"table-cell\" style:parent-style-name=\"Heading\">"
0447         "\n      <style:table-cell-properties style:rotation-angle=\"90\"/>"
0448         "\n    </style:style>"
0449         "\n    <style:style style:name=\"Excel_20_Built-in_20_Normal\" style:display-name=\"Excel Built-in Normal\" style:family=\"table-cell\" style:parent-style-name=\"Default\" style:data-style-name=\"N5000\">"
0450         "\n      <style:table-cell-properties style:cell-protect=\"protected\" style:print-content=\"true\" style:diagonal-bl-tr=\"none\" style:diagonal-tl-br=\"none\" style:text-align-source=\"value-type\" style:repeat-content=\"false\" fo:background-color=\"transparent\" fo:wrap-option=\"no-wrap\" fo:border=\"none\" style:direction=\"ltr\" style:rotation-angle=\"0\" style:rotation-align=\"none\" style:shrink-to-fit=\"false\" style:vertical-align=\"bottom\"/>"
0451         "\n      <style:paragraph-properties fo:margin-left=\"0cm\" style:writing-mode=\"page\"/>"
0452         "\n      <style:text-properties fo:color=\"#000000\" style:text-outline=\"false\" style:text-line-through-style=\"none\" style:font-name=\"Calibri\" fo:font-size=\"11pt\" fo:font-style=\"normal\" fo:text-shadow=\"none\" style:text-underline-style=\"none\" fo:font-weight=\"normal\" style:font-size-asian=\"11pt\" style:font-style-asian=\"normal\" style:font-weight-asian=\"normal\" style:font-size-complex=\"11pt\" style:font-style-complex=\"normal\" style:font-weight-complex=\"normal\"/>"
0453         "\n    </style:style>"
0454         "\n    <!-- /COPIED -->"
0455     );
0456 
0457     writers->mainStyles->insertRawOdfStyles(
0458         KoGenStyles::MasterStyles,
0459         "    <!-- COPIED -->"
0460         "\n    <style:master-page style:name=\"Default\" style:page-layout-name=\"pm1\">"
0461         "\n      <style:header>"
0462         "\n        <text:p>"
0463         "\n          <text:sheet-name>" "???" "</text:sheet-name>"
0464         "\n        </text:p>"
0465         "\n      </style:header>"
0466         "\n      <style:header-left style:display=\"false\"/>"
0467         "\n      <style:footer>"
0468         "\n        <text:p>Page <text:page-number>1</text:page-number></text:p>"
0469         "\n      </style:footer>"
0470         "\n      <style:footer-left style:display=\"false\"/>"
0471         "\n    </style:master-page>"
0472         "\n    <style:master-page style:name=\"Report\" style:page-layout-name=\"pm2\">"
0473         "\n      <style:header>"
0474         "\n        <style:region-left>"
0475         "\n          <text:p><text:sheet-name>" "???" "</text:sheet-name> (<text:title>" "???" "</text:title>)</text:p>"
0476         "\n        </style:region-left>"
0477         "\n        <style:region-right>"
0478         "\n          <text:p><text:date style:data-style-name=\"N2\" text:date-value=\"2009-07-18\">07/18/2009</text:date>, <text:time>21:48:12</text:time></text:p>"
0479         "\n        </style:region-right>"
0480         "\n      </style:header>"
0481         "\n      <style:header-left style:display=\"false\"/>"
0482         "\n      <style:footer>"
0483         "\n        <text:p>Page <text:page-number>1</text:page-number> / <text:page-count>99</text:page-count></text:p>"
0484         "\n      </style:footer>"
0485         "\n      <style:footer-left style:display=\"false\"/>"
0486         "\n    </style:master-page>"
0487         "\n    <style:master-page style:name=\"PageStyle_5f_Test_20_sheet_20__5f_1\" style:display-name=\"PageStyle_Test sheet _1\" style:page-layout-name=\"pm3\">"
0488         "\n      <style:header style:display=\"false\"/>"
0489         "\n      <style:header-left style:display=\"false\"/>"
0490         "\n      <style:footer style:display=\"false\"/>"
0491         "\n      <style:footer-left style:display=\"false\"/>"
0492         "\n    </style:master-page>"
0493         "\n    <style:master-page style:name=\"PageStyle_5f_Test_20_sheet_20__5f_2\" style:display-name=\"PageStyle_Test sheet _2\" style:page-layout-name=\"pm4\">"
0494         "\n      <style:header style:display=\"false\"/>"
0495         "\n      <style:header-left style:display=\"false\"/>"
0496         "\n      <style:footer style:display=\"false\"/>"
0497         "\n      <style:footer-left style:display=\"false\"/>"
0498         "\n    </style:master-page>"
0499         "\n    <!-- COPIED -->"
0500     );
0501 
0502     writers->mainStyles->insertRawOdfStyles(
0503         KoGenStyles::StylesXmlAutomaticStyles,
0504         "    <!-- COPIED -->"
0505         "\n    <style:page-layout style:name=\"pm1\">"
0506         "\n      <style:page-layout-properties style:first-page-number=\"continue\" style:writing-mode=\"lr-tb\"/>"
0507         "\n      <style:header-style>"
0508         "\n        <style:header-footer-properties fo:min-height=\"0.751cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-bottom=\"0.25cm\"/>"
0509         "\n      </style:header-style>"
0510         "\n      <style:footer-style>"
0511         "\n        <style:header-footer-properties fo:min-height=\"0.751cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-top=\"0.25cm\"/>"
0512         "\n      </style:footer-style>"
0513         "\n    </style:page-layout>"
0514         "\n    <style:page-layout style:name=\"pm2\">"
0515         "\n      <style:page-layout-properties style:writing-mode=\"lr-tb\"/>"
0516         "\n      <style:header-style>"
0517         "\n        <style:header-footer-properties fo:min-height=\"0.751cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-bottom=\"0.25cm\" fo:border=\"0.088cm solid #000000\" fo:padding=\"0.018cm\" fo:background-color=\"#c0c0c0\">"
0518         "\n          <style:background-image/>"
0519         "\n        </style:header-footer-properties>"
0520         "\n      </style:header-style>"
0521         "\n      <style:footer-style>"
0522         "\n        <style:header-footer-properties fo:min-height=\"0.751cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-top=\"0.25cm\" fo:border=\"0.088cm solid #000000\" fo:padding=\"0.018cm\" fo:background-color=\"#c0c0c0\">"
0523         "\n          <style:background-image/>"
0524         "\n        </style:header-footer-properties>"
0525         "\n      </style:footer-style>"
0526         "\n    </style:page-layout>"
0527         "\n    <style:page-layout style:name=\"pm3\">"
0528         "\n      <style:page-layout-properties fo:page-width=\"21.001cm\" fo:page-height=\"29.7cm\" style:num-format=\"1\" style:print-orientation=\"portrait\" fo:margin-top=\"1.905cm\" fo:margin-bottom=\"1.905cm\" fo:margin-left=\"1.778cm\" fo:margin-right=\"1.778cm\" style:print-page-order=\"ttb\" style:first-page-number=\"continue\" style:scale-to=\"100%\" style:writing-mode=\"lr-tb\" style:print=\"charts drawings objects zero-values\"/>"
0529         "\n      <style:header-style>"
0530         "\n        <style:header-footer-properties fo:min-height=\"0.75cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-bottom=\"0.25cm\"/>"
0531         "\n      </style:header-style>"
0532         "\n      <style:footer-style>"
0533         "\n        <style:header-footer-properties fo:min-height=\"0.75cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-top=\"0.25cm\"/>"
0534         "\n      </style:footer-style>"
0535         "\n    </style:page-layout>"
0536         "\n    <style:page-layout style:name=\"pm4\">"
0537         "\n      <style:page-layout-properties fo:page-width=\"21.59cm\" fo:page-height=\"27.94cm\" style:num-format=\"1\" style:print-orientation=\"portrait\" fo:margin-top=\"1.905cm\" fo:margin-bottom=\"1.905cm\" fo:margin-left=\"1.778cm\" fo:margin-right=\"1.778cm\" style:print-page-order=\"ttb\" style:first-page-number=\"continue\" style:scale-to=\"100%\" style:writing-mode=\"lr-tb\" style:print=\"charts drawings objects zero-values\"/>"
0538         "\n      <style:header-style>"
0539         "\n        <style:header-footer-properties fo:min-height=\"0.75cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-bottom=\"0.25cm\"/>"
0540         "\n      </style:header-style>"
0541         "\n      <style:footer-style>"
0542         "\n        <style:header-footer-properties fo:min-height=\"0.75cm\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\" fo:margin-top=\"0.25cm\"/>"
0543         "\n      </style:footer-style>"
0544         "\n    </style:page-layout>"
0545         "\n    <!-- /COPIED -->"
0546     );
0547 
0548     // Todo, find out whether these are defaults for xlsx or whether they can be read somewhere
0549     writers->body->startElement("table:calculation-settings");
0550     writers->body->addAttribute("table:case-sensitive", "false");
0551     writers->body->addAttribute("table:automatic-find-labels", "false");
0552     writers->body->addAttribute("table:use-regular-expressions", "false");
0553     writers->body->addAttribute("table:use-wildcards", "true");
0554     writers->body->endElement(); // table:calculation-settings
0555 
0556     // 1. parse themes
0557     QList<QByteArray> partNames = this->partNames(d->mainDocumentContentType());
0558 
0559     // following is a workaround till the patch at https://bugs.freedesktop.org/show_bug.cgi?id=30417 is applied
0560     // so we are able to proper handle this case already before using the mimetype.
0561     if (partNames.isEmpty() && d->type != XlsxMacroDocument) {
0562         QList<QByteArray> macroPartNames = this->partNames(MSOOXML::ContentTypes::spreadsheetMacroDocument);
0563         if (macroPartNames.count() == 1 && acceptsSourceMimeType("application/vnd.ms-excel.sheet.macroEnabled")) {
0564             partNames = macroPartNames;
0565         }
0566     }
0567 
0568     if (partNames.count() != 1) {
0569         errorMessage = i18n("Unable to find part for type %1", d->mainDocumentContentType());
0570         return KoFilter::WrongFormat;
0571     }
0572     const QString spreadPathAndFile(partNames.first());
0573     QString spreadPath, spreadFile;
0574     MSOOXML::Utils::splitPathAndFile(spreadPathAndFile, &spreadPath, &spreadFile);
0575 
0576     MSOOXML::DrawingMLTheme themes;
0577     const QString spreadThemePathAndFile(relationships->targetForType(
0578         spreadPath, spreadFile,
0579         QLatin1String(MSOOXML::Schemas::officeDocument::relationships) + "/theme"));
0580     qCDebug(lcXlsxImport) << QLatin1String(MSOOXML::Schemas::officeDocument::relationships) + "/theme";
0581 
0582     QString spreadThemePath, spreadThemeFile;
0583     MSOOXML::Utils::splitPathAndFile(spreadThemePathAndFile, &spreadThemePath, &spreadThemeFile);
0584 
0585     MSOOXML::MsooXmlThemesReader themesReader(writers);
0586     MSOOXML::MsooXmlThemesReaderContext themecontext(themes, relationships, (MSOOXML::MsooXmlImport*)this,
0587         spreadThemePath, spreadThemeFile);
0588 
0589     KoFilter::ConversionStatus status
0590         = loadAndParseDocument(&themesReader, spreadThemePathAndFile, errorMessage, &themecontext);
0591     Q_UNUSED(status);
0592     reportProgress(5);
0593 
0594     // 2. parse styles
0595     XlsxStyles styles;
0596     XlsxXmlStylesReaderContext colorContext(styles, true, this, &themes);
0597     {
0598         // In first round we read color overrides, in 2nd round we can actually use them.
0599         XlsxXmlStylesReader stylesReader(writers);
0600         RETURN_IF_ERROR(loadAndParseDocumentIfExists(
0601                             MSOOXML::ContentTypes::spreadsheetStyles, &stylesReader, writers, errorMessage, &colorContext))
0602         reportProgress(15);
0603         XlsxXmlStylesReaderContext context2(styles, false, this, &themes);
0604         context2.colorIndices = colorContext.colorIndices; // Overriding default colors potentially
0605         RETURN_IF_ERROR(loadAndParseDocumentIfExists(
0606                             MSOOXML::ContentTypes::spreadsheetStyles, &stylesReader, writers, errorMessage, &context2))
0607     }
0608 
0609     reportProgress(30);
0610 
0611     // 3. parse shared strings
0612     QVector<QString> sharedStrings;
0613     {
0614         XlsxXmlSharedStringsReader sharedStringsReader(writers);
0615         XlsxXmlSharedStringsReaderContext context(sharedStrings, &themes, colorContext.colorIndices);
0616         RETURN_IF_ERROR(loadAndParseDocumentIfExists(
0617                             MSOOXML::ContentTypes::spreadsheetSharedStrings, &sharedStringsReader, writers, errorMessage, &context))
0618     }
0619 
0620     reportProgress(35);
0621 
0622     // 4. parse comments
0623     XlsxComments comments;
0624     {
0625         XlsxXmlCommentsReader commentsReader(writers);
0626         XlsxXmlCommentsReaderContext context(comments, &themes, colorContext.colorIndices);
0627         RETURN_IF_ERROR( loadAndParseDocumentFromFileIfExists(
0628 //! @todo only support "xl/comments1.xml" filename for comments?
0629             "xl/comments1.xml", &commentsReader, writers, errorMessage, &context) )
0630     }
0631 
0632     reportProgress(40);
0633 
0634     // 5. parse document
0635     {
0636         XlsxXmlDocumentReaderContext context(*this, &themes, sharedStrings, comments, styles, *relationships, "workbook.xml", "xl");
0637         XlsxXmlDocumentReader documentReader(writers);
0638         RETURN_IF_ERROR(loadAndParseDocument(d->mainDocumentContentType(), &documentReader, writers, errorMessage, &context))
0639     }
0640 
0641     reportProgress(100);
0642 
0643     // more here...
0644     return KoFilter::OK;
0645 }
0646 
0647 #include "XlsxImport.moc"