Browse Source

Add font format support for cell data

master
Debao Zhang 11 years ago
parent
commit
abb991c212
  1. 9
      README.md
  2. 3
      examples/examples.pro
  3. 2
      examples/hello/main.cpp
  4. 32
      examples/style/main.cpp
  5. 5
      examples/style/style.pro
  6. 120
      src/xlsxformat.cpp
  7. 94
      src/xlsxformat.h
  8. 31
      src/xlsxstyles.cpp
  9. 45
      src/xlsxworksheet.cpp
  10. 18
      src/xlsxworksheet.h
  11. 1
      src/zipwriter.cpp

9
README.md

@ -0,0 +1,9 @@
## References
* https://github.com/jmcnamara/XlsxWriter
* http://officeopenxml.com/anatomyofOOXML-xlsx.php
* http://www.libxl.com
* http://closedxml.codeplex.com/
* http://search.cpan.org/~jmcnamara/Excel-Writer-XLSX-0.71/

3
examples/examples.pro

@ -1,3 +1,6 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS = hello SUBDIRS = hello
SUBDIRS += \
style

2
examples/hello/main.cpp

@ -18,6 +18,8 @@ int main()
sheet->write("D7", true); sheet->write("D7", true);
QXlsx::Worksheet *sheet2 = workbook.addWorksheet(); QXlsx::Worksheet *sheet2 = workbook.addWorksheet();
//Rows and columns are zero indexed.
//The first cell in a worksheet, "A1", is (0, 0).
sheet2->write(0, 0, "First"); sheet2->write(0, 0, "First");
sheet2->write(1, 0, "Second"); sheet2->write(1, 0, "Second");
sheet2->write(2, 0, "Third"); sheet2->write(2, 0, "Third");

32
examples/style/main.cpp

@ -0,0 +1,32 @@
#include <QtCore>
#include "xlsxworkbook.h"
#include "xlsxworksheet.h"
#include "xlsxformat.h"
#ifdef Q_OS_MAC
# define DATA_PATH "../../../"
#else
# define DATA_PATH "./"
#endif
int main()
{
QXlsx::Workbook workbook;
QXlsx::Worksheet *sheet = workbook.addWorksheet();
QXlsx::Format *format1 = workbook.addFormat();
format1->setFontColor(QColor(Qt::red));
format1->setFontSize(15);
sheet->write("A1", "Hello Qt!", format1);
sheet->write("B3", 12345, format1);
QXlsx::Format *format2 = workbook.addFormat();
format2->setFontBold(true);
format2->setFontUnderline(QXlsx::Format::FontUnderlineDouble);
sheet->write("C5", "=44+33", format2);
sheet->write("D7", true, format2);
workbook.save(DATA_PATH"TestStyle.xlsx");
workbook.save(DATA_PATH"TestStyle.zip");
return 0;
}

5
examples/style/style.pro

@ -0,0 +1,5 @@
TARGET = style
include(../../src/qtxlsxwriter.pri)
SOURCES += main.cpp

120
src/xlsxformat.cpp

