diff --git a/examples/style/main.cpp b/examples/style/main.cpp index b8e331a..75bfccc 100644 --- a/examples/style/main.cpp +++ b/examples/style/main.cpp @@ -18,12 +18,14 @@ int main() format1->setFontColor(QColor(Qt::red)); format1->setFontSize(15); format1->setHorizontalAlignment(QXlsx::Format::AlignHCenter); + format1->setBorderStyle(QXlsx::Format::BorderDashDotDot); sheet->write("A1", "Hello Qt!", format1); sheet->write("B3", 12345, format1); QXlsx::Format *format2 = workbook.addFormat(); format2->setFontBold(true); format2->setFontUnderline(QXlsx::Format::FontUnderlineDouble); + format2->setFillPattern(QXlsx::Format::PatternLightUp); sheet->write("C5", "=44+33", format2); sheet->write("D7", true, format2); diff --git a/src/xlsxformat.cpp b/src/xlsxformat.cpp index 5ae89bd..98bec95 100755 --- a/src/xlsxformat.cpp +++ b/src/xlsxformat.cpp @@ -23,11 +23,18 @@ ** ****************************************************************************/ #include "xlsxformat.h" +#include +#include namespace QXlsx { +QList Format::s_xfFormats; +QList Format::s_dxfFormats; + Format::Format() { + m_number.formatIndex = 0; + m_font.bold = false; m_font.color = QColor(Qt::black); m_font.italic = false; @@ -43,8 +50,9 @@ Format::Format() m_font.charset = 0; m_font.condense = 0; m_font.extend = 0; - m_font.redundant = false; - m_font.index = 0; + m_font._dirty = true; + m_font._redundant = false; + m_font._index = -1; m_alignment.alignH = AlignHGeneral; m_alignment.alignV = AlignBottom; @@ -53,20 +61,50 @@ Format::Format() m_alignment.indent = 0; m_alignment.shinkToFit = false; - m_is_dxf_fomat = false; + m_border.left = BorderNone; + m_border.right = BorderNone; + m_border.top = BorderNone; + m_border.bottom = BorderNone; + m_border.diagonal = BorderNone; + m_border.diagonalType = DiagonalBorderNone; + m_border.leftColor = QColor(); + m_border.rightColor = QColor(); + m_border.topColor = QColor(); + m_border.bottomColor = QColor(); + m_border.diagonalColor = QColor(); + m_border._dirty = true; + m_border._redundant = false; + m_border._index = -1; + + m_fill.pattern = PatternNone; + m_fill.bgColor = QColor(); + m_fill.fgColor = QColor(); + m_fill._dirty = true; + m_fill._redundant = false; + m_fill._index = -1; + + m_protection.locked = false; + m_protection.hidden = false; + + m_dirty = true; - m_xf_index = 0; - m_dxf_index = 0; + m_is_dxf_fomat = false; + m_xf_index = -1; + m_dxf_index = -1; - m_num_format_index = 0; m_theme = 0; m_color_indexed = 0; +} - m_has_fill = false; - m_fill_index = 0; +int Format::numberFormat() const +{ + return m_number.formatIndex; +} - m_has_borders = false; - m_border_index = false; +void Format::setNumberFormat(int format) +{ + m_dirty = true; + m_number.formatIndex = format; } int Format::fontSize() const @@ -77,6 +115,7 @@ int Format::fontSize() const void Format::setFontSize(int size) { m_font.size = size; + m_font._dirty = true; } bool Format::fontItalic() const @@ -87,6 +126,7 @@ bool Format::fontItalic() const void Format::setFontItalic(bool italic) { m_font.italic = italic; + m_font._dirty = true; } bool Format::fontStrikeOut() const @@ -94,9 +134,10 @@ bool Format::fontStrikeOut() const return m_font.strikeOut; } -void Format::setFontStricOut(bool stricOut) +void Format::setFontStrikeOut(bool strikeOut) { - m_font.strikeOut = stricOut; + m_font.strikeOut = strikeOut; + m_font._dirty = true; } QColor Format::fontColor() const @@ -107,6 +148,7 @@ QColor Format::fontColor() const void Format::setFontColor(const QColor &color) { m_font.color = color; + m_font._dirty = true; } bool Format::fontBold() const @@ -117,6 +159,7 @@ bool Format::fontBold() const void Format::setFontBold(bool bold) { m_font.bold = bold; + m_font._dirty = true; } Format::FontScript Format::fontScript() const @@ -127,6 +170,7 @@ Format::FontScript Format::fontScript() const void Format::setFontScript(FontScript script) { m_font.scirpt = script; + m_font._dirty = true; } Format::FontUnderline Format::fontUnderline() const @@ -137,6 +181,7 @@ Format::FontUnderline Format::fontUnderline() const void Format::setFontUnderline(FontUnderline underline) { m_font.underline = underline; + m_font._dirty = true; } bool Format::fontOutline() const @@ -147,6 +192,7 @@ bool Format::fontOutline() const void Format::setFontOutline(bool outline) { m_font.outline = outline; + m_font._dirty = true; } QString Format::fontName() const @@ -157,6 +203,27 @@ QString Format::fontName() const void Format::setFontName(const QString &name) { m_font.name = name; + m_font._dirty = true; +} + +/* Internal + */ +QByteArray Format::fontKey() const +{ + if (m_font._dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + stream<(this)->m_font._key = key; + const_cast(this)->m_font._dirty = false; + const_cast(this)->m_dirty = true; //Make sure formatKey() will be re-generated. + } + + return m_font._key; } Format::HorizontalAlignment Format::horizontalAlignment() const @@ -177,6 +244,7 @@ void Format::setHorizontalAlignment(HorizontalAlignment align) } m_alignment.alignH = align; + m_dirty = true; } Format::VerticalAlignment Format::verticalAlignment() const @@ -187,6 +255,7 @@ Format::VerticalAlignment Format::verticalAlignment() const void Format::setVerticalAlignment(VerticalAlignment align) { m_alignment.alignV = align; + m_dirty = true; } bool Format::textWrap() const @@ -200,6 +269,7 @@ void Format::setTextWarp(bool wrap) m_alignment.shinkToFit = false; m_alignment.wrap = wrap; + m_dirty = true; } int Format::rotation() const @@ -210,6 +280,7 @@ int Format::rotation() const void Format::setRotation(int rotation) { m_alignment.rotation = rotation; + m_dirty = true; } int Format::indent() const @@ -226,6 +297,7 @@ void Format::setIndent(int indent) m_alignment.alignH = AlignLeft; } m_alignment.indent = indent; + m_dirty = true; } bool Format::shrinkToFit() const @@ -244,6 +316,7 @@ void Format::setShrinkToFit(bool shink) } m_alignment.shinkToFit = shink; + m_dirty = true; } bool Format::alignmentChanged() const @@ -309,20 +382,303 @@ QString Format::verticalAlignmentString() const return align; } -bool Format::isDxfFormat() const +void Format::setBorderStyle(BorderStyle style) { - return m_is_dxf_fomat; + setLeftBorderStyle(style); + setRightBorderStyle(style); + setBottomBorderStyle(style); + setTopBorderStyle(style); +} + +void Format::setBorderColor(const QColor &color) +{ + setLeftBorderColor(color); + setRightBorderColor(color); + setTopBorderColor(color); + setBottomBorderColor(color); +} + +Format::BorderStyle Format::leftBorderStyle() const +{ + return m_border.left; +} + +void Format::setLeftBorderStyle(BorderStyle style) +{ + m_border.left = style; + m_border._dirty = true; +} + +QColor Format::leftBorderColor() const +{ + return m_border.leftColor; +} + +void Format::setLeftBorderColor(const QColor &color) +{ + m_border.leftColor = color; + m_border._dirty = true; +} + +Format::BorderStyle Format::rightBorderStyle() const +{ + return m_border.right; +} + +void Format::setRightBorderStyle(BorderStyle style) +{ + m_border.right = style; + m_border._dirty = true; +} + +QColor Format::rightBorderColor() const +{ + return m_border.rightColor; +} + +void Format::setRightBorderColor(const QColor &color) +{ + m_border.rightColor = color; + m_border._dirty = true; +} + +Format::BorderStyle Format::topBorderStyle() const +{ + return m_border.top; +} + +void Format::setTopBorderStyle(BorderStyle style) +{ + m_border.top = style; + m_border._dirty = true; +} + +QColor Format::topBorderColor() const +{ + return m_border.topColor; +} + +void Format::setTopBorderColor(const QColor &color) +{ + m_border.topColor = color; + m_border._dirty = true; +} + +Format::BorderStyle Format::bottomBorderStyle() const +{ + return m_border.bottom; +} + +void Format::setBottomBorderStyle(BorderStyle style) +{ + m_border.bottom = style; + m_border._dirty = true; +} + +QColor Format::bottomBorderColor() const +{ + return m_border.bottomColor; +} + +void Format::setBottomBorderColor(const QColor &color) +{ + m_border.bottomColor = color; + m_border._dirty = true; +} + +Format::BorderStyle Format::diagonalBorderStyle() const +{ + return m_border.diagonal; +} + +void Format::setDiagonalBorderStyle(BorderStyle style) +{ + m_border.diagonal = style; + m_border._dirty = true; +} + +Format::DiagonalBorderType Format::diagonalBorderType() const +{ + return m_border.diagonalType; +} + +void Format::setDiagonalBorderType(DiagonalBorderType style) +{ + m_border.diagonalType = style; + m_border._dirty = true; +} + +QColor Format::diagonalBorderColor() const +{ + return m_border.diagonalColor; +} + +void Format::setDiagonalBorderColor(const QColor &color) +{ + m_border.diagonalColor = color; + m_border._dirty = true; +} + + +/* Internal + */ +QByteArray Format::borderKey() const +{ + if (m_border._dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + stream<(this)->m_border._key = key; + const_cast(this)->m_border._dirty = false; + const_cast(this)->m_dirty = true; //Make sure formatKey() will be re-generated. + } + + return m_border._key; +} + +Format::FillPattern Format::fillPattern() const +{ + return m_fill.pattern; +} + +void Format::setFillPattern(FillPattern pattern) +{ + m_fill.pattern = pattern; + m_fill._dirty = true; +} + +QColor Format::patternForegroundColor() const +{ + return m_fill.fgColor; } +void Format::setPatternForegroundColor(const QColor &color) +{ + if (color.isValid() && m_fill.pattern == PatternNone) + m_fill.pattern = PatternSolid; + m_fill.fgColor = color; + m_fill._dirty = true; +} -void Format::setForegroundColor(const QColor &color) +QColor Format::patternBackgroundColor() const { - m_fg_color = color; + return m_fill.bgColor; } -void Format::setBackgroundColor(const QColor &color) +void Format::setPatternBackgroundColor(const QColor &color) { - m_bg_color = color; + if (color.isValid() && m_fill.pattern == PatternNone) + m_fill.pattern = PatternSolid; + m_fill.bgColor = color; + m_fill._dirty = true; +} + +/* Internal + */ +QByteArray Format::fillKey() const +{ + if (m_fill._dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + stream<(this)->m_fill._key = key; + const_cast(this)->m_fill._dirty = false; + const_cast(this)->m_dirty = true; //Make sure formatKey() will be re-generated. + } + + return m_fill._key; +} + +bool Format::hidden() const +{ + return m_protection.hidden; +} + +void Format::setHidden(bool hidden) +{ + m_protection.hidden = hidden; + m_dirty = true; +} + +bool Format::locked() const +{ + return m_protection.locked; +} + +void Format::setLocked(bool locked) +{ + m_protection.locked = locked; + m_dirty = true; +} + +QByteArray Format::formatKey() const +{ + if (m_dirty || m_font._dirty || m_border._dirty || m_fill._dirty) { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + stream<(this)->m_formatKey = key; + const_cast(this)->m_dirty = false; + } + + return m_formatKey; +} + +bool Format::operator ==(const Format &format) const +{ + return this->formatKey() == format.formatKey(); +} + +bool Format::operator !=(const Format &format) const +{ + return this->formatKey() != format.formatKey(); +} + +/* Internal + * + * This function will be called when wirte the cell contents of worksheet to xml files. + * Depending on the order of the Format used instead of the Format created, we assign a + * index to it. + */ +int Format::xfIndex(bool generateIfNotValid) +{ + if (m_xf_index == -1 && generateIfNotValid) { //Generate a valid xf_index for this format + int index = -1; + for (int i=0; i #include +#include +#include namespace QXlsx { @@ -73,12 +75,63 @@ public: AlignVDistributed }; + enum BorderStyle + { + BorderNone, + BorderThin, + BorderMedium, + BorderDashed, + BorderDotted, + BorderThick, + BorderDouble, + BorderHair, + BorderMediumDashed, + BorderDashDot, + BorderMediumDashDot, + BorderDashDotDot, + BorderMediumDashDotDot, + BorderSlantDashDot + }; + + enum DiagonalBorderType + { + DiagonalBorderNone, + DiagonalBorderDown, + DiagonalBorderUp, + DiagnoalBorderBoth + }; + + enum FillPattern + { + PatternNone, + PatternSolid, + PatternMediumGray, + PatternDarkGray, + PatternLightGray, + PatternDarkHorizontal, + PatternDarkVertical, + PatternDarkDown, + PatternDarkUp, + PatternDarkGrid, + PatternDarkTrellis, + PatternLightHorizontal, + PatternLightVertical, + PatternLightDown, + PatternLightUp, + PatternLightTrellis, + PatternGray125, + PatternGray0625 + }; + + int numberFormat() const; + void setNumberFormat(int format); + int fontSize() const; void setFontSize(int size); bool fontItalic() const; void setFontItalic(bool italic); bool fontStrikeOut() const; - void setFontStricOut(bool); + void setFontStrikeOut(bool); QColor fontColor() const; void setFontColor(const QColor &); bool fontBold() const; @@ -105,14 +158,56 @@ public: bool shrinkToFit() const; void setShrinkToFit(bool shink); - void setForegroundColor(const QColor &color); - void setBackgroundColor(const QColor &color); + void setBorderStyle(BorderStyle style); + void setBorderColor(const QColor &color); + BorderStyle leftBorderStyle() const; + void setLeftBorderStyle(BorderStyle style); + QColor leftBorderColor() const; + void setLeftBorderColor(const QColor &color); + BorderStyle rightBorderStyle() const; + void setRightBorderStyle(BorderStyle style); + QColor rightBorderColor() const; + void setRightBorderColor(const QColor &color); + BorderStyle topBorderStyle() const; + void setTopBorderStyle(BorderStyle style); + QColor topBorderColor() const; + void setTopBorderColor(const QColor &color); + BorderStyle bottomBorderStyle() const; + void setBottomBorderStyle(BorderStyle style); + QColor bottomBorderColor() const; + void setBottomBorderColor(const QColor &color); + BorderStyle diagonalBorderStyle() const; + void setDiagonalBorderStyle(BorderStyle style); + DiagonalBorderType diagonalBorderType() const; + void setDiagonalBorderType(DiagonalBorderType style); + QColor diagonalBorderColor() const; + void setDiagonalBorderColor(const QColor &color); + + FillPattern fillPattern() const; + void setFillPattern(FillPattern pattern); + QColor patternForegroundColor() const; + void setPatternForegroundColor(const QColor &color); + QColor patternBackgroundColor() const; + void setPatternBackgroundColor(const QColor &color); + + bool locked() const; + void setLocked(bool locked); + bool hidden() const; + void setHidden(bool hidden); + + bool operator == (const Format &format) const; + bool operator != (const Format &format) const; private: friend class Styles; friend class Worksheet; Format(); + struct NumberData + { + int formatIndex; + } m_number; + struct FontData { int size; @@ -132,13 +227,16 @@ private: int extend; //helper member - bool redundant; //same with the fonts used by some other Formats - int index; //index in the Font list + bool _dirty; //key re-generated is need. + QByteArray _key; + bool _redundant; //same font already used by some other Formats + int _index; //index in the Font list } m_font; - - bool hasFont() const {return !m_font.redundant;} - int fontIndex() const {return m_font.index;} - void setFontIndex(int index) {m_font.index = index;} + bool hasFont() const {return !m_font._redundant;} + void setFontRedundant(bool redundant) {m_font._redundant = redundant;} + int fontIndex() const {return m_font._index;} + void setFontIndex(int index) {m_font._index = index;} + QByteArray fontKey() const; int fontFamily() const{return m_font.family;} bool fontShadow() const {return m_font.shadow;} QString fontScheme() const {return m_font.scheme;} @@ -157,46 +255,75 @@ private: QString horizontalAlignmentString() const; QString verticalAlignmentString() const; - bool isDxfFormat() const; - int xfIndex() const {return m_xf_index;} - void setXfIndex(int index) {m_xf_index = index; m_font.index=index;} + struct BorderData + { + BorderStyle left; + BorderStyle right; + BorderStyle top; + BorderStyle bottom; + BorderStyle diagonal; + QColor leftColor; + QColor rightColor; + QColor topColor; + QColor bottomColor; + QColor diagonalColor; + DiagonalBorderType diagonalType; - //num - int numFormatIndex() const {return m_num_format_index;} + //helper member + bool _dirty; //key re-generated is need. + QByteArray _key; + bool _redundant; //same border already used by some other Formats + int _index; //index in the border list + } m_border; - int theme() const {return m_theme;} - int colorIndexed() const {return m_color_indexed;} + QByteArray borderKey() const; + bool hasBorders() const {return !m_border._redundant;} + void setBorderRedundant(bool redundant) {m_border._redundant = redundant;} + int borderIndex() const {return m_border._index;} + void setBorderIndex(int index) {m_border._index = index;} + + struct FillData { + FillPattern pattern; + QColor bgColor; + QColor fgColor; - //fills - bool hasFill() const {return m_has_fill;} - int fillIndex() const {return m_fill_index;} + //helper member + bool _dirty; //key re-generated is need. + QByteArray _key; + bool _redundant; //same border already used by some other Formats + int _index; //index in the border list + } m_fill; - //borders - bool hasBorders() const {return m_has_borders;} - void setHasBorder(bool has) {m_has_borders=has;} - int borderIndex() const {return m_border_index;} + QByteArray fillKey() const; + bool hasFill() const {return !m_fill._redundant;} + void setFillRedundant(bool redundant) {m_fill._redundant = redundant;} + int fillIndex() const {return m_fill._index;} + void setFillIndex(int index) {m_fill._index = index;} - bool m_is_dxf_fomat; + struct ProtectionData { + bool locked; + bool hidden; + } m_protection; + bool m_dirty; //The key re-generation is need. + QByteArray m_formatKey; + QByteArray formatKey() const; + + static QList s_xfFormats; int m_xf_index; - int m_dxf_index; + int xfIndex(bool generateIfNotValid=true); //Generate index when first called. + void clearExtraInfos(); - int m_num_format_index; + bool m_is_dxf_fomat; + int m_dxf_index; + static QList s_dxfFormats; + bool isDxfFormat() const; - bool m_has_font; - int m_font_index; - int m_font_family; - QString m_font_scheme; - QColor m_bg_color; - QColor m_fg_color; int m_theme; int m_color_indexed; + int theme() const {return m_theme;} + int colorIndexed() const {return m_color_indexed;} - bool m_has_fill; - int m_fill_index; - - bool m_has_borders; - int m_border_index; }; } // namespace QXlsx diff --git a/src/xlsxpackage.cpp b/src/xlsxpackage.cpp index ca31508..36e6d8c 100644 --- a/src/xlsxpackage.cpp +++ b/src/xlsxpackage.cpp @@ -89,6 +89,7 @@ bool Package::createPackage(const QString &packageName) { ZipWriter zipWriter(packageName); + m_workbook->styles()->clearExtraFormatInfo(); //These info will be generated when write the worksheet data. writeWorksheetFiles(zipWriter); // writeChartsheetFiles(zipWriter); writeWorkbookFile(zipWriter); @@ -100,6 +101,7 @@ bool Package::createPackage(const QString &packageName) writeSharedStringsFile(zipWriter); writeDocPropsFiles(zipWriter); writeContentTypesFiles(zipWriter); + m_workbook->styles()->prepareStyles(); writeStylesFiles(zipWriter); writeThemeFile(zipWriter); writeRootRelsFile(zipWriter); diff --git a/src/xlsxstyles.cpp b/src/xlsxstyles.cpp index 5e27d7e..d324f91 100755 --- a/src/xlsxstyles.cpp +++ b/src/xlsxstyles.cpp @@ -26,6 +26,9 @@ #include "xlsxformat.h" #include "xmlstreamwriter_p.h" #include +#include +#include +#include namespace QXlsx { @@ -34,29 +37,106 @@ Styles::Styles(QObject *parent) : QObject(parent) { m_fill_count = 2; //Starts from 2 - m_borders_count = 1; + m_borders_count = 0; m_font_count = 0; +} - //Add the default cell format - Format *format = addFormat(); - format->setHasBorder(true); +Styles::~Styles() +{ + qDeleteAll(m_formats); } Format *Styles::addFormat() { Format *format = new Format(); - format->setXfIndex(m_formats.size()); - m_font_count += 1; m_formats.append(format); return format; } -void Styles::saveToXmlFile(QIODevice *device) +/* + * This function should be called after worksheet written finished, + * which means the order of the Formats used have been known to us. + */ +void Styles::prepareStyles() { - //Todo - m_xf_formats = m_formats; + m_xf_formats = Format::s_xfFormats; + m_dxf_formats = Format::s_dxfFormats; + + //fonts + QMap fontsKeyCache; + foreach (Format *format, m_xf_formats) { + const QByteArray &key = format->fontKey(); + if (fontsKeyCache.contains(key)) { + //Font has already been used. + format->setFontIndex(fontsKeyCache[key]); + format->setFontRedundant(true); + } else { + int index = fontsKeyCache.size(); + fontsKeyCache[key] = index; + format->setFontIndex(index); + format->setFontRedundant(false); + } + } + m_font_count = fontsKeyCache.size(); + //borders + QMap bordersKeyCache; + foreach (Format *format, m_xf_formats) { + const QByteArray &key = format->borderKey(); + if (bordersKeyCache.contains(key)) { + //Border has already been used. + format->setBorderIndex(bordersKeyCache[key]); + format->setBorderRedundant(true); + } else { + int index = bordersKeyCache.size(); + bordersKeyCache[key] = index; + format->setBorderIndex(index); + format->setBorderRedundant(false); + } + } + m_borders_count = bordersKeyCache.size(); + + //fills + QMap fillsKeyCache; + // The user defined fill properties start from 2 since there are 2 + // default fills: patternType="none" and patternType="gray125". + { + QByteArray key; + QDataStream stream(&key, QIODevice::WriteOnly); + stream<fillKey(); + if (fillsKeyCache.contains(key)) { + //Border has already been used. + format->setFillIndex(fillsKeyCache[key]); + format->setFillRedundant(true); + } else { + int index = fillsKeyCache.size(); + fillsKeyCache[key] = index; + format->setFillIndex(index); + format->setFillRedundant(false); + } + } + m_fill_count = fillsKeyCache.size() + 2; +} + +void Styles::clearExtraFormatInfo() +{ + foreach (Format *format, m_formats) + format->clearExtraInfos(); +} + +void Styles::saveToXmlFile(QIODevice *device) +{ XmlStreamWriter writer(device); writer.writeStartDocument("1.0", true); @@ -180,6 +260,7 @@ void Styles::writeFills(XmlStreamWriter &writer) { writer.writeStartElement("fills"); writer.writeAttribute("count", QString::number(m_fill_count)); + //wirte two default fill first writer.writeStartElement("fill"); writer.writeEmptyElement("patternFill"); writer.writeAttribute("patternType", "none"); @@ -190,12 +271,52 @@ void Styles::writeFills(XmlStreamWriter &writer) writer.writeEndElement();//fill foreach (Format *format, m_xf_formats) { if (format->hasFill()) { - //:TODO + writeFill(writer, format); } } writer.writeEndElement(); //fills } +void Styles::writeFill(XmlStreamWriter &writer, Format *format) +{ + static QMap patternStrings; + if (patternStrings.isEmpty()) { + patternStrings[Format::PatternNone] = "none"; + patternStrings[Format::PatternSolid] = "solid"; + patternStrings[Format::PatternMediumGray] = "mediumGray"; + patternStrings[Format::PatternDarkGray] = "darkGray"; + patternStrings[Format::PatternLightGray] = "lightGray"; + patternStrings[Format::PatternDarkHorizontal] = "darkHorizontal"; + patternStrings[Format::PatternDarkVertical] = "darkVertical"; + patternStrings[Format::PatternDarkDown] = "darkDown"; + patternStrings[Format::PatternDarkUp] = "darkUp"; + patternStrings[Format::PatternDarkGrid] = "darkGrid"; + patternStrings[Format::PatternDarkTrellis] = "darkTrellis"; + patternStrings[Format::PatternLightHorizontal] = "lightHorizontal"; + patternStrings[Format::PatternLightVertical] = "lightVertical"; + patternStrings[Format::PatternLightDown] = "lightDown"; + patternStrings[Format::PatternLightUp] = "lightUp"; + patternStrings[Format::PatternLightTrellis] = "lightTrellis"; + patternStrings[Format::PatternGray125] = "gray125"; + patternStrings[Format::PatternGray0625] = "gray0625"; + } + + writer.writeStartElement("fill"); + writer.writeStartElement("patternFill"); + writer.writeAttribute("patternType", patternStrings[format->fillPattern()]); + if (format->patternForegroundColor().isValid()) { + writer.writeEmptyElement("fgColor"); + writer.writeAttribute("rgb", "FF"+format->patternForegroundColor().name().mid(1)); + } + if (format->patternBackgroundColor().isValid()) { + writer.writeEmptyElement("bgColor"); + writer.writeAttribute("rgb", "FF"+format->patternBackgroundColor().name().mid(1)); + } + + writer.writeEndElement();//patternFill + writer.writeEndElement();//fill +} + void Styles::writeBorders(XmlStreamWriter &writer) { writer.writeStartElement("borders"); @@ -203,12 +324,21 @@ void Styles::writeBorders(XmlStreamWriter &writer) foreach (Format *format, m_xf_formats) { if (format->hasBorders()) { writer.writeStartElement("border"); - writer.writeEmptyElement("left"); - writer.writeEmptyElement("right"); - writer.writeEmptyElement("top"); - writer.writeEmptyElement("bottom"); + if (format->diagonalBorderType() == Format::DiagonalBorderUp) { + writer.writeAttribute("diagonalUp", "1"); + } else if (format->diagonalBorderType() == Format::DiagonalBorderDown) { + writer.writeAttribute("diagonalDown", "1"); + } else if (format->DiagnoalBorderBoth) { + writer.writeAttribute("diagonalUp", "1"); + writer.writeAttribute("diagonalDown", "1"); + } + writeSubBorder(writer, "left", format->leftBorderStyle(), format->leftBorderColor()); + writeSubBorder(writer, "right", format->rightBorderStyle(), format->rightBorderColor()); + writeSubBorder(writer, "top", format->topBorderStyle(), format->topBorderColor()); + writeSubBorder(writer, "bottom", format->bottomBorderStyle(), format->bottomBorderColor()); + if (!format->isDxfFormat()) { - writer.writeEmptyElement("diagonal"); + writeSubBorder(writer, "diagonal", format->diagonalBorderStyle(), format->diagonalBorderColor()); } writer.writeEndElement();//border } @@ -216,12 +346,47 @@ void Styles::writeBorders(XmlStreamWriter &writer) writer.writeEndElement();//borders } +void Styles::writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color) +{ + if (style == Format::BorderNone) { + writer.writeEmptyElement(type); + return; + } + + static QMap stylesString; + if (stylesString.isEmpty()) { + stylesString[Format::BorderNone] = "none"; + stylesString[Format::BorderThin] = "thin"; + stylesString[Format::BorderMedium] = "medium"; + stylesString[Format::BorderDashed] = "dashed"; + stylesString[Format::BorderDotted] = "dotted"; + stylesString[Format::BorderThick] = "thick"; + stylesString[Format::BorderDouble] = "double"; + stylesString[Format::BorderHair] = "hair"; + stylesString[Format::BorderMediumDashed] = "mediumDashed"; + stylesString[Format::BorderDashDot] = "dashDot"; + stylesString[Format::BorderMediumDashDot] = "mediumDashDot"; + stylesString[Format::BorderDashDotDot] = "dashDotDot"; + stylesString[Format::BorderMediumDashDotDot] = "mediumDashDotDot"; + stylesString[Format::BorderSlantDashDot] = "slantDashDot"; + } + + writer.writeStartElement(type); + writer.writeAttribute("style", stylesString[style]); + writer.writeEmptyElement("color"); + if (color.isValid()) + writer.writeAttribute("rgb", "FF"+color.name().mid(1)); //remove # + else + writer.writeAttribute("auto", "1"); + writer.writeEndElement();//type +} + void Styles::writeCellXfs(XmlStreamWriter &writer) { writer.writeStartElement("cellXfs"); writer.writeAttribute("count", QString::number(m_xf_formats.size())); foreach (Format *format, m_xf_formats) { - int num_fmt_id = format->numFormatIndex(); + int num_fmt_id = format->numberFormat(); int font_id = format->fontIndex(); int fill_id = format->fillIndex(); int border_id = format->borderIndex(); @@ -232,12 +397,14 @@ void Styles::writeCellXfs(XmlStreamWriter &writer) writer.writeAttribute("fillId", QString::number(fill_id)); writer.writeAttribute("borderId", QString::number(border_id)); writer.writeAttribute("xfId", QString::number(xf_id)); - if (format->numFormatIndex() > 0) + if (format->numberFormat() > 0) writer.writeAttribute("applyNumberFormat", "1"); if (format->fontIndex() > 0) writer.writeAttribute("applyFont", "1"); - if (format->fillIndex() > 0) + if (format->borderIndex() > 0) writer.writeAttribute("applyBorder", "1"); + if (format->fillIndex() > 0) + writer.writeAttribute("applyFill", "1"); if (format->alignmentChanged()) writer.writeAttribute("applyAlignment", "1"); diff --git a/src/xlsxstyles_p.h b/src/xlsxstyles_p.h index 4642509..47dd95f 100755 --- a/src/xlsxstyles_p.h +++ b/src/xlsxstyles_p.h @@ -38,18 +38,22 @@ class Styles : public QObject { public: explicit Styles(QObject *parent=0); + ~Styles(); Format *addFormat(); + void prepareStyles(); + void clearExtraFormatInfo(); void saveToXmlFile(QIODevice *device); private: void writeFonts(XmlStreamWriter &writer); void writeFills(XmlStreamWriter &writer); + void writeFill(XmlStreamWriter &writer, Format *format); void writeBorders(XmlStreamWriter &writer); + void writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color); void writeCellXfs(XmlStreamWriter &writer); void writeDxfs(XmlStreamWriter &writer); - QList m_formats; QList m_xf_formats; QList m_dxf_formats;