Skip to main content

excelize_rs/
errors.rs

1//! Error types and messages for the `excelize` crate.
2//!
3//! These errors are ported from the Go `excelize` package's `errors.go`.
4
5use std::fmt;
6
7use thiserror::Error;
8
9use crate::constants::{
10    MAX_CELL_STYLES, MAX_COLUMN_WIDTH, MAX_COLUMNS, MAX_FIELD_LENGTH, MAX_FILE_PATH_LENGTH,
11    MAX_FONT_SIZE, MAX_FORM_CONTROL_VALUE, MAX_GRAPHIC_ALT_TEXT_LENGTH, MAX_GRAPHIC_NAME_LENGTH,
12    MAX_ROW_HEIGHT, MAX_SHEET_NAME_LENGTH, MIN_COLUMNS, MIN_FONT_SIZE, TOTAL_CELL_CHARS,
13};
14
15// ------------------------------------------------------------------
16// Static errors
17// ------------------------------------------------------------------
18
19#[derive(Debug, Error)]
20#[error("unsupported VBA project")]
21pub struct ErrAddVBAProject;
22
23#[derive(Debug, Error)]
24#[error("unexpected child of attrValBool")]
25pub struct ErrAttrValBool;
26
27#[derive(Debug, Error)]
28#[error("cell value must be 0-{0} characters", TOTAL_CELL_CHARS)]
29pub struct ErrCellCharsLength;
30
31#[derive(Debug, Error)]
32#[error("the cell styles exceeds the {MAX_CELL_STYLES} limit")]
33pub struct ErrCellStyles;
34
35#[derive(Debug, Error)]
36#[error("cannot set both 'Formula' and 'Paragraph' for chart title")]
37pub struct ErrChartTitle;
38
39#[derive(Debug, Error)]
40#[error(
41    "the column number must be greater than or equal to {MIN_COLUMNS} and less than or equal to {MAX_COLUMNS}"
42)]
43pub struct ErrColumnNumber;
44
45#[derive(Debug, Error)]
46#[error("the width of the column must be less than or equal to {MAX_COLUMN_WIDTH} characters")]
47pub struct ErrColumnWidth;
48
49#[derive(Debug, Error)]
50#[error("coordinates length must be 4")]
51pub struct ErrCoordinates;
52
53#[derive(Debug, Error)]
54#[error("custom number format can not be empty")]
55pub struct ErrCustomNumFmt;
56
57#[derive(Debug, Error)]
58#[error("data validation must be 0-{MAX_FIELD_LENGTH} characters")]
59pub struct ErrDataValidationFormulaLength;
60
61#[derive(Debug, Error)]
62#[error("data validation range exceeds limit")]
63pub struct ErrDataValidationRange;
64
65#[derive(Debug, Error)]
66#[error("the same name already exists on the scope")]
67pub struct ErrDefinedNameDuplicate;
68
69#[derive(Debug, Error)]
70#[error("no defined name on the scope")]
71pub struct ErrDefinedNameScope;
72
73#[derive(Debug, Error)]
74#[error("the same name sheet already exists")]
75pub struct ErrExistsSheet;
76
77#[derive(Debug, Error)]
78#[error("the same name table already exists")]
79pub struct ErrExistsTableName;
80
81#[derive(Debug, Error)]
82#[error("fill type value must be one of 'gradient' or 'pattern'")]
83pub struct ErrFillType;
84
85#[derive(Debug, Error)]
86#[error("fill color value must be an array of two colors for 'gradient' type")]
87pub struct ErrFillGradientColor;
88
89#[derive(Debug, Error)]
90#[error("fill shading value must be between 0 and 16 for 'gradient' type")]
91pub struct ErrFillGradientShading;
92
93#[derive(Debug, Error)]
94#[error("fill color value must be empty or an array of one color for 'pattern' type")]
95pub struct ErrFillPatternColor;
96
97#[derive(Debug, Error)]
98#[error("fill pattern value must be between 0 and 18")]
99pub struct ErrFillPattern;
100
101#[derive(Debug, Error)]
102#[error("the length of the font family name must be less than or equal to 31")]
103pub struct ErrFontLength;
104
105#[derive(Debug, Error)]
106#[error("font size must be an integer from {MIN_FONT_SIZE} to {MAX_FONT_SIZE} points")]
107pub struct ErrFontSize;
108
109#[derive(Debug, Error)]
110#[error("scroll value must be an integer from 0 to {MAX_FORM_CONTROL_VALUE}")]
111pub struct ErrFormControlValue;
112
113#[derive(Debug, Error)]
114#[error("group worksheet must contain an active worksheet")]
115pub struct ErrGroupSheets;
116
117#[derive(Debug, Error)]
118#[error("unsupported image extension")]
119pub struct ErrImgExt;
120
121#[derive(Debug, Error)]
122#[error("image decode failed")]
123pub struct ErrImgLoad;
124
125#[derive(Debug, Error)]
126#[error("formula not valid")]
127pub struct ErrInvalidFormula;
128
129#[derive(Debug, Error)]
130#[error("invalid date value")]
131pub struct ErrInvalidDate;
132
133#[derive(Debug, Error)]
134#[error("file path length exceeds maximum limit {MAX_FILE_PATH_LENGTH} characters")]
135pub struct ErrMaxFilePathLength;
136
137#[derive(Debug, Error)]
138#[error("the height of the row must be less than or equal to {MAX_ROW_HEIGHT} points")]
139pub struct ErrMaxRowHeight;
140
141#[derive(Debug, Error)]
142#[error("row number exceeds maximum limit")]
143pub struct ErrMaxRows;
144
145#[derive(Debug, Error)]
146#[error("the name length exceeds the {MAX_FIELD_LENGTH} characters limit")]
147pub struct ErrNameLength;
148
149#[derive(Debug, Error)]
150#[error("the alt text length exceeds the {MAX_GRAPHIC_ALT_TEXT_LENGTH} characters limit")]
151pub struct ErrMaxGraphicAltTextLength;
152
153#[derive(Debug, Error)]
154#[error("the name length exceeds the {MAX_GRAPHIC_NAME_LENGTH} characters limit")]
155pub struct ErrMaxGraphicNameLength;
156
157#[derive(Debug, Error)]
158#[error("the value of UnzipSizeLimit should be greater than or equal to UnzipXMLSizeLimit")]
159pub struct ErrOptionsUnzipSizeLimit;
160
161#[derive(Debug, Error)]
162#[error("invalid outline level")]
163pub struct ErrOutlineLevel;
164
165#[derive(Debug, Error)]
166#[error("adjust to value must be an integer from 0 to 400")]
167pub struct ErrPageSetupAdjustTo;
168
169#[derive(Debug, Error)]
170#[error("parameter is invalid")]
171pub struct ErrParameterInvalid;
172
173#[derive(Debug, Error)]
174#[error("parameter is required")]
175pub struct ErrParameterRequired;
176
177#[derive(Debug, Error)]
178#[error("password length invalid")]
179pub struct ErrPasswordLengthInvalid;
180
181#[derive(Debug, Error)]
182#[error("this kind of show value as type requires a base field")]
183pub struct ErrPivotTableShowValuesAsBaseField;
184
185#[derive(Debug, Error)]
186#[error("this kind of show value as type and base field requires a base item")]
187pub struct ErrPivotTableShowValuesAsBaseItem;
188
189#[derive(Debug, Error)]
190#[error("cannot enable ClassicLayout and CompactData in the same time")]
191pub struct ErrPivotTableClassicLayout;
192
193#[derive(Debug, Error)]
194#[error("no path defined for file, consider File.write_to or File.write")]
195pub struct ErrSave;
196
197#[derive(Debug, Error)]
198#[error("invalid worksheet index")]
199pub struct ErrSheetIdx;
200
201#[derive(Debug, Error)]
202#[error("the sheet name can not be blank")]
203pub struct ErrSheetNameBlank;
204
205#[derive(Debug, Error)]
206#[error("the sheet can not contain any of the characters :\\/?*[or]")]
207pub struct ErrSheetNameInvalid;
208
209#[derive(Debug, Error)]
210#[error("the sheet name length exceeds the {MAX_SHEET_NAME_LENGTH} characters limit")]
211pub struct ErrSheetNameLength;
212
213#[derive(Debug, Error)]
214#[error("the first or last character of the sheet name can not be a single quote")]
215pub struct ErrSheetNameSingleQuote;
216
217#[derive(Debug, Error)]
218#[error("must have the same number of 'Location' and 'Range' parameters")]
219pub struct ErrSparkline;
220
221#[derive(Debug, Error)]
222#[error("parameter 'Location' is required")]
223pub struct ErrSparklineLocation;
224
225#[derive(Debug, Error)]
226#[error("parameter 'Range' is required")]
227pub struct ErrSparklineRange;
228
229#[derive(Debug, Error)]
230#[error("parameter 'Style' value must be an integer from 0 to 35")]
231pub struct ErrSparklineStyle;
232
233#[derive(Debug, Error)]
234#[error("parameter 'Type' value must be one of 'line', 'column' or 'win_loss'")]
235pub struct ErrSparklineType;
236
237#[derive(Debug, Error)]
238#[error("over maximum limit hyperlinks in a worksheet")]
239pub struct ErrTotalSheetHyperlinks;
240
241#[derive(Debug, Error)]
242#[error("transparency value must be an integer from 0 to 100")]
243pub struct ErrTransparency;
244
245#[derive(Debug, Error)]
246#[error("unknown encryption mechanism")]
247pub struct ErrUnknownEncryptMechanism;
248
249#[derive(Debug, Error)]
250#[error("worksheet has set no protect")]
251pub struct ErrUnprotectSheet;
252
253#[derive(Debug, Error)]
254#[error("worksheet protect password not match")]
255pub struct ErrUnprotectSheetPassword;
256
257#[derive(Debug, Error)]
258#[error("workbook has set no protect")]
259pub struct ErrUnprotectWorkbook;
260
261#[derive(Debug, Error)]
262#[error("workbook protect password not match")]
263pub struct ErrUnprotectWorkbookPassword;
264
265#[derive(Debug, Error)]
266#[error("unsupported encryption mechanism")]
267pub struct ErrUnsupportedEncryptMechanism;
268
269#[derive(Debug, Error)]
270#[error("unsupported hash algorithm")]
271pub struct ErrUnsupportedHashAlgorithm;
272
273#[derive(Debug, Error)]
274#[error("unsupported number format token")]
275pub struct ErrUnsupportedNumberFormat;
276
277#[derive(Debug, Error)]
278#[error("unsupported pivot table show value as type")]
279pub struct ErrUnsupportedPivotTableShowValuesAsType;
280
281#[derive(Debug, Error)]
282#[error("unsupported workbook file format")]
283pub struct ErrWorkbookFileFormat;
284
285#[derive(Debug, Error)]
286#[error("the supplied open workbook password is not correct")]
287pub struct ErrWorkbookPassword;
288
289#[derive(Debug, Error)]
290#[error("workbook must contain at least one worksheet")]
291pub struct ErrWorkbook;
292
293// ------------------------------------------------------------------
294// Parameterized errors
295// ------------------------------------------------------------------
296
297/// Error returned when a worksheet does not exist.
298#[derive(Debug, Clone, PartialEq, Eq)]
299pub struct ErrSheetNotExist {
300    pub sheet_name: String,
301}
302
303impl fmt::Display for ErrSheetNotExist {
304    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305        write!(f, "sheet {} does not exist", self.sheet_name)
306    }
307}
308
309impl std::error::Error for ErrSheetNotExist {}
310
311/// A convenience alias for a `Result` using the dynamic `Error` type.
312pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
313
314// ------------------------------------------------------------------
315// Helper constructors (ported from `errors.go`)
316// ------------------------------------------------------------------
317
318pub fn new_add_comment_error(cell: &str) -> String {
319    format!("comment already exist on cell {cell}")
320}
321
322pub fn new_cell_name_to_coordinates_error(cell: &str, err: impl std::error::Error) -> String {
323    format!("cannot convert cell {cell:?} to coordinates: {err}")
324}
325
326pub fn new_chart_title_error(name: &str) -> String {
327    format!("chart title field {name} value must be an integer from 0 to 100")
328}
329
330pub fn new_coordinates_to_cell_name_error(col: i32, row: i32) -> String {
331    format!("invalid cell reference [{col}, {row}]")
332}
333
334pub fn new_field_length_error(name: &str) -> String {
335    format!("field {name} must be less than or equal to 255 characters")
336}
337
338pub fn new_invalid_auto_filter_column_error(col: &str) -> String {
339    format!("incorrect index of column {col:?}")
340}
341
342pub fn new_invalid_auto_filter_exp_error(exp: &str) -> String {
343    format!("incorrect number of tokens in criteria {exp:?}")
344}
345
346pub fn new_invalid_auto_filter_operator_error(op: &str, exp: &str) -> String {
347    format!(
348        "the operator {op:?} in expression {exp:?} is not valid in relation to Blanks/NonBlanks"
349    )
350}
351
352pub fn new_invalid_cell_name_error(cell: &str) -> String {
353    format!("invalid cell name {cell:?}")
354}
355
356pub fn new_invalid_column_name_error(col: &str) -> String {
357    format!("invalid column name {col:?}")
358}
359
360pub fn new_invalid_excel_date_error(date_value: f64) -> String {
361    format!("invalid date value {date_value}, negative values are not supported")
362}
363
364pub fn new_invalid_link_type_error(link_type: &str) -> String {
365    format!("invalid link type {link_type:?}")
366}
367
368pub fn new_invalid_name_error(name: &str) -> String {
369    format!(
370        "invalid name {name:?}, the name should be starts with a letter or underscore, can not include a space or character, and can not conflict with an existing name in the workbook"
371    )
372}
373
374pub fn new_invalid_optional_value(name: &str, value: &str, values: &[&str]) -> String {
375    format!(
376        "invalid {name} value {value:?}, acceptable value should be one of {}",
377        values.join(", ")
378    )
379}
380
381pub fn new_invalid_row_number_error(row: i32) -> String {
382    format!("invalid row number {row}")
383}
384
385pub fn new_invalid_shared_string_index_error(idx: i32) -> String {
386    format!("invalid shared string index {idx}")
387}
388
389pub fn new_invalid_slicer_name_error(name: &str) -> String {
390    format!("invalid slicer name {name:?}")
391}
392
393pub fn new_invalid_style_id_error(style_id: i32) -> String {
394    format!("invalid style ID {style_id}")
395}
396
397pub fn new_no_exist_slicer_error(name: &str) -> String {
398    format!("slicer {name} does not exist")
399}
400
401pub fn new_no_exist_table_error(name: &str) -> String {
402    format!("table {name} does not exist")
403}
404
405pub fn new_not_worksheet_error(name: &str) -> String {
406    format!("sheet {name} is not a worksheet")
407}
408
409pub fn new_pivot_table_col_fields_error(data: &[String]) -> String {
410    format!(
411        "data fields {} appear both in the pivot table column fields and filter fields",
412        data.join(", ")
413    )
414}
415
416pub fn new_pivot_table_row_fields_error(data: &[String]) -> String {
417    format!(
418        "data fields {} appear both in the pivot table row fields and filter fields",
419        data.join(", ")
420    )
421}
422
423pub fn new_pivot_table_data_range_error(msg: &str) -> String {
424    format!("parameter 'DataRange' parsing error: {msg}")
425}
426
427pub fn new_pivot_table_selected_item_error(item: &str, field: &str) -> String {
428    format!("selected item {item} does not exist in pivot table field {field}")
429}
430
431pub fn new_pivot_table_range_error(msg: &str) -> String {
432    format!("parameter 'PivotTableRange' parsing error: {msg}")
433}
434
435pub fn new_pivot_table_show_values_as_base_field_error(field: &str) -> String {
436    format!("base field {field} does not exist in shared items")
437}
438
439pub fn new_stream_set_row_error(row: i32) -> String {
440    format!("row {row} has already been written")
441}
442
443pub fn new_stream_set_row_order_error(name: &str) -> String {
444    format!("must call the {name} function before the SetRow function")
445}
446
447pub fn new_unknown_filter_token_error(token: &str) -> String {
448    format!("unknown operator: {token}")
449}
450
451pub fn new_unsupported_chart_type_error(chart_type: i32) -> String {
452    format!("unsupported chart type {chart_type}")
453}
454
455pub fn new_unsupported_pivot_cache_source_type_error(source_type: &str) -> String {
456    format!("unsupported pivot table cache source type: {source_type}")
457}
458
459pub fn new_unzip_size_limit_error(unzip_size_limit: i64) -> String {
460    format!("unzip size exceeds the {unzip_size_limit} bytes limit")
461}
462
463pub fn new_view_idx_error(view_index: i32) -> String {
464    format!("view index {view_index} out of range")
465}