Browse Source

Add Fill & Border Style control for cell

master
Debao Zhang 11 years ago
parent
commit
3d47093e38
  1. 2
      examples/style/main.cpp
  2. 392
      src/xlsxformat.cpp
  3. 201
      src/xlsxformat.h
  4. 2
      src/xlsxpackage.cpp
  5. 203
      src/xlsxstyles.cpp
  6. 6
      src/xlsxstyles_p.h

2
examples/style/main.cpp

@ -18,12 +18,14 @@ int main()
format1->setFontColor(QColor(Qt::red)); format1->setFontColor(QColor(Qt::red));
format1->setFontSize(15); format1->setFontSize(15);
format1->setHorizontalAlignment(QXlsx::Format::AlignHCenter); format1->setHorizontalAlignment(QXlsx::Format::AlignHCenter);
format1->setBorderStyle(QXlsx::Format::BorderDashDotDot);
sheet->write("A1", "Hello Qt!", format1); sheet->write("A1", "Hello Qt!", format1);
sheet->write("B3", 12345, format1); sheet->write("B3", 12345, format1);
QXlsx::Format *format2 = workbook.addFormat(); QXlsx::Format *format2 = workbook.addFormat();
format2->setFontBold(true); format2->setFontBold(true);
format2->setFontUnderline(QXlsx::Format::FontUnderlineDouble); format2->setFontUnderline(QXlsx::Format::FontUnderlineDouble);
format2->setFillPattern(QXlsx::Format::PatternLightUp);
sheet->write("C5", "=44+33", format2); sheet->write("C5", "=44+33", format2);
sheet->write("D7", true, format2); sheet->write("D7", true, format2);

392
src/xlsxformat.cpp