@ -26,24 +26,32 @@
namespace QXlsx { namespace QXlsx {
Format::Format(QObject *parent) : Format::Format()
QObject(parent)
{ {
m_font.bold = false;
m_font.color = QColor(Qt::black);
m_font.italic = false;
m_font.name = "Calibri";
m_font.scirpt = FontScriptNormal;
m_font.size = 11;
m_font.strikeOut = false;
m_font.underline = FontUnderlineNone;
m_font.shadow = false;
m_font.outline = false;
m_font.family = 2;
m_font.scheme = "minor";
m_font.charset = 0;
m_font.condense = 0;
m_font.extend = 0;
m_font.redundant = false;
m_font.index = 0;
m_is_dxf_fomat = false; m_is_dxf_fomat = false;
m_xf_index = 0; m_xf_index = 0;
m_dxf_index = 0; m_dxf_index = 0;
m_num_format_index = 0; m_num_format_index = 0;
m_has_font = false;
m_font_index = 0;
m_font_family = 2;
m_font_scheme = "minor";
m_font.setFamily("Calibri");
m_font.setPointSize(11);
m_theme = 0; m_theme = 0;
m_color_indexed = 0; m_color_indexed = 0;
@ -54,70 +62,110 @@ Format::Format(QObject *parent) :
m_border_index = false; m_border_index = false;
} }
bool Format::isDxfFormat() const int Format::fontSize() const
{ {
return m_is_dxf_fomat; return m_font.size;
} }
void Format::setFont(const QFont &font) void Format::setFontSize(int size)
{ {
m_font = font; m_font.size = size;
} }
void Format::setForegroundColor(const QColor &color) bool Format::fontItalic() const
{ {
m_fg_color = color; return m_font.italic;
} }
void Format::setBackgroundColor(const QColor &color) void Format::setFontItalic(bool italic)
{ {
m_bg_color = color; m_font.italic = italic;
} }
QString Format::fontName() const bool Format::fontStrikeOut() const
{
return m_font.strikeOut;
}
void Format::setFontStricOut(bool stricOut)
{
m_font.strikeOut = stricOut;
}
QColor Format::fontColor() const
{
return m_font.color;
}
void Format::setFontColor(const QColor &color)
{
m_font.color = color;
}
bool Format::fontBold() const
{
return m_font.bold;
}
void Format::setFontBold(bool bold)
{
m_font.bold = bold;
}
Format::FontScript Format::fontScript() const
{
return m_font.scirpt;
}
void Format::setFontScript(FontScript script)
{ {
return m_font.family(); m_font.scirpt = script;
} }
bool Format::bold() const Format::FontUnderline Format::fontUnderline() const
{ {
return m_font.weight() == QFont::Bold; return m_font.underline;
} }
bool Format::italic() const void Format::setFontUnderline(FontUnderline underline)
{ {
return m_font.italic(); m_font.underline = underline;
} }
bool Format::fontOutline() const bool Format::fontOutline() const
{ {
return false; return m_font.outline;
} }
bool Format::fontShadow() const void Format::setFontOutline(bool outline)
{ {
return false; m_font.outline = outline;
} }
bool Format::fontStrikout() const QString Format::fontName() const
{ {
return m_font.strikeOut(); return m_font.name;
} }
bool Format::fontUnderline() const void Format::setFontName(const QString &name)
{ {
return m_font.underline(); m_font.name = name;
} }
QColor Format::fontColor() const bool Format::isDxfFormat() const
{ {
return m_font_color; return m_is_dxf_fomat;
} }
int Format::fontSize() const
void Format::setForegroundColor(const QColor &color)
{ {
return m_font.pointSize(); m_fg_color = color;
} }
void Format::setBackgroundColor(const QColor &color)
{
m_bg_color = color;
}
} // namespace QXlsx } // namespace QXlsx

94
src/xlsxformat.h

@ -25,48 +25,100 @@
#ifndef QXLSX_FORMAT_H #ifndef QXLSX_FORMAT_H
#define QXLSX_FORMAT_H #define QXLSX_FORMAT_H
#include <QObject>
#include <QFont> #include <QFont>
#include <QColor> #include <QColor>
namespace QXlsx { namespace QXlsx {
class Styles; class Styles;
class Worksheet;
class Format : public QObject class Format
{ {
Q_OBJECT
public: public:
void setFont(const QFont &font); enum FontScript
{
FontScriptNormal,
FontScriptSuper,
FontScriptSub
};
enum FontUnderline
{
FontUnderlineNone,
FontUnderlineSingle,
FontUnderlineDouble,
FontUnderlineSingleAccounting,
FontUnderlineDoubleAccounting
};
int fontSize() const;
void setFontSize(int size);
bool fontItalic() const;
void setFontItalic(bool italic);
bool fontStrikeOut() const;
void setFontStricOut(bool);
QColor fontColor() const;
void setFontColor(const QColor &);
bool fontBold() const;
void setFontBold(bool bold);
FontScript fontScript() const;
void setFontScript(FontScript);
FontUnderline fontUnderline() const;
void setFontUnderline(FontUnderline);
bool fontOutline() const;
void setFontOutline(bool outline);
QString fontName() const;
void setFontName(const QString &);
void setForegroundColor(const QColor &color); void setForegroundColor(const QColor &color);
void setBackgroundColor(const QColor &color); void setBackgroundColor(const QColor &color);
private: private:
friend class Styles; friend class Styles;
explicit Format(QObject *parent = 0); friend class Worksheet;
explicit Format();
struct Font
{
int size;
bool italic;
bool strikeOut;
QColor color;
bool bold;
FontScript scirpt;
FontUnderline underline;
bool outline;
bool shadow;
QString name;
int family;
int charset;
QString scheme;
int condense;
int extend;
//helper member
bool redundant; //same with the fonts 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;}
int fontFamily() const{return m_font.family;}
bool fontShadow() const {return m_font.shadow;}
QString fontScheme() const {return m_font.scheme;}
bool isDxfFormat() const; bool isDxfFormat() const;
int xfIndex() const {return m_xf_index;}
void setXfIndex(int index) {m_xf_index = index; m_font.index=index;}
//num //num
int numFormatIndex() const {return m_num_format_index;} int numFormatIndex() const {return m_num_format_index;}
//fonts
bool hasFont() const {return m_has_font;}
int fontIndex() const {return m_font_index;}
QString fontName() const;
bool bold() const;
bool italic() const;
bool fontStrikout() const;
bool fontOutline() const;
bool fontShadow() const;
bool fontUnderline() const;
QColor fontColor() const;
int fontSize() const;
int fontFamily() const{return m_font_family;}
int theme() const {return m_theme;} int theme() const {return m_theme;}
int colorIndexed() const {return m_color_indexed;} int colorIndexed() const {return m_color_indexed;}
QString fontScheme() const {return m_font_scheme;}
void setHasFont(bool has) {m_has_font=has;}
//fills //fills
bool hasFill() const {return m_has_fill;} bool hasFill() const {return m_has_fill;}
@ -86,10 +138,8 @@ private:
bool m_has_font; bool m_has_font;
int m_font_index; int m_font_index;
QFont m_font;
int m_font_family; int m_font_family;
QString m_font_scheme; QString m_font_scheme;
QColor m_font_color;
QColor m_bg_color; QColor m_bg_color;
QColor m_fg_color; QColor m_fg_color;
int m_theme; int m_theme;

31
src/xlsxstyles.cpp

@ -35,17 +35,19 @@ Styles::Styles(QObject *parent) :
{ {
m_fill_count = 2; //Starts from 2 m_fill_count = 2; //Starts from 2
m_borders_count = 1; m_borders_count = 1;
m_font_count = 1; m_font_count = 0;
//Add the default cell format //Add the default cell format
Format *format = addFormat(); Format *format = addFormat();
format->setHasFont(true);
format->setHasBorder(true); format->setHasBorder(true);
} }
Format *Styles::addFormat() Format *Styles::addFormat()
{ {
Format *format = new Format(this); 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;
} }
@ -109,18 +111,33 @@ void Styles::writeFonts(XmlStreamWriter &writer)
foreach (Format *format, m_xf_formats) { foreach (Format *format, m_xf_formats) {
if (format->hasFont()) { if (format->hasFont()) {
writer.writeStartElement("font"); writer.writeStartElement("font");
if (format->bold()) if (format->fontBold())
writer.writeEmptyElement("b"); writer.writeEmptyElement("b");
if (format->italic()) if (format->fontItalic())
writer.writeEmptyElement("i"); writer.writeEmptyElement("i");
if (format->fontStrikout()) if (format->fontStrikeOut())
writer.writeEmptyElement("strike"); writer.writeEmptyElement("strike");
if (format->fontOutline()) if (format->fontOutline())
writer.writeEmptyElement("outline"); writer.writeEmptyElement("outline");
if (format->fontShadow()) if (format->fontShadow())
writer.writeEmptyElement("shadow"); writer.writeEmptyElement("shadow");
if (format->fontUnderline()) //More option if (format->fontUnderline() != Format::FontUnderlineNone) {
writer.writeEmptyElement("u"); writer.writeEmptyElement("u");
if (format->fontUnderline() == Format::FontUnderlineDouble)
writer.writeAttribute("val", "double");
else if (format->fontUnderline() == Format::FontUnderlineSingleAccounting)
writer.writeAttribute("val", "singleAccounting");
else if (format->fontUnderline() == Format::FontUnderlineDoubleAccounting)
writer.writeAttribute("val", "doubleAccounting");
}
if (format->fontScript() != Format::FontScriptNormal) {
writer.writeEmptyElement("vertAligh");
if (format->fontScript() == Format::FontScriptSuper)
writer.writeAttribute("val", "superscript");
else
writer.writeAttribute("val", "subscript");
}
if (!format->isDxfFormat()) { if (!format->isDxfFormat()) {
writer.writeEmptyElement("sz"); writer.writeEmptyElement("sz");
writer.writeAttribute("val", QString::number(format->fontSize())); writer.writeAttribute("val", QString::number(format->fontSize()));

45
src/xlsxworksheet.cpp

@ -24,6 +24,7 @@
****************************************************************************/ ****************************************************************************/
#include "xlsxworksheet.h" #include "xlsxworksheet.h"
#include "xlsxworkbook.h" #include "xlsxworkbook.h"
#include "xlsxformat.h"
#include "xlsxutility_p.h" #include "xlsxutility_p.h"
#include "xlsxsharedstrings_p.h" #include "xlsxsharedstrings_p.h"
#include "xmlstreamwriter_p.h" #include "xmlstreamwriter_p.h"
@ -124,34 +125,34 @@ void Worksheet::setZeroValuesHidden(bool enable)
m_show_zeros = !enable; m_show_zeros = !enable;
} }
int Worksheet::write(int row, int column, const QVariant &value) int Worksheet::write(int row, int column, const QVariant &value, Format *format)
{ {
bool ok; bool ok;
int ret = 0; int ret = 0;
if (value.isNull()) { //blank if (value.isNull()) { //blank
ret = writeBlank(row, column); ret = writeBlank(row, column, format);
} else if (value.type() == QMetaType::Bool) { //Bool } else if (value.type() == QMetaType::Bool) { //Bool
ret = writeBool(row,column, value.toBool()); ret = writeBool(row,column, value.toBool(), format);
} else if (value.toDateTime().isValid()) { //DateTime } else if (value.toDateTime().isValid()) { //DateTime
} else if (value.toDouble(&ok), ok) { //Number } else if (value.toDouble(&ok), ok) { //Number
if (!m_workbook->isStringsToNumbersEnabled() && value.type() == QMetaType::QString) { if (!m_workbook->isStringsToNumbersEnabled() && value.type() == QMetaType::QString) {
//Don't convert string to number if the flag not enabled. //Don't convert string to number if the flag not enabled.
ret = writeString(row, column, value.toString()); ret = writeString(row, column, value.toString(), format);
} else { } else {
ret = writeNumber(row, column, value.toDouble()); ret = writeNumber(row, column, value.toDouble(), format);
} }
} else if (value.type() == QMetaType::QUrl) { //url } else if (value.type() == QMetaType::QUrl) { //url
} else if (value.type() == QMetaType::QString) { //string } else if (value.type() == QMetaType::QString) { //string
QString token = value.toString(); QString token = value.toString();
if (token.startsWith("=")) { if (token.startsWith("=")) {
ret = writeFormula(row, column, token); ret = writeFormula(row, column, token, format);
} else if (token.startsWith("{") && token.endsWith("}")) { } else if (token.startsWith("{") && token.endsWith("}")) {
} else { } else {
ret = writeString(row, column, token); ret = writeString(row, column, token, format);
} }
} else { //Wrong type } else { //Wrong type
@ -162,16 +163,16 @@ int Worksheet::write(int row, int column, const QVariant &value)
} }
//convert the "A1" notation to row/column notation //convert the "A1" notation to row/column notation
int Worksheet::write(const QString row_column, const QVariant &value) int Worksheet::write(const QString row_column, const QVariant &value, Format *format)
{ {
QPoint pos = xl_cell_to_rowcol(row_column); QPoint pos = xl_cell_to_rowcol(row_column);
if (pos == QPoint(-1, -1)) { if (pos == QPoint(-1, -1)) {
return -1; return -1;
} }
return write(pos.x(), pos.y(), value); return write(pos.x(), pos.y(), value, format);
} }
int Worksheet::writeString(int row, int column, const QString &value) int Worksheet::writeString(int row, int column, const QString &value, Format *format)
{ {
int error = 0; int error = 0;
QString content = value; QString content = value;
@ -186,20 +187,20 @@ int Worksheet::writeString(int row, int column, const QString &value)
SharedStrings *sharedStrings = m_workbook->sharedStrings(); SharedStrings *sharedStrings = m_workbook->sharedStrings();
int index = sharedStrings->addSharedString(content); int index = sharedStrings->addSharedString(content);
m_table[row][column] = XlsxCellData(index, XlsxCellData::String); m_table[row][column] = XlsxCellData(index, XlsxCellData::String, format);
return error; return error;
} }
int Worksheet::writeNumber(int row, int column, double value) int Worksheet::writeNumber(int row, int column, double value, Format *format)
{ {
if (checkDimensions(row, column)) if (checkDimensions(row, column))
return -1; return -1;
m_table[row][column] = XlsxCellData(value, XlsxCellData::Number); m_table[row][column] = XlsxCellData(value, XlsxCellData::Number, format);
return 0; return 0;
} }
int Worksheet::writeFormula(int row, int column, const QString &content, double result) int Worksheet::writeFormula(int row, int column, const QString &content, Format *format, double result)
{ {
int error = 0; int error = 0;
QString formula = content; QString formula = content;
@ -210,28 +211,28 @@ int Worksheet::writeFormula(int row, int column, const QString &content, double
if (formula.startsWith("=")) if (formula.startsWith("="))
formula.remove(0,1); formula.remove(0,1);
XlsxCellData data(result, XlsxCellData::Formula); XlsxCellData data(result, XlsxCellData::Formula, format);
data.formula = formula; data.formula = formula;
m_table[row][column] = data; m_table[row][column] = data;
return error; return error;
} }
int Worksheet::writeBlank(int row, int column) int Worksheet::writeBlank(int row, int column, Format *format)
{ {
if (checkDimensions(row, column)) if (checkDimensions(row, column))
return -1; return -1;
m_table[row][column] = XlsxCellData(QVariant(), XlsxCellData::Blank); m_table[row][column] = XlsxCellData(QVariant(), XlsxCellData::Blank, format);
return 0; return 0;
} }
int Worksheet::writeBool(int row, int column, bool value) int Worksheet::writeBool(int row, int column, bool value, Format *format)
{ {
if (checkDimensions(row, column)) if (checkDimensions(row, column))
return -1; return -1;
m_table[row][column] = XlsxCellData(value, XlsxCellData::Boolean); m_table[row][column] = XlsxCellData(value, XlsxCellData::Boolean, format);
return 0; return 0;
} }
@ -386,8 +387,10 @@ void Worksheet::writeCellData(XmlStreamWriter &writer, int row, int col, const X
writer.writeStartElement("c"); writer.writeStartElement("c");
writer.writeAttribute("r", cell_range); writer.writeAttribute("r", cell_range);
//Style used by the cell, row /col
// writer.writeAttribute("s", QString::number("")); //Style used by the cell, row or col
if (data.format)
writer.writeAttribute("s", QString::number(data.format->xfIndex()));
if (data.dataType == XlsxCellData::String) { if (data.dataType == XlsxCellData::String) {
//data.data: Index of the string in sharedStringTable //data.data: Index of the string in sharedStringTable

18
src/xlsxworksheet.h

@ -47,8 +47,8 @@ struct XlsxCellData
ArrayFormula, ArrayFormula,
Boolean Boolean
}; };
XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank) : XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank, Format *format=0) :
value(data), dataType(type), format(0) value(data), dataType(type), format(format)
{ {
} }
@ -63,13 +63,13 @@ class Worksheet : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
int write(const QString row_column, const QVariant &value); int write(const QString row_column, const QVariant &value, Format *format=0);
int write(int row, int column, const QVariant &value); int write(int row, int column, const QVariant &value, Format *format=0);
int writeString(int row, int column, const QString &value); int writeString(int row, int column, const QString &value, Format *format=0);
int writeNumber(int row, int column, double value); int writeNumber(int row, int column, double value, Format *format=0);
int writeFormula(int row, int column, const QString &formula, double result=0); int writeFormula(int row, int column, const QString &formula, Format *format=0, double result=0);
int writeBlank(int row, int column); int writeBlank(int row, int column, Format *format=0);
int writeBool(int row, int column, bool value); int writeBool(int row, int column, bool value, Format *format=0);
void setRightToLeft(bool enable); void setRightToLeft(bool enable);
void setZeroValuesHidden(bool enable); void setZeroValuesHidden(bool enable);

1
src/zipwriter.cpp

@ -47,7 +47,6 @@ void ZipWriter::addFile(const QString &filePath, QIODevice *device)
void ZipWriter::addFile(const QString &filePath, const QByteArray &data) void ZipWriter::addFile(const QString &filePath, const QByteArray &data)
{ {
qDebug()<<filePath<<data.size();
m_writer->addFile(filePath, data); m_writer->addFile(filePath, data);
} }

Loading…
Cancel
Save