andre@1: /**************************************************************************** andre@1: ** Copyright (c) 2013-2014 Debao Zhang andre@1: ** All right reserved. andre@1: ** andre@1: ** Permission is hereby granted, free of charge, to any person obtaining andre@1: ** a copy of this software and associated documentation files (the andre@1: ** "Software"), to deal in the Software without restriction, including andre@1: ** without limitation the rights to use, copy, modify, merge, publish, andre@1: ** distribute, sublicense, and/or sell copies of the Software, and to andre@1: ** permit persons to whom the Software is furnished to do so, subject to andre@1: ** the following conditions: andre@1: ** andre@1: ** The above copyright notice and this permission notice shall be andre@1: ** included in all copies or substantial portions of the Software. andre@1: ** andre@1: ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, andre@1: ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF andre@1: ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND andre@1: ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE andre@1: ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION andre@1: ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION andre@1: ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. andre@1: ** andre@1: ****************************************************************************/ andre@1: #include "xlsxcellreference.h" andre@1: #include andre@1: #include andre@1: #include andre@1: andre@1: QT_BEGIN_NAMESPACE_XLSX andre@1: andre@1: namespace { andre@1: andre@1: int intPow(int x, int p) andre@1: { andre@1: if (p == 0) return 1; andre@1: if (p == 1) return x; andre@1: andre@1: int tmp = intPow(x, p/2); andre@1: if (p%2 == 0) return tmp * tmp; andre@1: else return x * tmp * tmp; andre@1: } andre@1: andre@1: QString col_to_name(int col_num) andre@1: { andre@1: static QMap col_cache; andre@1: andre@1: if (!col_cache.contains(col_num)) { andre@1: QString col_str; andre@1: int remainder; andre@1: while (col_num) { andre@1: remainder = col_num % 26; andre@1: if (remainder == 0) andre@1: remainder = 26; andre@1: col_str.prepend(QChar('A'+remainder-1)); andre@1: col_num = (col_num - 1) / 26; andre@1: } andre@1: col_cache.insert(col_num, col_str); andre@1: } andre@1: andre@1: return col_cache[col_num]; andre@1: } andre@1: andre@1: int col_from_name(const QString &col_str) andre@1: { andre@1: int col = 0; andre@1: int expn = 0; andre@1: for (int i=col_str.size()-1; i>-1; --i) { andre@1: col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn); andre@1: expn++; andre@1: } andre@1: andre@1: return col; andre@1: } andre@1: } //namespace andre@1: andre@1: /*! andre@1: \class CellReference andre@1: \brief For one single cell such as "A1" andre@1: \inmodule QtXlsx andre@1: andre@1: The CellReference class stores the cell location in a worksheet. andre@1: */ andre@1: andre@1: /*! andre@1: Constructs an invalid Cell Reference andre@1: */ andre@1: CellReference::CellReference() andre@1: : _row(-1), _column(-1) andre@1: { andre@1: } andre@1: andre@1: /*! andre@1: Constructs the Reference from the given \a row, and \a column. andre@1: */ andre@1: CellReference::CellReference(int row, int column) andre@1: : _row(row), _column(column) andre@1: { andre@1: } andre@1: andre@1: /*! andre@1: \overload andre@1: Constructs the Reference form the given \a cell string. andre@1: */ andre@1: CellReference::CellReference(const QString &cell) andre@1: { andre@1: init(cell); andre@1: } andre@1: andre@1: /*! andre@1: \overload andre@1: Constructs the Reference form the given \a cell string. andre@1: */ andre@1: CellReference::CellReference(const char *cell) andre@1: { andre@1: init(QString::fromLatin1(cell)); andre@1: } andre@1: andre@1: void CellReference::init(const QString &cell_str) andre@1: { andre@1: static QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$")); andre@1: QRegularExpressionMatch match = re.match(cell_str); andre@1: if (match.hasMatch()) { andre@1: const QString col_str = match.captured(1); andre@1: const QString row_str = match.captured(2); andre@1: _row = row_str.toInt(); andre@1: _column = col_from_name(col_str); andre@1: } andre@1: } andre@1: andre@1: /*! andre@1: Constructs a Reference by copying the given \a andre@1: other Reference. andre@1: */ andre@1: CellReference::CellReference(const CellReference &other) andre@1: : _row(other._row), _column(other._column) andre@1: { andre@1: } andre@1: andre@1: /*! andre@1: Destroys the Reference. andre@1: */ andre@1: CellReference::~CellReference() andre@1: { andre@1: } andre@1: andre@1: /*! andre@1: Convert the Reference to string notation, such as "A1" or "$A$1". andre@1: If current object is invalid, an empty string will be returned. andre@1: */ andre@1: QString CellReference::toString(bool row_abs, bool col_abs) const andre@1: { andre@1: if (!isValid()) andre@1: return QString(); andre@1: andre@1: QString cell_str; andre@1: if (col_abs) andre@1: cell_str.append(QLatin1Char('$')); andre@1: cell_str.append(col_to_name(_column)); andre@1: if (row_abs) andre@1: cell_str.append(QLatin1Char('$')); andre@1: cell_str.append(QString::number(_row)); andre@1: return cell_str; andre@1: } andre@1: andre@1: /*! andre@1: * Returns true if the Reference is valid. andre@1: */ andre@1: bool CellReference::isValid() const andre@1: { andre@1: return _row > 0 && _column > 0; andre@1: } andre@1: andre@1: QT_END_NAMESPACE_XLSX