1use super::Cell;
2use super::CellValue;
3use super::Style;
4use crate::helper::coordinate::*;
5use crate::helper::range::*;
6use crate::structs::Column;
7use crate::structs::Row;
8use crate::traits::AdjustmentCoordinate;
9use crate::traits::AdjustmentCoordinateWith2Sheet;
10use crate::traits::AdjustmentCoordinateWithSheet;
11use std::collections::{BTreeSet, HashMap};
12
13#[derive(Clone, Default, Debug)]
14pub struct Cells {
15 map: HashMap<(u32, u32), Box<Cell>>,
16 row_column_index: BTreeSet<(u32, u32)>,
17 column_row_index: BTreeSet<(u32, u32)>,
18 default_cell_value: CellValue,
19 default_style: Style,
20}
21impl Cells {
22 #[inline]
24 pub fn iter_collection(&self) -> impl Iterator<Item = &Cell> {
25 self.map.values().map(Box::as_ref)
26 }
27
28 #[inline(always)]
29 pub fn get_collection(&self) -> Vec<&Cell> {
30 self.iter_collection().collect()
31 }
32
33 #[inline]
34 pub fn is_row_empty(&self, row_num: u32) -> bool {
35 self.row_column_index
36 .range((row_num, 0)..=(row_num, u32::MAX))
37 .next()
38 .is_none()
39 }
40
41 #[inline]
42 pub fn is_col_empty(&self, col_num: u32) -> bool {
43 self.column_row_index
44 .range((col_num, 0)..=(col_num, u32::MAX))
45 .next()
46 .is_none()
47 }
48
49 #[inline(always)]
52 pub fn iter_coordinates_sorted_by_row_column(&self) -> impl Iterator<Item = (u32, u32)> + '_ {
53 self.row_column_index
54 .iter()
55 .copied()
56 .map(|(row, col)| (col, row))
57 }
58
59 #[inline]
62 pub fn iter_cells_sorted_by_row_column(&self) -> impl Iterator<Item = &Cell> {
63 self.iter_coordinates_sorted_by_row_column()
64 .map(|(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
65 }
66
67 #[inline(always)]
70 pub fn iter_coordinates_sorted_by_column_row(&self) -> impl Iterator<Item = (u32, u32)> + '_ {
71 self.column_row_index.iter().copied()
72 }
73
74 #[inline]
77 pub fn iter_cells_sorted_by_column_row(&self) -> impl Iterator<Item = &Cell> {
78 self.iter_coordinates_sorted_by_column_row()
79 .map(|(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
80 }
81
82 #[inline(always)]
83 pub fn get_collection_sorted(&self) -> Vec<&Cell> {
84 self.iter_cells_sorted_by_row_column().collect()
85 }
86
87 #[inline]
88 pub(crate) fn get_collection_mut(&mut self) -> Vec<&mut Cell> {
89 self.map.values_mut().map(Box::as_mut).collect()
90 }
91
92 #[inline]
93 pub fn get_collection_to_hashmap(&self) -> &HashMap<(u32, u32), Box<Cell>> {
94 &self.map
95 }
96
97 #[inline]
99 pub fn iter_rows_with_cells_by_column(
100 &self,
101 column_num: u32,
102 ) -> impl Iterator<Item = u32> + '_ {
103 self.column_row_index
104 .range((column_num, 0)..=(column_num, u32::MAX))
105 .copied()
106 .map(|(_, row)| row)
107 }
108
109 #[inline]
111 pub fn iter_cells_by_column(&self, column_num: u32) -> impl Iterator<Item = &Cell> {
112 self.iter_rows_with_cells_by_column(column_num)
113 .map(move |row| self.map.get(&(row, column_num)).unwrap().as_ref())
114 }
115
116 #[inline(always)]
117 pub fn get_collection_by_column(&self, column_num: &u32) -> Vec<&Cell> {
118 self.iter_cells_by_column(*column_num).collect()
119 }
120
121 #[inline]
123 pub fn iter_columns_with_cells_by_row(&self, row_num: u32) -> impl Iterator<Item = u32> + '_ {
124 self.row_column_index
125 .range((row_num, 0)..=(row_num, u32::MAX))
126 .copied()
127 .map(|(_, col)| col)
128 }
129
130 #[inline]
132 pub fn iter_cells_by_row(&self, row_num: u32) -> impl Iterator<Item = &Cell> {
133 self.iter_columns_with_cells_by_row(row_num)
134 .map(move |col| self.map.get(&(row_num, col)).unwrap().as_ref())
135 }
136
137 #[inline(always)]
138 pub fn get_collection_by_row(&self, row_num: &u32) -> Vec<&Cell> {
139 self.iter_cells_by_row(*row_num).collect()
140 }
141
142 #[inline]
145 pub fn iter_coordinates_by_range_sorted_by_row(
146 &self,
147 row_start: u32,
148 row_end: u32,
149 col_start: u32,
150 col_end: u32,
151 ) -> impl Iterator<Item = (u32, u32)> + '_ {
152 self.row_column_index
153 .range((row_start, col_start)..=(row_end, col_end))
154 .copied()
155 .filter(move |(_, col)| (col_start..=col_end).contains(col))
156 .map(|(row, col)| (col, row))
157 }
158
159 #[inline]
161 pub fn iter_cells_by_range_sorted_by_row(
162 &self,
163 row_start: u32,
164 row_end: u32,
165 col_start: u32,
166 col_end: u32,
167 ) -> impl Iterator<Item = &Cell> {
168 self.iter_coordinates_by_range_sorted_by_row(row_start, row_end, col_start, col_end)
169 .map(move |(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
170 }
171
172 #[inline]
175 pub fn iter_coordinates_by_range_sorted_by_column(
176 &self,
177 col_start: u32,
178 col_end: u32,
179 row_start: u32,
180 row_end: u32,
181 ) -> impl Iterator<Item = (u32, u32)> + '_ {
182 self.column_row_index
183 .range((col_start, row_start)..=(col_end, row_end))
184 .copied()
185 .filter(move |(_, row)| (row_start..=row_end).contains(row))
186 }
187
188 #[inline]
191 pub fn iter_cells_by_range_sorted_by_column(
192 &self,
193 col_start: u32,
194 col_end: u32,
195 row_start: u32,
196 row_end: u32,
197 ) -> impl Iterator<Item = &Cell> {
198 self.iter_coordinates_by_range_sorted_by_column(col_start, col_end, row_start, row_end)
199 .map(move |(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
200 }
201
202 #[inline]
203 pub fn get_collection_by_column_to_hashmap(&self, column_num: &u32) -> HashMap<u32, &Cell> {
204 self.iter_cells_by_column(*column_num)
205 .map(|cell| (*cell.get_coordinate().get_row_num(), cell))
206 .collect()
207 }
208
209 #[inline]
210 pub fn get_collection_by_row_to_hashmap(&self, row_num: &u32) -> HashMap<u32, &Cell> {
211 self.iter_cells_by_row(*row_num)
212 .map(|cell| (*cell.get_coordinate().get_col_num(), cell))
213 .collect()
214 }
215
216 #[inline]
217 pub(crate) fn get_collection_to_hashmap_mut(&mut self) -> &mut HashMap<(u32, u32), Box<Cell>> {
218 &mut self.map
219 }
220
221 #[inline(always)]
222 pub fn get_highest_column_and_row(&self) -> (u32, u32) {
223 (
224 self.column_row_index.last().copied().unwrap_or((0, 0)).0,
225 self.row_column_index.last().copied().unwrap_or((0, 0)).0,
226 )
227 }
228
229 #[inline]
231 pub fn has_hyperlink(&self) -> bool {
232 self.map.values().find_map(|c| c.get_hyperlink()).is_some()
233 }
234
235 #[inline]
236 pub fn get<T>(&self, coordinate: T) -> Option<&Cell>
237 where
238 T: Into<CellCoordinates>,
239 {
240 let CellCoordinates { col, row } = coordinate.into();
241 self.map.get(&(row, col)).map(Box::as_ref)
242 }
243
244 pub(crate) fn get_mut<T>(
245 &mut self,
246 coordinate: T,
247 row_dimension: &Row,
248 col_dimension: &Column,
249 ) -> &mut Cell
250 where
251 T: Into<CellCoordinates>,
252 {
253 let CellCoordinates { col, row } = coordinate.into();
254 self.map.entry((row, col)).or_insert_with(|| {
255 let mut c = Cell::default();
256 c.get_coordinate_mut().set_col_num(col);
257 c.get_coordinate_mut().set_row_num(row);
258 if col_dimension.has_style() {
259 c.set_style(col_dimension.get_style().clone());
260 }
261 if row_dimension.has_style() {
262 c.set_style(row_dimension.get_style().clone());
263 }
264
265 self.row_column_index.insert((row, col));
266 self.column_row_index.insert((col, row));
267
268 Box::new(c)
269 })
270 }
271
272 #[inline]
273 pub fn get_cell_value<T>(&self, coordinate: T) -> &CellValue
274 where
275 T: Into<CellCoordinates>,
276 {
277 let CellCoordinates { col, row } = coordinate.into();
278 self.map
279 .get(&(row, col))
280 .map(|c| c.get_cell_value())
281 .unwrap_or(&self.default_cell_value)
282 }
283
284 #[inline]
285 pub fn get_style<T>(&self, coordinate: T) -> &Style
286 where
287 T: Into<CellCoordinates>,
288 {
289 let CellCoordinates { col, row } = coordinate.into();
290 self.map
291 .get(&(row, col))
292 .map(|c| c.get_style())
293 .unwrap_or(&self.default_style)
294 }
295
296 #[inline]
297 pub(crate) fn set(
298 &mut self,
299 cell: Cell,
300 row_dimension: &Row,
301 col_dimension: &Column,
302 ) -> &mut Self {
303 let col_num = cell.get_coordinate().get_col_num();
304 let row_num = cell.get_coordinate().get_row_num();
305 let target_cell = self.get_mut((col_num, row_num), row_dimension, col_dimension);
306 target_cell.set_obj(cell);
307 self
308 }
309
310 #[inline]
311 pub(crate) fn set_fast(&mut self, cell: Cell) -> &mut Self {
312 self.add(cell);
313 self
314 }
315
316 pub(crate) fn add(&mut self, cell: Cell) {
317 let col_num = *cell.get_coordinate().get_col_num();
318 let row_num = *cell.get_coordinate().get_row_num();
319 self.map.insert((row_num, col_num), Box::new(cell));
320 self.row_column_index.insert((row_num, col_num));
321 self.column_row_index.insert((col_num, row_num));
322 }
323
324 #[inline]
325 pub(crate) fn remove(&mut self, col_num: &u32, row_num: &u32) -> bool {
326 let k = (*row_num, *col_num);
327 let r = self.map.remove(&k).is_some();
328 if r {
329 self.row_column_index.remove(&k);
330 self.column_row_index.remove(&(k.1, k.0));
331 }
332 r
333 }
334
335 pub fn iter_all_coordinates_by_range_sorted_by_row(
336 &self,
337 range: &str,
338 ) -> impl Iterator<Item = Option<(u32, u32)>> + '_ {
339 let (row_start, row_end, col_start, col_end) = get_start_and_end_point(range);
340
341 let mut iter =
342 self.iter_coordinates_by_range_sorted_by_row(row_start, row_end, col_start, col_end);
343
344 let mut current = iter.next();
345
346 (row_start..=row_end)
347 .flat_map(move |row| (col_start..=col_end).map(move |col| (row, col)))
348 .map(move |x| {
349 if let Some((cur_col, cur_row)) = current {
350 if x < (cur_row, cur_col) {
351 None
352 } else {
353 current = iter.next();
354 Some((x.1, x.0))
355 }
356 } else {
357 None
358 }
359 })
360 }
361
362 pub fn iter_all_cells_by_range_sorted_by_row(
363 &self,
364 range: &str,
365 ) -> impl Iterator<Item = Option<&Cell>> + '_ {
366 self.iter_all_coordinates_by_range_sorted_by_row(range)
367 .map(move |coordinate| {
368 coordinate.map(move |(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
369 })
370 }
371
372 #[inline]
373 pub fn iter_all_cell_values_by_range_sorted_by_row(
374 &self,
375 range: &str,
376 ) -> impl Iterator<Item = &CellValue> + '_ {
377 self.iter_all_coordinates_by_range_sorted_by_row(range)
378 .map(|coordinate| {
379 coordinate.map_or(&self.default_cell_value, |c| self.get_cell_value(c))
380 })
381 }
382
383 pub fn iter_all_coordinates_by_range_sorted_by_column(
384 &self,
385 range: &str,
386 ) -> impl Iterator<Item = Option<(u32, u32)>> + '_ {
387 let (row_start, row_end, col_start, col_end) = get_start_and_end_point(range);
388
389 let mut iter =
390 self.iter_coordinates_by_range_sorted_by_column(col_start, col_end, row_start, row_end);
391
392 let mut current = iter.next();
393
394 (col_start..=col_end)
395 .flat_map(move |col| (row_start..=row_end).map(move |row| (col, row)))
396 .map(move |coordinate| {
397 if let Some(cur) = current {
398 if coordinate < cur {
399 None
400 } else {
401 current = iter.next();
402 Some(coordinate)
403 }
404 } else {
405 None
406 }
407 })
408 }
409
410 pub fn iter_all_cells_by_range_sorted_by_column(
411 &self,
412 range: &str,
413 ) -> impl Iterator<Item = Option<&Cell>> + '_ {
414 self.iter_all_coordinates_by_range_sorted_by_column(range)
415 .map(move |coordinate| {
416 coordinate.map(move |(col, row)| self.map.get(&(row, col)).unwrap().as_ref())
417 })
418 }
419
420 #[inline]
421 pub fn iter_all_cell_values_by_range_sorted_by_column(
422 &self,
423 range: &str,
424 ) -> impl Iterator<Item = &CellValue> + '_ {
425 self.iter_all_coordinates_by_range_sorted_by_column(range)
426 .map(|coordinate| {
427 coordinate.map_or(&self.default_cell_value, |c| self.get_cell_value(c))
428 })
429 }
430
431 #[inline(always)]
432 pub fn get_cell_by_range(&self, range: &str) -> Vec<Option<&Cell>> {
433 self.iter_all_cells_by_range_sorted_by_row(range).collect()
434 }
435
436 #[inline(always)]
437 pub fn get_cell_value_by_range(&self, range: &str) -> Vec<&CellValue> {
438 self.iter_all_cell_values_by_range_sorted_by_row(range)
439 .collect::<Vec<_>>()
440 }
441
442 #[inline]
443 pub fn get_formatted_value_by_column_and_row(&self, col_num: &u32, row_num: &u32) -> String {
444 match self.get((col_num, row_num)) {
445 Some(v) => v.get_formatted_value(),
446 None => "".into(),
447 }
448 }
449
450 pub(crate) fn rebuild_map_and_indices(&mut self) {
451 self.map = self
452 .get_collection_to_hashmap_mut()
453 .iter_mut()
454 .map(|(_, cell)| {
455 (
456 (
457 *cell.get_coordinate().get_row_num(),
458 *cell.get_coordinate().get_col_num(),
459 ),
460 std::mem::take(cell),
461 )
462 })
463 .collect();
464
465 self.row_column_index = self.map.keys().copied().collect();
466
467 self.column_row_index = self
468 .map
469 .keys()
470 .copied()
471 .map(|(col, row)| (row, col))
472 .collect();
473 }
474}
475impl AdjustmentCoordinate for Cells {
476 #[inline]
477 fn adjustment_insert_coordinate(
478 &mut self,
479 root_col_num: &u32,
480 offset_col_num: &u32,
481 root_row_num: &u32,
482 offset_row_num: &u32,
483 ) {
484 for cell in self.get_collection_to_hashmap_mut().values_mut() {
486 cell.adjustment_insert_coordinate(
487 root_col_num,
488 offset_col_num,
489 root_row_num,
490 offset_row_num,
491 );
492 }
493 self.rebuild_map_and_indices();
494 }
495
496 #[inline]
497 fn adjustment_remove_coordinate(
498 &mut self,
499 root_col_num: &u32,
500 offset_col_num: &u32,
501 root_row_num: &u32,
502 offset_row_num: &u32,
503 ) {
504 self.map.retain(|k, x| {
506 !(x.get_coordinate().is_remove_coordinate(
507 root_col_num,
508 offset_col_num,
509 root_row_num,
510 offset_row_num,
511 ))
512 });
513 for cell in self.get_collection_mut() {
514 cell.adjustment_remove_coordinate(
515 root_col_num,
516 offset_col_num,
517 root_row_num,
518 offset_row_num,
519 );
520 }
521 self.rebuild_map_and_indices();
522 }
523}
524impl AdjustmentCoordinateWith2Sheet for Cells {
525 #[inline]
526 fn adjustment_insert_coordinate_with_2sheet(
527 &mut self,
528 self_sheet_name: &str,
529 sheet_name: &str,
530 root_col_num: &u32,
531 offset_col_num: &u32,
532 root_row_num: &u32,
533 offset_row_num: &u32,
534 ) {
535 for cell in self.get_collection_to_hashmap_mut().values_mut() {
536 cell.adjustment_insert_coordinate_with_2sheet(
537 self_sheet_name,
538 sheet_name,
539 root_col_num,
540 offset_col_num,
541 root_row_num,
542 offset_row_num,
543 );
544 }
545 }
546
547 #[inline]
548 fn adjustment_remove_coordinate_with_2sheet(
549 &mut self,
550 self_sheet_name: &str,
551 sheet_name: &str,
552 root_col_num: &u32,
553 offset_col_num: &u32,
554 root_row_num: &u32,
555 offset_row_num: &u32,
556 ) {
557 for cell in self.get_collection_to_hashmap_mut().values_mut() {
558 cell.adjustment_remove_coordinate_with_2sheet(
559 self_sheet_name,
560 sheet_name,
561 root_col_num,
562 offset_col_num,
563 root_row_num,
564 offset_row_num,
565 );
566 }
567 }
568}