@ -23,11 +23,18 @@
** **
****************************************************************************/ ****************************************************************************/
#include "xlsxformat.h" #include "xlsxformat.h"
#include <QDataStream>
#include <QDebug>
namespace QXlsx { namespace QXlsx {
QList<Format *> Format::s_xfFormats;
QList<Format *> Format::s_dxfFormats;
Format::Format() Format::Format()
{ {
m_number.formatIndex = 0;
m_font.bold = false; m_font.bold = false;
m_font.color = QColor(Qt::black); m_font.color = QColor(Qt::black);
m_font.italic = false; m_font.italic = false;
@ -43,8 +50,9 @@ Format::Format()
m_font.charset = 0; m_font.charset = 0;
m_font.condense = 0; m_font.condense = 0;
m_font.extend = 0; m_font.extend = 0;
m_font.redundant = false; m_font._dirty = true;
m_font.index = 0; m_font._redundant = false;
m_font._index = -1;
m_alignment.alignH = AlignHGeneral; m_alignment.alignH = AlignHGeneral;
m_alignment.alignV = AlignBottom; m_alignment.alignV = AlignBottom;
@ -53,20 +61,50 @@ Format::Format()
m_alignment.indent = 0; m_alignment.indent = 0;
m_alignment.shinkToFit = false; 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_is_dxf_fomat = false;
m_dxf_index = 0; m_xf_index = -1;
m_dxf_index = -1;
m_num_format_index = 0;
m_theme = 0; m_theme = 0;
m_color_indexed = 0; m_color_indexed = 0;
}
m_has_fill = false; int Format::numberFormat() const
m_fill_index = 0; {
return m_number.formatIndex;
}
m_has_borders = false; void Format::setNumberFormat(int format)
m_border_index = false; {
m_dirty = true;
m_number.formatIndex = format;
} }
int Format::fontSize() const int Format::fontSize() const
@ -77,6 +115,7 @@ int Format::fontSize() const
void Format::setFontSize(int size) void Format::setFontSize(int size)
{ {
m_font.size = size; m_font.size = size;
m_font._dirty = true;
} }
bool Format::fontItalic() const bool Format::fontItalic() const
@ -87,6 +126,7 @@ bool Format::fontItalic() const
void Format::setFontItalic(bool italic) void Format::setFontItalic(bool italic)
{ {
m_font.italic = italic; m_font.italic = italic;
m_font._dirty = true;
} }
bool Format::fontStrikeOut() const bool Format::fontStrikeOut() const
@ -94,9 +134,10 @@ bool Format::fontStrikeOut() const
return m_font.strikeOut; 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 QColor Format::fontColor() const
@ -107,6 +148,7 @@ QColor Format::fontColor() const
void Format::setFontColor(const QColor &color) void Format::setFontColor(const QColor &color)
{ {
m_font.color = color; m_font.color = color;
m_font._dirty = true;
} }
bool Format::fontBold() const bool Format::fontBold() const
@ -117,6 +159,7 @@ bool Format::fontBold() const
void Format::setFontBold(bool bold) void Format::setFontBold(bool bold)
{ {
m_font.bold = bold; m_font.bold = bold;
m_font._dirty = true;
} }
Format::FontScript Format::fontScript() const Format::FontScript Format::fontScript() const
@ -127,6 +170,7 @@ Format::FontScript Format::fontScript() const
void Format::setFontScript(FontScript script) void Format::setFontScript(FontScript script)
{ {
m_font.scirpt = script; m_font.scirpt = script;
m_font._dirty = true;
} }
Format::FontUnderline Format::fontUnderline() const Format::FontUnderline Format::fontUnderline() const
@ -137,6 +181,7 @@ Format::FontUnderline Format::fontUnderline() const
void Format::setFontUnderline(FontUnderline underline) void Format::setFontUnderline(FontUnderline underline)
{ {
m_font.underline = underline; m_font.underline = underline;
m_font._dirty = true;
} }
bool Format::fontOutline() const bool Format::fontOutline() const
@ -147,6 +192,7 @@ bool Format::fontOutline() const
void Format::setFontOutline(bool outline) void Format::setFontOutline(bool outline)
{ {
m_font.outline = outline; m_font.outline = outline;
m_font._dirty = true;
} }
QString Format::fontName() const QString Format::fontName() const
@ -157,6 +203,27 @@ QString Format::fontName() const
void Format::setFontName(const QString &name) void Format::setFontName(const QString &name)
{ {
m_font.name = 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<<m_font.bold<<m_font.charset<<m_font.color<<m_font.condense
<<m_font.extend<<m_font.family<<m_font.italic<<m_font.name
<<m_font.outline<<m_font.scheme<<m_font.scirpt<<m_font.shadow
<<m_font.size<<m_font.strikeOut<<m_font.underline;
const_cast<Format*>(this)->m_font._key = key;
const_cast<Format*>(this)->m_font._dirty = false;
const_cast<Format*>(this)->m_dirty = true; //Make sure formatKey() will be re-generated.
}
return m_font._key;
} }
Format::HorizontalAlignment Format::horizontalAlignment() const Format::HorizontalAlignment Format::horizontalAlignment() const
@ -177,6 +244,7 @@ void Format::setHorizontalAlignment(HorizontalAlignment align)
} }
m_alignment.alignH = align; m_alignment.alignH = align;
m_dirty = true;
} }
Format::VerticalAlignment Format::verticalAlignment() const Format::VerticalAlignment Format::verticalAlignment() const
@ -187,6 +255,7 @@ Format::VerticalAlignment Format::verticalAlignment() const
void Format::setVerticalAlignment(VerticalAlignment align) void Format::setVerticalAlignment(VerticalAlignment align)
{ {
m_alignment.alignV = align; m_alignment.alignV = align;
m_dirty = true;
} }
bool Format::textWrap() const bool Format::textWrap() const
@ -200,6 +269,7 @@ void Format::setTextWarp(bool wrap)
m_alignment.shinkToFit = false; m_alignment.shinkToFit = false;
m_alignment.wrap = wrap; m_alignment.wrap = wrap;
m_dirty = true;
} }
int Format::rotation() const int Format::rotation() const
@ -210,6 +280,7 @@ int Format::rotation() const
void Format::setRotation(int rotation) void Format::setRotation(int rotation)
{ {
m_alignment.rotation = rotation; m_alignment.rotation = rotation;
m_dirty = true;
} }
int Format::indent() const int Format::indent() const
@ -226,6 +297,7 @@ void Format::setIndent(int indent)
m_alignment.alignH = AlignLeft; m_alignment.alignH = AlignLeft;
} }
m_alignment.indent = indent; m_alignment.indent = indent;
m_dirty = true;
} }
bool Format::shrinkToFit() const bool Format::shrinkToFit() const
@ -244,6 +316,7 @@ void Format::setShrinkToFit(bool shink)
} }
m_alignment.shinkToFit = shink; m_alignment.shinkToFit = shink;
m_dirty = true;
} }
bool Format::alignmentChanged() const bool Format::alignmentChanged() const
@ -309,20 +382,303 @@ QString Format::verticalAlignmentString() const
return align; 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<<m_border.bottom<<m_border.bottomColor
<<m_border.diagonal<<m_border.diagonalColor<<m_border.diagonalType
<<m_border.left<<m_border.leftColor
<<m_border.right<<m_border.rightColor
<<m_border.top<<m_border.topColor;
const_cast<Format*>(this)->m_border._key = key;
const_cast<Format*>(this)->m_border._dirty = false;
const_cast<Format*>(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<<m_fill.bgColor<<m_fill.fgColor<<m_fill.pattern;
const_cast<Format*>(this)->m_fill._key = key;
const_cast<Format*>(this)->m_fill._dirty = false;
const_cast<Format*>(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<<fontKey()<<borderKey()<<fillKey()
<<m_number.formatIndex
<<m_alignment.alignH<<m_alignment.alignV<<m_alignment.indent
<<m_alignment.rotation<<m_alignment.shinkToFit<<m_alignment.wrap
<<m_protection.hidden<<m_protection.locked;
const_cast<Format*>(this)->m_formatKey = key;
const_cast<Format*>(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<s_xfFormats.size(); ++i) {
if (*s_xfFormats[i] == *this) {
index = i;
break;
}
}
if (index != -1) {
m_xf_index = index;
} else {
m_xf_index = s_xfFormats.size();
s_xfFormats.append(this);
}
}
return m_xf_index;
}
void Format::clearExtraInfos()
{
m_xf_index = -1;
m_dxf_index = -1;
s_xfFormats.clear();
s_dxfFormats.clear();
}
bool Format::isDxfFormat() const
{
return m_is_dxf_fomat;
} }
} // namespace QXlsx } // namespace QXlsx

