[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: koffice/filters/kspread/excel
From: Marijn Kruisselbrink <m.kruisselbrink () student ! tue ! nl>
Date: 2010-08-29 20:55:24
Message-ID: 20100829205524.77008AC895 () svn ! kde ! org
[Download RAW message or body]
SVN commit 1169668 by mkruisselbrink:
add initial limited support for styles in the xls export filter
M +135 -1 export/ExcelExport.cpp
M +3 -0 export/ExcelExport.h
M +3 -3 sidewinder/records.xml
--- trunk/koffice/filters/kspread/excel/export/ExcelExport.cpp #1169667:1169668
@@ -37,6 +37,7 @@
#include <Sheet.h>
#include <Region.h>
#include <RowColumnFormat.h>
+#include <StyleStorage.h>
#include <ValueStorage.h>
#include <kspread_limits.h>
@@ -48,6 +49,16 @@
typedef KGenericFactory<ExcelExport> ExcelExportFactory;
K_EXPORT_COMPONENT_FACTORY(libexcelexport, ExcelExportFactory("kofficefilters"))
+static uint qHash(const QFont& f)
+{
+ return qHash(f.family()) ^ 37 * f.pointSize();
+}
+
+static uint qHash(const QColor& c)
+{
+ return uint(c.rgba());
+}
+
using namespace Swinder;
class ExcelExport::Private
@@ -56,6 +67,11 @@
const KSpread::Doc* inputDoc;
QString outputFile;
XlsRecordOutputStream* out;
+ QHash<KSpread::Style, unsigned> styles;
+ QList<FontRecord> fontRecords;
+
+ void convertStyle(const KSpread::Style& style, XFRecord& xf, QHash<QPair<QFont, \
QColor>, unsigned>& fontMap); + unsigned fontIndex(const QFont& font, const \
QColor& color, QHash<QPair<QFont, QColor>, unsigned>& fontMap); };
ExcelExport::ExcelExport(QObject* parent, const QStringList&)
@@ -138,9 +154,19 @@
o.writeRecord(RefreshAllRecord(0));
o.writeRecord(BookBoolRecord(0));
+ QHash<QPair<QFont, QColor>, unsigned> fonts;
+ fonts[qMakePair(QFont(), QColor())] = 0;
{
FontRecord fnt(0);
fnt.setFontName("Arial");
+ d->fontRecords.append(fnt);
+ }
+ QList<XFRecord> xfs;
+ for (int i = 0; i < d->inputDoc->map()->count(); i++) {
+ collectStyles(d->inputDoc->map()->sheet(i), xfs, fonts);
+ }
+
+ foreach (const FontRecord& fnt, d->fontRecords) {
o.writeRecord(fnt);
}
@@ -160,8 +186,12 @@
o.writeRecord(fr);
}
+ o.writeRecord(XFRecord(0)); // default first record
+ foreach (const XFRecord& xf, xfs) {
+ o.writeRecord(xf);
+ }
// XLS requires 16 XF records for some reason
- for (int i = 0; i < 16; i++) {
+ for (int i = xfs.size()+1; i < 16; i++) {
o.writeRecord(XFRecord(0));
}
@@ -220,6 +250,23 @@
return width / factor * 256;
}
+void ExcelExport::collectStyles(KSpread::Sheet* sheet, QList<XFRecord>& xfRecords, \
QHash<QPair<QFont, QColor>, unsigned>& fontMap) +{
+ QRect area = sheet->cellStorage()->styleStorage()->usedArea();
+ for (int row = area.top(); row <= area.bottom(); row++) {
+ for (int col = area.left(); col <= area.right(); col++){
+ KSpread::Style s = sheet->cellStorage()->style(col, row);
+ unsigned& idx = d->styles[s];
+ if (!idx) {
+ XFRecord xfr(0);
+ d->convertStyle(s, xfr, fontMap);
+ xfRecords.append(xfr);
+ idx = xfRecords.size();
+ }
+ }
+ }
+}
+
void ExcelExport::buildStringTable(KSpread::Sheet* sheet, Swinder::SSTRecord& sst, \
QHash<QString, unsigned>& stringTable) {
unsigned useCount = 0;
@@ -345,11 +392,14 @@
for (int col = first.column(); col <= last.column(); col++) {
KSpread::Cell cell(sheet, col, row);
KSpread::Value val = cell.value();
+ KSpread::Style style = cell.style();
+ unsigned xfi = d->styles[style];
if (cell.isFormula()) {
FormulaRecord fr(0);
fr.setRow(row-1);
fr.setColumn(col-1);
+ fr.setXfIndex(xfi);
if (val.isNumber()) {
fr.setResult(Value((double)numToDouble(val.asFloat())));
} else if (val.isBoolean()) {
@@ -392,18 +442,21 @@
NumberRecord nr(0);
nr.setRow(row-1);
nr.setColumn(col-1);
+ nr.setXfIndex(xfi);
nr.setNumber(cell.value().asFloat());
o.writeRecord(nr);
} else if (val.isString()) {
LabelSSTRecord lr(0);
lr.setRow(row-1);
lr.setColumn(col-1);
+ lr.setXfIndex(xfi);
lr.setSstIndex(sst[cell.value().asString()]);
o.writeRecord(lr);
} else if (val.isBoolean() || val.isError()) {
BoolErrRecord br(0);
br.setRow(row-1);
br.setColumn(col-1);
+ br.setXfIndex(xfi);
if (val.isBoolean()) {
br.setError(false);
br.setValue(val.asBoolean() ? 1 : 0);
@@ -436,6 +489,7 @@
BlankRecord br(0);
br.setRow(row-1);
br.setColumn(col-1);
+ br.setXfIndex(xfi);
o.writeRecord(br);
}
}
@@ -979,3 +1033,83 @@
return codes;
}
+
+void ExcelExport::Private::convertStyle(const KSpread::Style& style, XFRecord& xf, \
QHash<QPair<QFont, QColor>, unsigned>& fontMap) +{
+ unsigned fontIdx = fontIndex(style.font(), style.fontColor(), fontMap);
+ xf.setFontIndex(fontIdx);
+ // TODO: number format
+ switch (style.halign()) {
+ case KSpread::Style::Left:
+ xf.setHorizontalAlignment(XFRecord::Left); break;
+ case KSpread::Style::Center:
+ xf.setHorizontalAlignment(XFRecord::Centered); break;
+ case KSpread::Style::Right:
+ xf.setHorizontalAlignment(XFRecord::Right); break;
+ case KSpread::Style::Justified:
+ xf.setHorizontalAlignment(XFRecord::Justified); break;
+ case KSpread::Style::HAlignUndefined:
+ default:
+ xf.setHorizontalAlignment(XFRecord::General); break;
+ }
+ xf.setTextWrap(style.wrapText());
+ switch (style.valign()) {
+ case KSpread::Style::Top:
+ xf.setVerticalAlignment(XFRecord::Top); break;
+ case KSpread::Style::Middle:
+ xf.setVerticalAlignment(XFRecord::VCentered); break;
+ case KSpread::Style::Bottom:
+ xf.setVerticalAlignment(XFRecord::Bottom); break;
+ case KSpread::Style::VDistributed:
+ xf.setVerticalAlignment(XFRecord::VDistributed); break;
+ case KSpread::Style::VJustified:
+ xf.setVerticalAlignment(XFRecord::VJustified); break;
+ default:
+ xf.setVerticalAlignment(XFRecord::Bottom); break;
+ }
+ if (style.verticalText()) {
+ xf.setRawTextRotation97(255);
+ } else if (style.angle()) {
+ int angle = (style.angle() + 360)% 360;
+ if (angle > 180) angle -= 360;
+ if (angle > 0) xf.setRawTextRotation97(90+angle);
+ else xf.setRawTextRotation97(-angle);
+ }
+ xf.setShrinkToFit(style.shrinkToFit());
+
+ // TODO: borders
+ // TODO: background
+}
+
+unsigned ExcelExport::Private::fontIndex(const QFont& f, const QColor& c, \
QHash<QPair<QFont, QColor>, unsigned>& fontMap) +{
+ unsigned& idx = fontMap[qMakePair(f, c)];
+ if (idx) return idx;
+ FontRecord fr(0);
+ fr.setHeight(f.pointSizeF() * 20);
+ fr.setItalic(f.italic());
+ fr.setStrikeout(f.strikeOut());
+ fr.setCondensed(f.stretch() <= QFont::SemiCondensed);
+ fr.setExtended(f.stretch() >= QFont::SemiExpanded);
+ fr.setFontWeight(qBound(100, (f.weight() - 50) * 12 + 400, 1000));
+ fr.setUnderline(f.underline() ? FontRecord::Single : FontRecord::None);
+ switch (f.styleHint()) {
+ case QFont::SansSerif:
+ fr.setFontFamily(FontRecord::Swiss); break;
+ case QFont::Serif:
+ fr.setFontFamily(FontRecord::Roman); break;
+ case QFont::TypeWriter:
+ fr.setFontFamily(FontRecord::Modern); break;
+ case QFont::Decorative:
+ fr.setFontFamily(FontRecord::Decorative); break;
+ case QFont::AnyStyle:
+ case QFont::System:
+ default:
+ fr.setFontFamily(FontRecord::Unknown); break;
+ }
+ fr.setFontName(f.family());
+ // color
+ idx = fontRecords.size();
+ fontRecords.append(fr);
+ return idx;
+}
--- trunk/koffice/filters/kspread/excel/export/ExcelExport.h #1169667:1169668
@@ -27,6 +27,8 @@
#include <KoFilter.h>
#include <KoStore.h>
+#include <records.h>
+
namespace KSpread {
class Sheet;
class Tokens;
@@ -53,6 +55,7 @@
void convertSheet(KSpread::Sheet* sheet, const QHash<QString, unsigned>& sst);
void buildStringTable(KSpread::Sheet* sheet, Swinder::SSTRecord& sst, \
QHash<QString, unsigned>& stringTable); + void collectStyles(KSpread::Sheet* \
sheet, QList<Swinder::XFRecord>& xfRecords, QHash<QPair<QFont, QColor>, unsigned>& \
fontMap); private:
class Private;
Private* d;
--- trunk/koffice/filters/kspread/excel/sidewinder/records.xml #1169667:1169668
@@ -462,7 +462,7 @@
<field name="reserved0" size="2" />
</if>
<if predicate="version() >= Excel97">
- <field name="rawTextRotation2" type="unsigned" size="8" />
+ <field name="rawTextRotation97" type="unsigned" size="8" />
<field name="indentationLevel" type="unsigned" size="4" />
<field name="shrinkToFit" type="bool" size="1" />
<field name="reserved1" size="1" />
@@ -505,9 +505,9 @@
-->
<computedField name="rotationAngle" ctype="int" value="version() < Excel97
? (rawTextRotation1() == 2 ? 90 : rawTextRotation1() == 3 ? 180 : 0)
- : (rawTextRotation2() == 255 ? 0 : rawTextRotation2())" />
+ : (rawTextRotation97() == 255 ? 0 : rawTextRotation97())" />
<computedField name="stackedLetters" ctype="bool" value="version() < Excel97
- ? rawTextRotation1() == 1 : rawTextRotation2() == 255" />
+ ? rawTextRotation1() == 1 : rawTextRotation97() == 255" />
</record>
<!-- TODO: Formula -->
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic