Branch data TLA Line data Source code
1 : : // Copyright (c) 2014-2022 Thomas Fussell
2 : : // Copyright (c) 2024-2025 xlnt-community
3 : : //
4 : : // Permission is hereby granted, free of charge, to any person obtaining a copy
5 : : // of this software and associated documentation files (the "Software"), to deal
6 : : // in the Software without restriction, including without limitation the rights
7 : : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : : // copies of the Software, and to permit persons to whom the Software is
9 : : // furnished to do so, subject to the following conditions:
10 : : //
11 : : // The above copyright notice and this permission notice shall be included in
12 : : // all copies or substantial portions of the Software.
13 : : //
14 : : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : : // THE SOFTWARE
21 : : //
22 : : // @license: http://www.opensource.org/licenses/mit-license.php
23 : : // @author: see AUTHORS file
24 : :
25 : : #pragma once
26 : :
27 : : #include <xlnt/xlnt_config.hpp>
28 : : #include <xlnt/cell/index_types.hpp>
29 : :
30 : : #include <cstdint>
31 : : #include <functional>
32 : : #include <string>
33 : : #include <utility>
34 : :
35 : : namespace xlnt {
36 : :
37 : : class cell_reference;
38 : : class range_reference;
39 : :
40 : : /// <summary>
41 : : /// Functor for hashing a cell reference.
42 : : /// Allows for use of std::unordered_set<cell_reference, cel_reference_hash> and similar.
43 : : /// </summary>
44 : : struct XLNT_API cell_reference_hash
45 : : {
46 : : /// <summary>
47 : : /// Returns a hash representing a particular cell_reference.
48 : : /// </summary>
49 : : std::size_t operator()(const cell_reference &k) const;
50 : : };
51 : :
52 : : /// <summary>
53 : : /// An object used to refer to a cell.
54 : : /// References have two parts, the column and the row.
55 : : /// In Excel, the reference string A1 refers to the top-left-most cell. A cell_reference
56 : : /// can be initialized from a string of this form or a 1-indexed ordered pair of the form
57 : : /// column, row.
58 : : /// </summary>
59 : : class XLNT_API cell_reference
60 : : {
61 : : public:
62 : : /// <summary>
63 : : /// Splits a coordinate string like "A1" into an equivalent pair like {"A", 1}.
64 : : /// </summary>
65 : : static std::pair<std::string, row_t> split_reference(const std::string &reference_string);
66 : :
67 : : /// <summary>
68 : : /// Splits a coordinate string like "A1" into an equivalent pair like {"A", 1}.
69 : : /// Reference parameters absolute_column and absolute_row will be set to true
70 : : /// if column part or row part are prefixed by a dollar-sign indicating they
71 : : /// are absolute, otherwise false.
72 : : /// </summary>
73 : : static std::pair<std::string, row_t> split_reference(
74 : : const std::string &reference_string, bool &absolute_column, bool &absolute_row);
75 : :
76 : : // constructors
77 : :
78 : : /// <summary>
79 : : /// Default constructor makes a reference to the top-left-most cell, "A1".
80 : : /// </summary>
81 : : cell_reference();
82 : :
83 : : // TODO: should these be explicit? The implicit conversion is nice sometimes.
84 : :
85 : : /// <summary>
86 : : /// Constructs a cell_reference from a string reprenting a cell coordinate (e.g. $B14).
87 : : /// </summary>
88 : : cell_reference(const char *reference_string);
89 : :
90 : : /// <summary>
91 : : /// Constructs a cell_reference from a string reprenting a cell coordinate (e.g. $B14).
92 : : /// </summary>
93 : : cell_reference(const std::string &reference_string);
94 : :
95 : : /// <summary>
96 : : /// Constructs a cell_reference from a 1-indexed column index and row index.
97 : : /// </summary>
98 : : cell_reference(column_t column, row_t row);
99 : :
100 : : // absoluteness
101 : :
102 : : /// <summary>
103 : : /// Converts a coordinate to an absolute coordinate string (e.g. B12 -> $B$12)
104 : : /// Defaulting to true, absolute_column and absolute_row can optionally control
105 : : /// whether the resulting cell_reference has an absolute column (e.g. B12 -> $B12)
106 : : /// and absolute row (e.g. B12 -> B$12) respectively.
107 : : /// </summary>
108 : : /// <remarks>
109 : : /// This is functionally equivalent to:
110 : : /// cell_reference copy(*this);
111 : : /// copy.column_absolute(absolute_column);
112 : : /// copy.row_absolute(absolute_row);
113 : : /// return copy;
114 : : /// </remarks>
115 : : cell_reference &make_absolute(bool absolute_column = true, bool absolute_row = true);
116 : :
117 : : /// <summary>
118 : : /// Returns true if the reference refers to an absolute column, otherwise false.
119 : : /// </summary>
120 : : bool column_absolute() const;
121 : :
122 : : /// <summary>
123 : : /// Makes this reference have an absolute column if absolute_column is true,
124 : : /// otherwise not absolute.
125 : : /// </summary>
126 : : void column_absolute(bool absolute_column);
127 : :
128 : : /// <summary>
129 : : /// Returns true if the reference refers to an absolute row, otherwise false.
130 : : /// </summary>
131 : : bool row_absolute() const;
132 : :
133 : : /// <summary>
134 : : /// Makes this reference have an absolute row if absolute_row is true,
135 : : /// otherwise not absolute.
136 : : /// </summary>
137 : : void row_absolute(bool absolute_row);
138 : :
139 : : // getters/setters
140 : :
141 : : /// <summary>
142 : : /// Returns a string that identifies the column of this reference
143 : : /// (e.g. second column from left is "B")
144 : : /// </summary>
145 : : column_t column() const;
146 : :
147 : : /// <summary>
148 : : /// Sets the column of this reference from a string that identifies a particular column.
149 : : /// </summary>
150 : : void column(const std::string &column_string);
151 : :
152 : : /// <summary>
153 : : /// Returns a 1-indexed numeric index of the column of this reference.
154 : : /// </summary>
155 : : column_t::index_t column_index() const;
156 : :
157 : : /// <summary>
158 : : /// Sets the column of this reference from a 1-indexed number that identifies a particular column.
159 : : /// </summary>
160 : : void column_index(column_t column);
161 : :
162 : : /// <summary>
163 : : /// Returns a 1-indexed numeric index of the row of this reference.
164 : : /// </summary>
165 : : row_t row() const;
166 : :
167 : : /// <summary>
168 : : /// Sets the row of this reference from a 1-indexed number that identifies a particular row.
169 : : /// </summary>
170 : : void row(row_t row);
171 : :
172 : : /// <summary>
173 : : /// Returns a cell_reference offset from this cell_reference by
174 : : /// the number of columns and rows specified by the parameters.
175 : : /// A negative value for column_offset or row_offset results
176 : : /// in a reference above or left of this cell_reference, respectively.
177 : : /// </summary>
178 : : cell_reference make_offset(int column_offset, int row_offset) const;
179 : :
180 : : /// <summary>
181 : : /// Returns a string like "A1" for cell_reference(1, 1).
182 : : /// </summary>
183 : : std::string to_string() const;
184 : :
185 : : /// <summary>
186 : : /// Returns a 1x1 range_reference containing only this cell_reference.
187 : : /// </summary>
188 : : range_reference to_range() const;
189 : :
190 : : // operators
191 : :
192 : : /// <summary>
193 : : /// I've always wanted to overload the comma operator.
194 : : /// cell_reference("A", 1), cell_reference("B", 1) will return
195 : : /// range_reference(cell_reference("A", 1), cell_reference("B", 1))
196 : : /// </summary>
197 : : range_reference operator,(const cell_reference &other) const;
198 : :
199 : : /// <summary>
200 : : /// Returns true if this reference is identical to comparand including
201 : : /// in absoluteness of column and row.
202 : : /// </summary>
203 : : bool operator==(const cell_reference &comparand) const;
204 : :
205 : : /// <summary>
206 : : /// Constructs a cell_reference from reference_string and return the result
207 : : /// of their comparison.
208 : : /// </summary>
209 : : bool operator==(const std::string &reference_string) const;
210 : :
211 : : /// <summary>
212 : : /// Constructs a cell_reference from reference_string and return the result
213 : : /// of their comparison.
214 : : /// </summary>
215 : : bool operator==(const char *reference_string) const;
216 : :
217 : : /// <summary>
218 : : /// Returns true if this reference is not identical to comparand including
219 : : /// in absoluteness of column and row.
220 : : /// </summary>
221 : : bool operator!=(const cell_reference &comparand) const;
222 : :
223 : : /// <summary>
224 : : /// Constructs a cell_reference from reference_string and return the result
225 : : /// of their comparison.
226 : : /// </summary>
227 : : bool operator!=(const std::string &reference_string) const;
228 : :
229 : : /// <summary>
230 : : /// Constructs a cell_reference from reference_string and return the result
231 : : /// of their comparison.
232 : : /// </summary>
233 : : bool operator!=(const char *reference_string) const;
234 : :
235 : : private:
236 : : /// <summary>
237 : : /// Index of the column. Important: this is one-indexed to conform
238 : : /// with Excel. Column "A", the first column, would have an index of 1.
239 : : /// </summary>
240 : : column_t column_;
241 : :
242 : : /// <summary>
243 : : /// Index of the column. Important: this is one-indexed to conform
244 : : /// with Excel. Column "A", the first column, would have an index of 1.
245 : : /// </summary>
246 : : row_t row_;
247 : :
248 : : /// <summary>
249 : : /// True if the reference's row is absolute. This looks like "A$1" in Excel.
250 : : /// </summary>
251 : : bool absolute_row_ = false;
252 : :
253 : : /// <summary>
254 : : /// True if the reference's column is absolute. This looks like "$A1" in Excel.
255 : : /// </summary>
256 : : bool absolute_column_ = false;
257 : : };
258 : :
259 : : } // namespace xlnt
260 : :
261 : : namespace std {
262 : : template <>
263 : : struct hash<xlnt::cell_reference>
264 : : {
265 :CBC 19014 : size_t operator()(const xlnt::cell_reference &x) const
266 : : {
267 : : static_assert(std::is_same<decltype(x.row()), std::uint32_t>::value, "this hash function expects both row and column to be 32-bit numbers");
268 : : static_assert(std::is_same<decltype(x.column_index()), std::uint32_t>::value, "this hash function expects both row and column to be 32-bit numbers");
269 [ + + ]: 19014 : return hash<std::uint64_t>{}(x.row() | static_cast<std::uint64_t>(x.column_index()) << 32);
270 : : }
271 : : };
272 : : } // namespace std
|