201
src/xlsxformat.h

@ -27,6 +27,8 @@
#include <QFont> #include <QFont>
#include <QColor> #include <QColor>
#include <QByteArray>
#include <QList>
namespace QXlsx { namespace QXlsx {
@ -73,12 +75,63 @@ public:
AlignVDistributed 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; int fontSize() const;
void setFontSize(int size); void setFontSize(int size);
bool fontItalic() const; bool fontItalic() const;
void setFontItalic(bool italic); void setFontItalic(bool italic);
bool fontStrikeOut() const; bool fontStrikeOut() const;
void setFontStricOut(bool); void setFontStrikeOut(bool);
QColor fontColor() const; QColor fontColor() const;
void setFontColor(const QColor &); void setFontColor(const QColor &);
bool fontBold() const; bool fontBold() const;
@ -105,14 +158,56 @@ public:
bool shrinkToFit() const; bool shrinkToFit() const;
void setShrinkToFit(bool shink); void setShrinkToFit(bool shink);
void setForegroundColor(const QColor &color); void setBorderStyle(BorderStyle style);
void setBackgroundColor(const QColor &color); 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: private:
friend class Styles; friend class Styles;
friend class Worksheet; friend class Worksheet;
Format(); Format();
struct NumberData
{
int formatIndex;
} m_number;
struct FontData struct FontData
{ {
int size; int size;
@ -132,13 +227,16 @@ private:
int extend; int extend;
//helper member //helper member
bool redundant; //same with the fonts used by some other Formats bool _dirty; //key re-generated is need.
int index; //index in the Font list QByteArray _key;
bool _redundant; //same font already used by some other Formats
int _index; //index in the Font list
} m_font; } m_font;
bool hasFont() const {return !m_font._redundant;}
bool hasFont() const {return !m_font.redundant;} void setFontRedundant(bool redundant) {m_font._redundant = redundant;}
int fontIndex() const {return m_font.index;} int fontIndex() const {return m_font._index;}
void setFontIndex(int index) {m_font.index = index;} void setFontIndex(int index) {m_font._index = index;}
QByteArray fontKey() const;
int fontFamily() const{return m_font.family;} int fontFamily() const{return m_font.family;}
bool fontShadow() const {return m_font.shadow;} bool fontShadow() const {return m_font.shadow;}
QString fontScheme() const {return m_font.scheme;} QString fontScheme() const {return m_font.scheme;}
@ -157,46 +255,75 @@ private:
QString horizontalAlignmentString() const; QString horizontalAlignmentString() const;
QString verticalAlignmentString() const; QString verticalAlignmentString() const;
bool isDxfFormat() const; struct BorderData
int xfIndex() const {return m_xf_index;} {
void setXfIndex(int index) {m_xf_index = index; m_font.index=index;} BorderStyle left;
BorderStyle right;
BorderStyle top;
BorderStyle bottom;
BorderStyle diagonal;
QColor leftColor;
QColor rightColor;
QColor topColor;
QColor bottomColor;
QColor diagonalColor;
DiagonalBorderType diagonalType;
//num //helper member
int numFormatIndex() const {return m_num_format_index;} 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;} QByteArray borderKey() const;
int colorIndexed() const {return m_color_indexed;} 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 //helper member
bool hasFill() const {return m_has_fill;} bool _dirty; //key re-generated is need.
int fillIndex() const {return m_fill_index;} QByteArray _key;
bool _redundant; //same border already used by some other Formats
int _index; //index in the border list
} m_fill;
//borders QByteArray fillKey() const;
bool hasBorders() const {return m_has_borders;} bool hasFill() const {return !m_fill._redundant;}
void setHasBorder(bool has) {m_has_borders=has;} void setFillRedundant(bool redundant) {m_fill._redundant = redundant;}
int borderIndex() const {return m_border_index;} 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<Format *> s_xfFormats;
int m_xf_index; 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<Format *> 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_theme;
int m_color_indexed; 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 } // namespace QXlsx

