Browse Source

Add setRow and setColumn

master
Debao Zhang 11 years ago
parent
commit
a6bfe24986
  1. 17
      examples/style/main.cpp
  2. 207
      src/xlsxworksheet.cpp
  3. 41
      src/xlsxworksheet.h

17
examples/style/main.cpp

@ -26,7 +26,22 @@ int main()
sheet->write("C5", "=44+33", format2); sheet->write("C5", "=44+33", format2);
sheet->write("D7", true, format2); sheet->write("D7", true, format2);
QXlsx::Format *format3 = workbook.addFormat();
format3->setFontBold(true);
format3->setFontColor(QColor(Qt::blue));
format3->setFontSize(20);
sheet->write(10, 0, "Hello Row Style");
sheet->write(10, 5, "Blue Color");
sheet->setRow(10, 40, format3);
QXlsx::Format *format4 = workbook.addFormat();
format4->setFontBold(true);
format4->setFontColor(QColor(Qt::magenta));
for (int row=20; row<40; row++)
for (int col=8; col<15; col++)
sheet->write(row, col, row+col);
sheet->setColumn(8, 15, 5.0, format4);
workbook.save(DATA_PATH"TestStyle.xlsx"); workbook.save(DATA_PATH"TestStyle.xlsx");
workbook.save(DATA_PATH"TestStyle.zip");
return 0; return 0;
} }

207
src/xlsxworksheet.cpp

