xlsxcellreference.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // xlsxcellreference.cpp
  2. #include "xlsxcellreference.h"
  3. #include <QStringList>
  4. #include <QMap>
  5. #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
  6. #include <QRegularExpression>
  7. #else
  8. #include <QRegExp>
  9. #endif
  10. QT_BEGIN_NAMESPACE_XLSX
  11. namespace {
  12. int intPow(int x, int p)
  13. {
  14. if (p == 0) return 1;
  15. if (p == 1) return x;
  16. int tmp = intPow(x, p/2);
  17. if (p%2 == 0) return tmp * tmp;
  18. else return x * tmp * tmp;
  19. }
  20. QString col_to_name(int col_num)
  21. {
  22. static thread_local QMap<int, QString> col_cache;
  23. auto it = col_cache.find(col_num);
  24. if (it == col_cache.end()) {
  25. QString col_str;
  26. int remainder;
  27. while (col_num) {
  28. remainder = col_num % 26;
  29. if (remainder == 0)
  30. remainder = 26;
  31. col_str.prepend(QChar('A'+remainder-1));
  32. col_num = (col_num - 1) / 26;
  33. }
  34. it = col_cache.insert(col_num, col_str);
  35. }
  36. return it.value();
  37. }
  38. int col_from_name(const QString &col_str)
  39. {
  40. int col = 0;
  41. int expn = 0;
  42. for (int i=col_str.size()-1; i>-1; --i) {
  43. col += (col_str[i].unicode() - 'A' + 1) * intPow(26, expn);
  44. expn++;
  45. }
  46. return col;
  47. }
  48. } //namespace
  49. /*!
  50. \class CellReference
  51. \brief For one single cell such as "A1"
  52. \inmodule QtXlsx
  53. The CellReference class stores the cell location in a worksheet.
  54. */
  55. /*!
  56. Constructs an invalid Cell Reference
  57. */
  58. CellReference::CellReference()
  59. : _row(-1), _column(-1)
  60. {
  61. }
  62. /*!
  63. Constructs the Reference from the given \a row, and \a column.
  64. */
  65. CellReference::CellReference(int row, int column)
  66. : _row(row), _column(column)
  67. {
  68. }
  69. /*!
  70. \overload
  71. Constructs the Reference form the given \a cell string.
  72. */
  73. CellReference::CellReference(const QString &cell)
  74. {
  75. init(cell);
  76. }
  77. /*!
  78. \overload
  79. Constructs the Reference form the given \a cell string.
  80. */
  81. CellReference::CellReference(const char *cell)
  82. {
  83. init(QString::fromLatin1(cell));
  84. }
  85. void CellReference::init(const QString &cell_str)
  86. {
  87. #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
  88. static thread_local QRegularExpression re(QStringLiteral("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
  89. QRegularExpressionMatch match = re.match(cell_str);
  90. if (match.hasMatch()) {
  91. const QString col_str = match.captured(1);
  92. const QString row_str = match.captured(2);
  93. _row = row_str.toInt();
  94. _column = col_from_name(col_str);
  95. }
  96. #else
  97. QRegExp re(QLatin1String("^\\$?([A-Z]{1,3})\\$?(\\d+)$"));
  98. if (re.indexIn(cell_str) != -1)
  99. {
  100. const QString col_str = re.cap(1);
  101. const QString row_str = re.cap(2);
  102. _row = row_str.toInt();
  103. _column = col_from_name(col_str);
  104. }
  105. #endif
  106. }
  107. /*!
  108. Constructs a Reference by copying the given \a
  109. other Reference.
  110. */
  111. CellReference::CellReference(const CellReference &other)
  112. : _row(other._row), _column(other._column)
  113. {
  114. }
  115. /*!
  116. Destroys the Reference.
  117. */
  118. CellReference::~CellReference()
  119. {
  120. }
  121. /*!
  122. Convert the Reference to string notation, such as "A1" or "$A$1".
  123. If current object is invalid, an empty string will be returned.
  124. */
  125. QString CellReference::toString(bool row_abs, bool col_abs) const
  126. {
  127. if (!isValid())
  128. return QString();
  129. QString cell_str;
  130. if (col_abs)
  131. cell_str.append(QLatin1Char('$'));
  132. cell_str.append(col_to_name(_column));
  133. if (row_abs)
  134. cell_str.append(QLatin1Char('$'));
  135. cell_str.append(QString::number(_row));
  136. return cell_str;
  137. }
  138. /*!
  139. * Returns true if the Reference is valid.
  140. */
  141. bool CellReference::isValid() const
  142. {
  143. return _row > 0 && _column > 0;
  144. }
  145. QT_END_NAMESPACE_XLSX