2
src/xlsxpackage.cpp

@ -89,6 +89,7 @@ bool Package::createPackage(const QString &packageName)
{ {
ZipWriter zipWriter(packageName); ZipWriter zipWriter(packageName);
m_workbook->styles()->clearExtraFormatInfo(); //These info will be generated when write the worksheet data.
writeWorksheetFiles(zipWriter); writeWorksheetFiles(zipWriter);
// writeChartsheetFiles(zipWriter); // writeChartsheetFiles(zipWriter);
writeWorkbookFile(zipWriter); writeWorkbookFile(zipWriter);
@ -100,6 +101,7 @@ bool Package::createPackage(const QString &packageName)
writeSharedStringsFile(zipWriter); writeSharedStringsFile(zipWriter);
writeDocPropsFiles(zipWriter); writeDocPropsFiles(zipWriter);
writeContentTypesFiles(zipWriter); writeContentTypesFiles(zipWriter);
m_workbook->styles()->prepareStyles();
writeStylesFiles(zipWriter); writeStylesFiles(zipWriter);
writeThemeFile(zipWriter); writeThemeFile(zipWriter);
writeRootRelsFile(zipWriter); writeRootRelsFile(zipWriter);

203
src/xlsxstyles.cpp

@ -26,6 +26,9 @@
#include "xlsxformat.h" #include "xlsxformat.h"
#include "xmlstreamwriter_p.h" #include "xmlstreamwriter_p.h"
#include <QFile> #include <QFile>
#include <QMap>
#include <QDataStream>
#include <QDebug>
namespace QXlsx { namespace QXlsx {
@ -34,29 +37,106 @@ Styles::Styles(QObject *parent) :
QObject(parent) QObject(parent)
{ {
m_fill_count = 2; //Starts from 2 m_fill_count = 2; //Starts from 2
m_borders_count = 1; m_borders_count = 0;
m_font_count = 0; m_font_count = 0;
}
//Add the default cell format Styles::~Styles()
Format *format = addFormat(); {
format->setHasBorder(true); qDeleteAll(m_formats);
} }
Format *Styles::addFormat() Format *Styles::addFormat()
{ {
Format *format = new Format(); Format *format = new Format();
format->setXfIndex(m_formats.size());
m_font_count += 1;
m_formats.append(format); m_formats.append(format);
return 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 = Format::s_xfFormats;
m_xf_formats = m_formats; m_dxf_formats = Format::s_dxfFormats;
//fonts
QMap<QByteArray, int> 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<QByteArray, int> 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<QByteArray, int> 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<<QColor()<<QColor()<<Format::PatternNone;
fillsKeyCache[key] = 0;
}
{
QByteArray key;
QDataStream stream(&key, QIODevice::WriteOnly);
stream<<QColor()<<QColor()<<Format::PatternGray125;
fillsKeyCache[key] = 1;
}
foreach (Format *format, m_xf_formats) {
const QByteArray &key = format->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); XmlStreamWriter writer(device);
writer.writeStartDocument("1.0", true); writer.writeStartDocument("1.0", true);
@ -180,6 +260,7 @@ void Styles::writeFills(XmlStreamWriter &writer)
{ {
writer.writeStartElement("fills"); writer.writeStartElement("fills");
writer.writeAttribute("count", QString::number(m_fill_count)); writer.writeAttribute("count", QString::number(m_fill_count));
//wirte two default fill first
writer.writeStartElement("fill"); writer.writeStartElement("fill");
writer.writeEmptyElement("patternFill"); writer.writeEmptyElement("patternFill");
writer.writeAttribute("patternType", "none"); writer.writeAttribute("patternType", "none");
@ -190,12 +271,52 @@ void Styles::writeFills(XmlStreamWriter &writer)
writer.writeEndElement();//fill writer.writeEndElement();//fill
foreach (Format *format, m_xf_formats) { foreach (Format *format, m_xf_formats) {
if (format->hasFill()) { if (format->hasFill()) {
//:TODO writeFill(writer, format);
} }
} }
writer.writeEndElement(); //fills writer.writeEndElement(); //fills
} }
void Styles::writeFill(XmlStreamWriter &writer, Format *format)
{
static QMap<int, QString> 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) void Styles::writeBorders(XmlStreamWriter &writer)
{ {
writer.writeStartElement("borders"); writer.writeStartElement("borders");
@ -203,12 +324,21 @@ void Styles::writeBorders(XmlStreamWriter &writer)
foreach (Format *format, m_xf_formats) { foreach (Format *format, m_xf_formats) {
if (format->hasBorders()) { if (format->hasBorders()) {
writer.writeStartElement("border"); writer.writeStartElement("border");
writer.writeEmptyElement("left"); if (format->diagonalBorderType() == Format::DiagonalBorderUp) {
writer.writeEmptyElement("right"); writer.writeAttribute("diagonalUp", "1");
writer.writeEmptyElement("top"); } else if (format->diagonalBorderType() == Format::DiagonalBorderDown) {
writer.writeEmptyElement("bottom"); 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()) { if (!format->isDxfFormat()) {
writer.writeEmptyElement("diagonal"); writeSubBorder(writer, "diagonal", format->diagonalBorderStyle(), format->diagonalBorderColor());
} }
writer.writeEndElement();//border writer.writeEndElement();//border
} }
@ -216,12 +346,47 @@ void Styles::writeBorders(XmlStreamWriter &writer)
writer.writeEndElement();//borders 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<int, QString> 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) void Styles::writeCellXfs(XmlStreamWriter &writer)
{ {
writer.writeStartElement("cellXfs"); writer.writeStartElement("cellXfs");
writer.writeAttribute("count", QString::number(m_xf_formats.size())); writer.writeAttribute("count", QString::number(m_xf_formats.size()));
foreach (Format *format, m_xf_formats) { foreach (Format *format, m_xf_formats) {
int num_fmt_id = format->numFormatIndex(); int num_fmt_id = format->numberFormat();
int font_id = format->fontIndex(); int font_id = format->fontIndex();
int fill_id = format->fillIndex(); int fill_id = format->fillIndex();
int border_id = format->borderIndex(); int border_id = format->borderIndex();
@ -232,12 +397,14 @@ void Styles::writeCellXfs(XmlStreamWriter &writer)
writer.writeAttribute("fillId", QString::number(fill_id)); writer.writeAttribute("fillId", QString::number(fill_id));
writer.writeAttribute("borderId", QString::number(border_id)); writer.writeAttribute("borderId", QString::number(border_id));
writer.writeAttribute("xfId", QString::number(xf_id)); writer.writeAttribute("xfId", QString::number(xf_id));
if (format->numFormatIndex() > 0) if (format->numberFormat() > 0)
writer.writeAttribute("applyNumberFormat", "1"); writer.writeAttribute("applyNumberFormat", "1");
if (format->fontIndex() > 0) if (format->fontIndex() > 0)
writer.writeAttribute("applyFont", "1"); writer.writeAttribute("applyFont", "1");
if (format->fillIndex() > 0) if (format->borderIndex() > 0)
writer.writeAttribute("applyBorder", "1"); writer.writeAttribute("applyBorder", "1");
if (format->fillIndex() > 0)
writer.writeAttribute("applyFill", "1");
if (format->alignmentChanged()) if (format->alignmentChanged())
writer.writeAttribute("applyAlignment", "1"); writer.writeAttribute("applyAlignment", "1");

6
src/xlsxstyles_p.h

@ -38,18 +38,22 @@ class Styles : public QObject
{ {
public: public:
explicit Styles(QObject *parent=0); explicit Styles(QObject *parent=0);
~Styles();
Format *addFormat(); Format *addFormat();
void prepareStyles();
void clearExtraFormatInfo();
void saveToXmlFile(QIODevice *device); void saveToXmlFile(QIODevice *device);
private: private:
void writeFonts(XmlStreamWriter &writer); void writeFonts(XmlStreamWriter &writer);
void writeFills(XmlStreamWriter &writer); void writeFills(XmlStreamWriter &writer);
void writeFill(XmlStreamWriter &writer, Format *format);
void writeBorders(XmlStreamWriter &writer); void writeBorders(XmlStreamWriter &writer);
void writeSubBorder(XmlStreamWriter &writer, const QString &type, int style, const QColor &color);
void writeCellXfs(XmlStreamWriter &writer); void writeCellXfs(XmlStreamWriter &writer);
void writeDxfs(XmlStreamWriter &writer); void writeDxfs(XmlStreamWriter &writer);
QList<Format *> m_formats; QList<Format *> m_formats;
QList<Format *> m_xf_formats; QList<Format *> m_xf_formats;
QList<Format *> m_dxf_formats; QList<Format *> m_dxf_formats;

Loading…
Cancel
Save