@ -38,6 +38,55 @@
namespace QXlsx { namespace QXlsx {
struct XlsxCellData
{
enum CellDataType {
Blank,
String,
Number,
Formula,
ArrayFormula,
Boolean
};
XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank, Format *format=0) :
value(data), dataType(type), format(format)
{
}
QVariant value;
QString formula;
CellDataType dataType;
Format *format;
};
struct XlsxRowInfo
{
XlsxRowInfo(double height, Format *format, bool hidden) :
height(height), format(format), hidden(hidden)
{
}
double height;
Format *format;
bool hidden;
};
struct XlsxColumnInfo
{
XlsxColumnInfo(int column_min, int column_max, double width, Format *format, bool hidden) :
column_min(column_min), column_max(column_max), width(width), format(format), hidden(hidden)
{
}
int column_min;
int column_max;
double width;
Format *format;
bool hidden;
};
/*! /*!
* \brief Worksheet::Worksheet * \brief Worksheet::Worksheet
* \param name Name of the worksheet * \param name Name of the worksheet
@ -70,6 +119,21 @@ Worksheet::Worksheet(const QString &name, int index, Workbook *parent) :
m_show_zeros = true; m_show_zeros = true;
} }
Worksheet::~Worksheet()
{
typedef QMap<int, XlsxCellData *> RowMap;
foreach (RowMap row, m_cellTable) {
foreach (XlsxCellData *item, row)
delete item;
}
foreach (XlsxRowInfo *row, m_rowsInfo)
delete row;
foreach (XlsxColumnInfo *col, m_colsInfo)
delete col;
}
bool Worksheet::isChartsheet() const bool Worksheet::isChartsheet() const
{ {
return false; return false;
@ -187,7 +251,7 @@ int Worksheet::writeString(int row, int column, const QString &value, Format *fo
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, format); m_cellTable[row][column] = new XlsxCellData(index, XlsxCellData::String, format);
return error; return error;
} }
@ -196,7 +260,7 @@ 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, format); m_cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Number, format);
return 0; return 0;
} }
@ -211,9 +275,9 @@ int Worksheet::writeFormula(int row, int column, const QString &content, Format
if (formula.startsWith("=")) if (formula.startsWith("="))
formula.remove(0,1); formula.remove(0,1);
XlsxCellData data(result, XlsxCellData::Formula, format); XlsxCellData *data = new XlsxCellData(result, XlsxCellData::Formula, format);
data.formula = formula; data->formula = formula;
m_table[row][column] = data; m_cellTable[row][column] = data;
return error; return error;
} }
@ -223,7 +287,7 @@ 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, format); m_cellTable[row][column] = new XlsxCellData(QVariant(), XlsxCellData::Blank, format);
return 0; return 0;
} }
@ -232,7 +296,7 @@ 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, format); m_cellTable[row][column] = new XlsxCellData(value, XlsxCellData::Boolean, format);
return 0; return 0;
} }
@ -304,6 +368,22 @@ void Worksheet::saveToXmlFile(QIODevice *device)
// writer.writeAttribute("x14ac:dyDescent", "0.25"); // writer.writeAttribute("x14ac:dyDescent", "0.25");
writer.writeEndElement();//sheetFormatPr writer.writeEndElement();//sheetFormatPr
writer.writeStartElement("cols");
foreach (XlsxColumnInfo *col_info, m_colsInfo) {
writer.writeStartElement("col");
writer.writeAttribute("min", QString::number(col_info->column_min));
writer.writeAttribute("max", QString::number(col_info->column_max));
writer.writeAttribute("width", QString::number(col_info->width, 'g', 15));
if (col_info->format)
writer.writeAttribute("style", QString::number(col_info->format->xfIndex()));
if (col_info->hidden)
writer.writeAttribute("hidden", "1");
if (col_info->width)
writer.writeAttribute("customWidth", "1");
writer.writeEndElement();//col
}
writer.writeEndElement();//cols
writer.writeStartElement("sheetData"); writer.writeStartElement("sheetData");
if (m_dim_rowmax == INT32_MIN) { if (m_dim_rowmax == INT32_MIN) {
//If the max dimensions are equal to INT32_MIN, then there is no data to write //If the max dimensions are equal to INT32_MIN, then there is no data to write
@ -350,7 +430,7 @@ void Worksheet::writeSheetData(XmlStreamWriter &writer)
{ {
calculateSpans(); calculateSpans();
for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) { for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) {
if (!(m_table.contains(row_num) || m_comments.contains(row_num))) { if (!(m_cellTable.contains(row_num) || m_comments.contains(row_num) || m_rowsInfo.contains(row_num))) {
//Only process rows with cell data / comments / formatting //Only process rows with cell data / comments / formatting
continue; continue;
} }
@ -360,14 +440,30 @@ void Worksheet::writeSheetData(XmlStreamWriter &writer)
if (m_row_spans.contains(span_index)) if (m_row_spans.contains(span_index))
span = m_row_spans[span_index]; span = m_row_spans[span_index];
if (m_table.contains(row_num)) { if (m_cellTable.contains(row_num)) {
writer.writeStartElement("row"); writer.writeStartElement("row");
writer.writeAttribute("r", QString::number(row_num + 1)); writer.writeAttribute("r", QString::number(row_num + 1));
if (!span.isEmpty()) if (!span.isEmpty())
writer.writeAttribute("spans", span); writer.writeAttribute("spans", span);
if (m_rowsInfo.contains(row_num)) {
XlsxRowInfo *rowInfo = m_rowsInfo[row_num];
if (rowInfo->format) {
writer.writeAttribute("s", QString::number(rowInfo->format->xfIndex()));
writer.writeAttribute("customFormat", "1");
}
if (rowInfo->height != 15) {
writer.writeAttribute("ht", QString::number(rowInfo->height));
writer.writeAttribute("customHeight", "1");
}
if (rowInfo->hidden)
writer.writeAttribute("hidden", "1");
}
for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) { for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) {
if (m_table[row_num].contains(col_num)) { if (m_cellTable[row_num].contains(col_num)) {
writeCellData(writer, row_num, col_num, m_table[row_num][col_num]); writeCellData(writer, row_num, col_num, m_cellTable[row_num][col_num]);
} }
} }
writer.writeEndElement(); //row writer.writeEndElement(); //row
@ -376,11 +472,10 @@ void Worksheet::writeSheetData(XmlStreamWriter &writer)
} else { } else {
} }
} }
} }
void Worksheet::writeCellData(XmlStreamWriter &writer, int row, int col, const XlsxCellData &data) void Worksheet::writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell)
{ {
//This is the innermost loop so efficiency is important. //This is the innermost loop so efficiency is important.
QString cell_range = xl_rowcol_to_cell_fast(row, col); QString cell_range = xl_rowcol_to_cell_fast(row, col);
@ -389,28 +484,32 @@ void Worksheet::writeCellData(XmlStreamWriter &writer, int row, int col, const X
writer.writeAttribute("r", cell_range); writer.writeAttribute("r", cell_range);
//Style used by the cell, row or col //Style used by the cell, row or col
if (data.format) if (cell->format)
writer.writeAttribute("s", QString::number(data.format->xfIndex())); writer.writeAttribute("s", QString::number(cell->format->xfIndex()));
else if (m_rowsInfo.contains(row) && m_rowsInfo[row]->format)
if (data.dataType == XlsxCellData::String) { writer.writeAttribute("s", QString::number(m_rowsInfo[row]->format->xfIndex()));
//data.data: Index of the string in sharedStringTable else if (m_colsInfoHelper.contains(col) && m_colsInfoHelper[col]->format)
writer.writeAttribute("s", QString::number(m_colsInfoHelper[col]->format->xfIndex()));
if (cell->dataType == XlsxCellData::String) {
//cell->data: Index of the string in sharedStringTable
writer.writeAttribute("t", "s"); writer.writeAttribute("t", "s");
writer.writeTextElement("v", data.value.toString()); writer.writeTextElement("v", cell->value.toString());
} else if (data.dataType == XlsxCellData::Number){ } else if (cell->dataType == XlsxCellData::Number){
writer.writeTextElement("v", data.value.toString()); writer.writeTextElement("v", cell->value.toString());
} else if (data.dataType == XlsxCellData::Formula) { } else if (cell->dataType == XlsxCellData::Formula) {
bool ok = true; bool ok = true;
data.formula.toDouble(&ok); cell->formula.toDouble(&ok);
if (!ok) //is string if (!ok) //is string
writer.writeAttribute("t", "str"); writer.writeAttribute("t", "str");
writer.writeTextElement("f", data.formula); writer.writeTextElement("f", cell->formula);
writer.writeTextElement("v", data.value.toString()); writer.writeTextElement("v", cell->value.toString());
} else if (data.dataType == XlsxCellData::ArrayFormula) { } else if (cell->dataType == XlsxCellData::ArrayFormula) {
} else if (data.dataType == XlsxCellData::Boolean) { } else if (cell->dataType == XlsxCellData::Boolean) {
writer.writeAttribute("t", "b"); writer.writeAttribute("t", "b");
writer.writeTextElement("v", data.value.toBool() ? "1" : "0"); writer.writeTextElement("v", cell->value.toBool() ? "1" : "0");
} else if (data.dataType == XlsxCellData::Blank) { } else if (cell->dataType == XlsxCellData::Blank) {
//Ok, empty here. //Ok, empty here.
} }
writer.writeEndElement(); //c writer.writeEndElement(); //c
@ -429,9 +528,9 @@ void Worksheet::calculateSpans()
int span_max = INT32_MIN; int span_max = INT32_MIN;
for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) { for (int row_num = m_dim_rowmin; row_num <= m_dim_rowmax; row_num++) {
if (m_table.contains(row_num)) { if (m_cellTable.contains(row_num)) {
for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) { for (int col_num = m_dim_colmin; col_num <= m_dim_colmax; col_num++) {
if (m_table[row_num].contains(col_num)) { if (m_cellTable[row_num].contains(col_num)) {
if (span_max == INT32_MIN) { if (span_max == INT32_MIN) {
span_min = col_num; span_min = col_num;
span_max = col_num; span_max = col_num;
@ -472,4 +571,50 @@ void Worksheet::calculateSpans()
} }
} }
/*
Sets row height and format. Row height measured in point size. If format
equals 0 then format is ignored.
*/
bool Worksheet::setRow(int row, double height, Format *format, bool hidden)
{
int min_col = m_dim_colmax == INT32_MIN ? 0 : m_dim_colmin;
if (checkDimensions(row, min_col))
return false;
if (m_rowsInfo.contains(row)) {
m_rowsInfo[row]->height = height;
m_rowsInfo[row]->format = format;
m_rowsInfo[row]->hidden = hidden;
} else {
m_rowsInfo[row] = new XlsxRowInfo(height, format, hidden);
}
return true;
}
/*
Sets column width and format for all columns from colFirst to colLast. Column
width measured as the number of characters of the maximum digit width of the
numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. If format
equals 0 then format is ignored.
*/
bool Worksheet::setColumn(int colFirst, int colLast, double width, Format *format, bool hidden)
{
bool ignore_row = true;
bool ignore_col = (format || (width && hidden)) ? false : true;
if (checkDimensions(0, colLast, ignore_row, ignore_col))
return false;
if (checkDimensions(0, colFirst, ignore_row, ignore_col))
return false;
XlsxColumnInfo *info = new XlsxColumnInfo(colFirst, colLast, width, format, hidden);
m_colsInfo.append(info);
for (int col=colFirst; col<=colLast; ++col)
m_colsInfoHelper[col] = info;
return true;
}
} //namespace } //namespace

