File indexing completed on 2025-03-23 03:32:46
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