Skip to main content

umya_spreadsheet/structs/
column.rs

1use md5::Digest;
2use quick_xml::{
3    Reader,
4    events::BytesStart,
5};
6
7use super::{
8    BooleanValue,
9    DoubleValue,
10    Style,
11    Stylesheet,
12    UInt32Value,
13};
14use crate::{
15    reader::driver::{
16        get_attribute,
17        set_string_from_xml,
18    },
19    structs::Cells,
20    traits::AdjustmentValue,
21};
22
23/// # Examples
24/// ## set auto width
25/// ```rust
26/// use umya_spreadsheet::*;
27/// let mut book = new_file();
28/// let mut worksheet = book.sheet_by_name_mut("Sheet1").unwrap();
29/// worksheet.column_dimension_mut("A").set_auto_width(true);
30/// ```
31/// ## set manual width
32/// ```rust
33/// use umya_spreadsheet::*;
34/// let mut book = new_file();
35/// let mut worksheet = book.sheet_by_name_mut("Sheet1").unwrap();
36/// worksheet.column_dimension_mut("A").set_width(60f64);
37/// ```
38#[derive(Clone, Debug)]
39pub struct Column {
40    col_num:             UInt32Value,
41    pub(crate) width:    DoubleValue,
42    pub(crate) hidden:   BooleanValue,
43    pub(crate) best_fit: BooleanValue,
44    style:               Box<Style>,
45    auto_width:          BooleanValue,
46}
47
48impl Default for Column {
49    #[inline]
50    fn default() -> Self {
51        let mut width = DoubleValue::default();
52        width.set_value(8.38f64);
53        Self {
54            col_num: UInt32Value::default(),
55            width,
56            hidden: BooleanValue::default(),
57            best_fit: BooleanValue::default(),
58            style: Box::new(Style::default()),
59            auto_width: BooleanValue::default(),
60        }
61    }
62}
63
64impl Column {
65    #[inline]
66    #[must_use]
67    pub fn col_num(&self) -> u32 {
68        self.col_num.value()
69    }
70
71    #[inline]
72    #[must_use]
73    #[deprecated(since = "3.0.0", note = "Use col_num()")]
74    pub fn get_col_num(&self) -> u32 {
75        self.col_num()
76    }
77
78    #[inline]
79    pub fn set_col_num(&mut self, value: u32) -> &mut Self {
80        self.col_num.set_value(value);
81        self
82    }
83
84    #[inline]
85    #[must_use]
86    pub fn width(&self) -> f64 {
87        self.width.value()
88    }
89
90    #[inline]
91    #[must_use]
92    #[deprecated(since = "3.0.0", note = "Use width()")]
93    pub fn get_width(&self) -> f64 {
94        self.width()
95    }
96
97    #[inline]
98    pub fn set_width(&mut self, value: f64) -> &mut Self {
99        self.width.set_value(value);
100        self
101    }
102
103    #[inline]
104    #[must_use]
105    pub fn hidden(&self) -> bool {
106        self.hidden.value()
107    }
108
109    #[inline]
110    #[must_use]
111    #[deprecated(since = "3.0.0", note = "Use hidden()")]
112    pub fn get_hidden(&self) -> bool {
113        self.hidden()
114    }
115
116    #[inline]
117    pub fn set_hidden(&mut self, value: bool) -> &mut Self {
118        self.hidden.set_value(value);
119        self
120    }
121
122    #[inline]
123    #[must_use]
124    pub fn best_fit(&self) -> bool {
125        self.best_fit.value()
126    }
127
128    #[inline]
129    #[must_use]
130    #[deprecated(since = "3.0.0", note = "Use best_fit()")]
131    pub fn get_best_fit(&self) -> bool {
132        self.best_fit()
133    }
134
135    #[inline]
136    pub fn set_best_fit(&mut self, value: bool) -> &mut Self {
137        self.best_fit.set_value(value);
138        self
139    }
140
141    #[inline]
142    #[must_use]
143    pub fn style(&self) -> &Style {
144        &self.style
145    }
146
147    #[inline]
148    #[must_use]
149    #[deprecated(since = "3.0.0", note = "Use style()")]
150    pub fn get_style(&self) -> &Style {
151        self.style()
152    }
153
154    #[inline]
155    pub fn style_mut(&mut self) -> &mut Style {
156        &mut self.style
157    }
158
159    #[inline]
160    #[deprecated(since = "3.0.0", note = "Use style()")]
161    pub fn get_style_mut(&mut self) -> &mut Style {
162        self.style_mut()
163    }
164
165    #[inline]
166    pub fn set_style(&mut self, value: Style) -> &mut Self {
167        *self.style = value;
168        self
169    }
170
171    #[inline]
172    #[must_use]
173    pub fn auto_width(&self) -> bool {
174        self.auto_width.value()
175    }
176
177    #[inline]
178    #[must_use]
179    #[deprecated(since = "3.0.0", note = "Use auto_width()")]
180    pub fn get_auto_width(&self) -> bool {
181        self.auto_width()
182    }
183
184    #[inline]
185    pub fn set_auto_width(&mut self, value: bool) -> &mut Self {
186        self.auto_width.set_value(value);
187        self
188    }
189
190    pub(crate) fn calculation_auto_width(&mut self, cells: &Cells) -> &mut Self {
191        if !self.auto_width() {
192            return self;
193        }
194
195        let mut column_width_max = 0f64;
196
197        // default font size len.
198        let column_font_size = match self.style().font() {
199            Some(font) => font.font_size().val(),
200            None => 11f64,
201        };
202
203        for cell in cells.iter_cells_by_column(self.col_num()) {
204            let column_width = cell.width_point(column_font_size);
205
206            if column_width > column_width_max {
207                column_width_max = column_width;
208            }
209        }
210
211        // set default width if empty column.
212        if column_width_max == 0f64 {
213            column_width_max = 8.38f64;
214        }
215
216        self.set_width(column_width_max);
217        self
218    }
219
220    #[inline]
221    pub(crate) fn has_style(&self) -> bool {
222        *self.style != Style::default()
223    }
224
225    #[inline]
226    pub(crate) fn hash_code(&self) -> String {
227        format!(
228            "{:x}",
229            md5::Md5::digest(format!(
230                "{}{}{}",
231                self.width.value_string(),
232                self.hidden.value_string(),
233                self.best_fit.value_string(),
234            ))
235        )
236    }
237
238    #[inline]
239    #[deprecated(since = "3.0.0", note = "Use hash_code()")]
240    pub(crate) fn get_hash_code(&self) -> String {
241        self.hash_code()
242    }
243
244    pub(crate) fn set_attributes<R: std::io::BufRead>(
245        &mut self,
246        _reader: &mut Reader<R>,
247        e: &BytesStart,
248        stylesheet: &Stylesheet,
249    ) {
250        set_string_from_xml!(self, e, width, "width");
251        set_string_from_xml!(self, e, hidden, "hidden");
252        set_string_from_xml!(self, e, best_fit, "bestFit");
253
254        if let Some(v) = get_attribute(e, b"style") {
255            let style = stylesheet.style(v.parse::<usize>().unwrap());
256            self.set_style(style);
257        }
258    }
259}
260impl AdjustmentValue for Column {
261    #[inline]
262    fn adjustment_insert_value(&mut self, root_num: u32, offset_num: u32) {
263        if self.col_num.value() >= root_num {
264            self.col_num.set_value(self.col_num.value() + offset_num);
265        }
266    }
267
268    #[inline]
269    fn adjustment_remove_value(&mut self, root_num: u32, offset_num: u32) {
270        if self.col_num.value() >= root_num {
271            self.col_num.set_value(self.col_num.value() - offset_num);
272        }
273    }
274
275    #[inline]
276    fn is_remove_value(&self, root_num: u32, offset_num: u32) -> bool {
277        self.col_num.value() >= root_num && self.col_num.value() < root_num + offset_num
278    }
279}