41
src/xlsxworksheet.h

@ -37,27 +37,9 @@ class Workbook;
class XmlStreamWriter; class XmlStreamWriter;
class Format; class Format;
struct XlsxCellData struct XlsxCellData;
{ struct XlsxRowInfo;
enum CellDataType { struct XlsxColumnInfo;
Blank,
String,
Number,
Formula,
ArrayFormula,
Boolean
};
XlsxCellData(const QVariant &data=QVariant(), CellDataType type=Blank, Format *format=0) :
value(data), dataType(type), format(format)
{
}
QVariant value;
QString formula;
CellDataType dataType;
Format *format;
};
class Worksheet : public QObject class Worksheet : public QObject
{ {
@ -71,13 +53,18 @@ public:
int writeBlank(int row, int column, Format *format=0); int writeBlank(int row, int column, Format *format=0);
int writeBool(int row, int column, bool value, Format *format=0); int writeBool(int row, int column, bool value, Format *format=0);
bool setRow(int row, double height, Format* format=0, bool hidden=false);
bool setColumn(int colFirst, int colLast, double width, Format* format=0, bool hidden=false);
void setRightToLeft(bool enable); void setRightToLeft(bool enable);
void setZeroValuesHidden(bool enable); void setZeroValuesHidden(bool enable);
private: private:
friend class Package; friend class Package;
friend class Workbook; friend class Workbook;
explicit Worksheet(const QString &sheetName, int sheetIndex, Workbook *parent=0); Worksheet(const QString &sheetName, int sheetIndex, Workbook *parent=0);
~Worksheet();
virtual bool isChartsheet() const; virtual bool isChartsheet() const;
QString name() const; QString name() const;
int index() const; int index() const;
@ -91,12 +78,16 @@ private:
int checkDimensions(int row, int col, bool ignore_row=false, bool ignore_col=false); int checkDimensions(int row, int col, bool ignore_row=false, bool ignore_col=false);
QString generateDimensionString(); QString generateDimensionString();
void writeSheetData(XmlStreamWriter &writer); void writeSheetData(XmlStreamWriter &writer);
void writeCellData(XmlStreamWriter &writer, int row, int col, const XlsxCellData &data); void writeCellData(XmlStreamWriter &writer, int row, int col, XlsxCellData *cell);
void calculateSpans(); void calculateSpans();
Workbook *m_workbook; Workbook *m_workbook;
QMap<int, QMap<int, XlsxCellData> > m_table; QMap<int, QMap<int, XlsxCellData *> > m_cellTable;
QMap<int, QMap<int, QString> > m_comments; QMap<int, QMap<int, QString> > m_comments;
QMap<int, XlsxRowInfo *> m_rowsInfo;
QList<XlsxColumnInfo *> m_colsInfo;
QMap<int, XlsxColumnInfo *> m_colsInfoHelper;//Not owns the XlsxColumnInfo
int m_xls_rowmax; int m_xls_rowmax;
int m_xls_colmax; int m_xls_colmax;
@ -126,6 +117,4 @@ private:
} //QXlsx } //QXlsx
Q_DECLARE_TYPEINFO(QXlsx::XlsxCellData, Q_MOVABLE_TYPE);
#endif // XLSXWORKSHEET_H #endif // XLSXWORKSHEET_H

Loading…
Cancel
Save