1 // xlsxcell.cpp
2
3 #include <cmath>
4
5 #include <QtGlobal>
6 #include <QDebug>
7 #include <QDateTime>
8 #include <QDate>
9 #include <QTime>
10
11 #include "xlsxcell.h"
12 #include "xlsxcell_p.h"
13 #include "xlsxformat.h"
14 #include "xlsxformat_p.h"
15 #include "xlsxutility_p.h"
16 #include "xlsxworksheet.h"
17 #include "xlsxworkbook.h"
18
19 QT_BEGIN_NAMESPACE_XLSX
20
CellPrivate(Cell * p)21 CellPrivate::CellPrivate(Cell *p) :
22 q_ptr(p)
23 {
24
25 }
26
CellPrivate(const CellPrivate * const cp)27 CellPrivate::CellPrivate(const CellPrivate * const cp)
28 : parent(cp->parent)
29 , cellType(cp->cellType)
30 , value(cp->value)
31 , formula(cp->formula)
32 , format(cp->format)
33 , richString(cp->richString)
34 , styleNumber(cp->styleNumber)
35 {
36
37 }
38
39 /*!
40 \class Cell
41 \inmodule QtXlsx
42 \brief The Cell class provides a API that is used to handle the worksheet cell.
43
44 */
45
46 /*!
47 \enum Cell::CellType
48 \value BooleanType Boolean type
49 \value NumberType Number type, can be blank or used with forumula
50 \value ErrorType Error type
51 \value SharedStringType Shared string type
52 \value StringType String type, can be used with forumula
53 \value InlineStringType Inline string type
54 */
55
56 /*!
57 * \internal
58 * Created by Worksheet only.
59 */
60 // qint32 styleIndex = (-1)
Cell(const QVariant & data,CellType type,const Format & format,Worksheet * parent,qint32 styleIndex)61 Cell::Cell(const QVariant &data,
62 CellType type,
63 const Format &format,
64 Worksheet *parent,
65 qint32 styleIndex ) :
66 d_ptr(new CellPrivate(this))
67 {
68 d_ptr->value = data;
69 d_ptr->cellType = type;
70 d_ptr->format = format;
71 d_ptr->parent = parent;
72 d_ptr->styleNumber = styleIndex;
73 }
74
75 /*!
76 * \internal
77 */
Cell(const Cell * const cell)78 Cell::Cell(const Cell * const cell):
79 d_ptr(new CellPrivate(cell->d_ptr))
80 {
81 d_ptr->q_ptr = this;
82 }
83
84 /*!
85 * Destroys the Cell and cleans up.
86 */
~Cell()87 Cell::~Cell()
88 {
89 if ( NULL != d_ptr )
90 delete d_ptr;
91 }
92
93 /*!
94 * Return the dataType of this Cell
95 */
cellType() const96 Cell::CellType Cell::cellType() const
97 {
98 Q_D(const Cell);
99
100 return d->cellType;
101 }
102
103 /*!
104 * Return the data content of this Cell
105 */
value() const106 QVariant Cell::value() const
107 {
108 Q_D(const Cell);
109
110 return d->value;
111 }
112
113 /*!
114 * Return the data content of this Cell for reading
115 */
readValue() const116 QVariant Cell::readValue() const
117 {
118 Q_D(const Cell);
119
120 QVariant ret; // return value
121 ret = d->value;
122
123 Format fmt = this->format();
124
125 if (isDateTime())
126 {
127 QVariant vDT = dateTime();
128 if ( vDT.isNull() )
129 {
130 return QVariant();
131 }
132
133 // https://github.com/QtExcel/QXlsx/issues/171
134 // https://www.qt.io/blog/whats-new-in-qmetatype-qvariant
135 #if QT_VERSION >= 0x060000 // Qt 6.0 or over
136 if ( vDT.metaType().id() == QMetaType::QDateTime )
137 {
138 ret = vDT;
139 }
140 else if ( vDT.metaType().id() == QMetaType::QDate )
141 {
142 ret = vDT;
143 }
144 else if ( vDT.metaType().id() == QMetaType::QTime )
145 {
146 ret = vDT;
147 }
148 else
149 {
150 return QVariant();
151 }
152 #else
153 if ( vDT.type() == QVariant::DateTime )
154 {
155 ret = vDT;
156 }
157 else if ( vDT.type() == QVariant::Date )
158 {
159 ret = vDT;
160 }
161 else if ( vDT.type() == QVariant::Time )
162 {
163 ret = vDT;
164 }
165 else
166 {
167 return QVariant();
168 }
169 #endif
170
171 // QDateTime dt = dateTime();
172 // ret = dt;
173
174 // QString strFormat = fmt.numberFormat();
175 // if (!strFormat.isEmpty())
176 // {
177 // // TODO: use number format
178 // }
179
180 // qint32 styleNo = d->styleNumber;
181
182 // if (styleNo == 10)
183 // {
184 // }
185
186 // if (styleNo == 11)
187 // {
188 // QTime timeValue = dt.time(); // only time. (HH:mm:ss)
189 // ret = timeValue;
190 // return ret;
191 // }
192
193 // if (styleNo == 12)
194 // {
195 // }
196
197 // if (styleNo == 13) // (HH:mm:ss)
198 // {
199 // double dValue = d->value.toDouble();
200 // int day = int(dValue); // unit is day.
201 // double deciamlPointValue1 = dValue - double(day);
202
203 // double dHour = deciamlPointValue1 * (double(1.0) / double(24.0));
204 // int hour = int(dHour);
205
206 // double deciamlPointValue2 = deciamlPointValue1 - (double(hour) * (double(1.0) / double(24.0)));
207 // double dMin = deciamlPointValue2 * (double(1.0) / double(60.0));
208 // int min = int(dMin);
209
210 // double deciamlPointValue3 = deciamlPointValue2 - (double(min) * (double(1.0) / double(60.0)));
211 // double dSec = deciamlPointValue3 * (double(1.0) / double(60.0));
212 // int sec = int(dSec);
213
214 // int totalHour = hour + (day * 24);
215
216 // QString strTime;
217 // strTime = QString("%1:%2:%3").arg(totalHour).arg(min).arg(sec);
218 // ret = strTime;
219
220 // return ret;
221 // }
222
223 // return ret;
224 // */
225 }
226
227 if (hasFormula())
228 {
229 QString formulaString = this->formula().formulaText();
230 ret = formulaString;
231 return ret; // return formula string
232 }
233
234 return ret;
235 }
236
237 /*!
238 * Return the style used by this Cell. If no style used, 0 will be returned.
239 */
format() const240 Format Cell::format() const
241 {
242 Q_D(const Cell);
243
244 return d->format;
245 }
246
247 /*!
248 * Returns true if the cell has one formula.
249 */
hasFormula() const250 bool Cell::hasFormula() const
251 {
252 Q_D(const Cell);
253
254 return d->formula.isValid();
255 }
256
257 /*!
258 * Return the formula contents if the dataType is Formula
259 */
formula() const260 CellFormula Cell::formula() const
261 {
262 Q_D(const Cell);
263
264 return d->formula;
265 }
266
267 /*!
268 * Returns whether the value is probably a dateTime or not
269 */
isDateTime() const270 bool Cell::isDateTime() const
271 {
272 Q_D(const Cell);
273
274 Cell::CellType cellType = d->cellType;
275 double dValue = d->value.toDouble(); // number
276 // QString strValue = d->value.toString().toUtf8();
277 bool isValidFormat = d->format.isValid();
278 bool isDateTimeFormat = d->format.isDateTimeFormat(); // datetime format
279
280 // dev67
281 if ( cellType == NumberType ||
282 cellType == DateType ||
283 cellType == CustomType )
284 {
285 if ( dValue >= 0 &&
286 isValidFormat &&
287 isDateTimeFormat )
288 {
289 return true;
290 }
291 }
292
293 return false;
294 }
295
296 /*!
297 * Return the data time value.
298 */
299 /*
300 QDateTime Cell::dateTime() const
301 {
302 Q_D(const Cell);
303
304 if (!isDateTime())
305 return QDateTime();
306
307 return datetimeFromNumber(d->value.toDouble(), d->parent->workbook()->isDate1904());
308 }
309 */
dateTime() const310 QVariant Cell::dateTime() const
311 {
312 Q_D(const Cell);
313
314 if (!isDateTime())
315 {
316 return QVariant();
317 }
318
319 // dev57
320
321 QVariant ret;
322 double dValue = d->value.toDouble();
323 bool isDate1904 = d->parent->workbook()->isDate1904();
324 ret = datetimeFromNumber(dValue, isDate1904);
325 return ret;
326 }
327
328 /*!
329 * Returns whether the cell is probably a rich string or not
330 */
isRichString() const331 bool Cell::isRichString() const
332 {
333 Q_D(const Cell);
334
335 if ( d->cellType != SharedStringType &&
336 d->cellType != InlineStringType &&
337 d->cellType != StringType )
338 {
339 return false;
340 }
341
342 return d->richString.isRichString();
343 }
344
styleNumber() const345 qint32 Cell::styleNumber() const
346 {
347 Q_D(const Cell);
348
349 qint32 ret = d->styleNumber;
350 return ret;
351 }
352
353 QT_END_NAMESPACE_XLSX
354