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