File indexing completed on 2024-05-26 03:50:48

0001 // xlsxcell.cpp
0002 
0003 #include <cmath>
0004 
0005 #include <QtGlobal>
0006 #include <QDebug>
0007 #include <QDateTime>
0008 #include <QDate>
0009 #include <QTime>
0010 
0011 #include "xlsxcell.h"
0012 #include "xlsxcell_p.h"
0013 #include "xlsxformat.h"
0014 #include "xlsxformat_p.h"
0015 #include "xlsxutility_p.h"
0016 #include "xlsxworksheet.h"
0017 #include "xlsxworkbook.h"
0018 
0019 QT_BEGIN_NAMESPACE_XLSX
0020 
0021 CellPrivate::CellPrivate(Cell *p) :
0022     q_ptr(p)
0023 {
0024 
0025 }
0026 
0027 CellPrivate::CellPrivate(const CellPrivate * const cp)
0028     : parent(cp->parent)
0029     , cellType(cp->cellType)
0030     , value(cp->value)
0031     , formula(cp->formula)
0032     , format(cp->format)
0033     , richString(cp->richString)
0034     , styleNumber(cp->styleNumber)
0035 {
0036 
0037 }
0038 
0039 /*!
0040   \class Cell
0041   \inmodule QtXlsx
0042   \brief The Cell class provides a API that is used to handle the worksheet cell.
0043 
0044 */
0045 
0046 /*!
0047   \enum Cell::CellType
0048   \value BooleanType      Boolean type
0049   \value NumberType       Number type, can be blank or used with forumula
0050   \value ErrorType        Error type
0051   \value SharedStringType Shared string type
0052   \value StringType       String type, can be used with forumula
0053   \value InlineStringType Inline string type
0054   */
0055 
0056 /*!
0057  * \internal
0058  * Created by Worksheet only.
0059  */
0060 // qint32 styleIndex = (-1)
0061 Cell::Cell(const QVariant &data, 
0062     CellType type, 
0063     const Format &format, 
0064     Worksheet *parent,
0065     qint32 styleIndex ) :
0066     d_ptr(new CellPrivate(this))
0067 {
0068     d_ptr->value = data;
0069     d_ptr->cellType = type;
0070     d_ptr->format = format;
0071     d_ptr->parent = parent;
0072     d_ptr->styleNumber = styleIndex; 
0073 }
0074 
0075 /*!
0076  * \internal
0077  */
0078 Cell::Cell(const Cell * const cell):
0079     d_ptr(new CellPrivate(cell->d_ptr))
0080 {
0081     d_ptr->q_ptr = this;
0082 }
0083 
0084 /*!
0085  * Destroys the Cell and cleans up.
0086  */
0087 Cell::~Cell()
0088 {
0089     if ( nullptr != d_ptr )
0090         delete d_ptr;
0091 }
0092 
0093 /*!
0094  * Return the dataType of this Cell
0095  */
0096 Cell::CellType Cell::cellType() const
0097 {
0098     Q_D(const Cell);
0099 
0100     return d->cellType;
0101 }
0102 
0103 /*!
0104  * Return the data content of this Cell
0105  */
0106 QVariant Cell::value() const
0107 {
0108     Q_D(const Cell); 
0109 
0110     return d->value; 
0111 }
0112 
0113 /*!
0114 * Return the data content of this Cell for reading 
0115 */
0116 QVariant Cell::readValue() const
0117 {
0118     Q_D(const Cell);
0119 
0120     QVariant ret; // return value 
0121     ret = d->value;
0122 
0123     Format fmt = this->format();
0124 
0125     if (isDateTime())
0126     {
0127         QVariant vDT = dateTime();
0128         if ( vDT.isNull() )
0129         {
0130             return QVariant();
0131         }
0132 
0133         // https://github.com/QtExcel/QXlsx/issues/171
0134         // https://www.qt.io/blog/whats-new-in-qmetatype-qvariant
0135         #if QT_VERSION >= 0x060000 // Qt 6.0 or over
0136                 if ( vDT.metaType().id() == QMetaType::QDateTime )
0137                 {
0138                     ret = vDT;
0139                 }
0140                 else if ( vDT.metaType().id() == QMetaType::QDate )
0141                 {
0142                     ret = vDT;
0143                 }
0144                 else if ( vDT.metaType().id() == QMetaType::QTime )
0145                 {
0146                     ret = vDT;
0147                 }
0148                 else
0149                 {
0150                     return QVariant();
0151                 }
0152         #else
0153                 if ( vDT.type() == QVariant::DateTime )
0154                 {
0155                     ret = vDT;
0156                 }
0157                 else if ( vDT.type() == QVariant::Date )
0158                 {
0159                     ret = vDT;
0160                 }
0161                 else if ( vDT.type() == QVariant::Time )
0162                 {
0163                     ret = vDT;
0164                 }
0165                 else
0166                 {
0167                     return QVariant();
0168                 }
0169         #endif
0170 
0171         // QDateTime dt = dateTime();
0172         // ret = dt;
0173         
0174         // QString strFormat = fmt.numberFormat();
0175         // if (!strFormat.isEmpty())
0176         // {
0177         //  // TODO: use number format
0178         // }
0179 
0180         // qint32 styleNo = d->styleNumber;
0181 
0182         // if (styleNo == 10)
0183         // {
0184         // }
0185 
0186         // if (styleNo == 11)
0187         // {
0188             // QTime timeValue = dt.time(); // only time. (HH:mm:ss) 
0189             // ret = timeValue;
0190             // return ret;
0191         // }
0192 
0193         // if (styleNo == 12)
0194         // {
0195         // }
0196 
0197         // if (styleNo == 13) // (HH:mm:ss)
0198         // {
0199             // double dValue = d->value.toDouble();
0200             // int day = int(dValue); // unit is day.
0201             // double deciamlPointValue1 = dValue - double(day);
0202 
0203             // double dHour = deciamlPointValue1 * (double(1.0) / double(24.0));
0204             // int hour = int(dHour);
0205 
0206             // double deciamlPointValue2 = deciamlPointValue1 - (double(hour) * (double(1.0) / double(24.0)));
0207             // double dMin = deciamlPointValue2 * (double(1.0) / double(60.0));
0208             // int min = int(dMin);
0209 
0210             // double deciamlPointValue3 = deciamlPointValue2 - (double(min) * (double(1.0) / double(60.0)));
0211             // double dSec = deciamlPointValue3 * (double(1.0) / double(60.0));
0212             // int sec = int(dSec);
0213     
0214             // int totalHour = hour + (day * 24);
0215 
0216             // QString strTime;
0217             // strTime = QString("%1:%2:%3").arg(totalHour).arg(min).arg(sec);
0218             // ret = strTime;
0219 
0220             // return ret;
0221         // }
0222 
0223         // return ret;
0224         // */
0225     }
0226 
0227     if (hasFormula())
0228     {
0229         QString formulaString = this->formula().formulaText();
0230         ret = formulaString;
0231         return ret; // return formula string 
0232     }
0233 
0234     return ret;
0235 }
0236 
0237 /*!
0238  * Return the style used by this Cell. If no style used, 0 will be returned.
0239  */
0240 Format Cell::format() const
0241 {
0242     Q_D(const Cell);
0243 
0244     return d->format;
0245 }
0246 
0247 /*!
0248  * Returns true if the cell has one formula.
0249  */
0250 bool Cell::hasFormula() const
0251 {
0252     Q_D(const Cell);
0253 
0254     return d->formula.isValid();
0255 }
0256 
0257 /*!
0258  * Return the formula contents if the dataType is Formula
0259  */
0260 CellFormula Cell::formula() const
0261 {
0262     Q_D(const Cell);
0263 
0264     return d->formula;
0265 }
0266 
0267 /*!
0268  * Returns whether the value is probably a dateTime or not
0269  */
0270 bool Cell::isDateTime() const
0271 {
0272     Q_D(const Cell);
0273 
0274     Cell::CellType cellType = d->cellType;
0275     double dValue = d->value.toDouble(); // number
0276 //  QString strValue = d->value.toString().toUtf8();
0277     bool isValidFormat = d->format.isValid();
0278     bool isDateTimeFormat = d->format.isDateTimeFormat(); // datetime format
0279 
0280     // dev67
0281     if ( cellType == NumberType ||
0282          cellType == DateType ||
0283          cellType == CustomType )
0284     {
0285         if ( dValue >= 0 &&
0286              isValidFormat &&
0287              isDateTimeFormat )
0288         {
0289             return true;
0290         }
0291     }
0292 
0293     return false;
0294 }
0295 
0296 /*!
0297  * Return the data time value.
0298  */
0299 /*
0300 QDateTime Cell::dateTime() const
0301 {
0302     Q_D(const Cell);
0303 
0304     if (!isDateTime())
0305         return QDateTime();
0306 
0307     return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904());
0308 }
0309 */
0310 QVariant Cell::dateTime() const
0311 {
0312     Q_D(const Cell);
0313 
0314     if (!isDateTime())
0315     {
0316         return QVariant();
0317     }
0318 
0319     // dev57
0320 
0321     QVariant ret;
0322     double dValue = d->value.toDouble();
0323     bool isDate1904 = d->parent->workbook()->isDate1904();
0324     ret = datetimeFromNumber(dValue, isDate1904);
0325     return ret;
0326 }
0327 
0328 /*!
0329  * Returns whether the cell is probably a rich string or not
0330  */
0331 bool Cell::isRichString() const
0332 {
0333     Q_D(const Cell);
0334 
0335     if ( d->cellType != SharedStringType &&
0336             d->cellType != InlineStringType &&
0337             d->cellType != StringType )
0338     {
0339         return false;
0340     }
0341 
0342     return d->richString.isRichString();
0343 }
0344 
0345 qint32 Cell::styleNumber() const 
0346 {
0347     Q_D(const Cell);
0348 
0349     qint32 ret = d->styleNumber;
0350     return ret; 
0351 }
0352 
0353 bool Cell::isDateType(CellType cellType, const Format &format)
0354 {
0355     if ( cellType == NumberType ||
0356          cellType == DateType ||
0357          cellType == CustomType )
0358     {
0359         return format.isValid() && format.isDateTimeFormat();
0360     }
0361     return false;
0362 }
0363 
0364 QT_END_NAMESPACE_XLSX