use crate::{FormulaText, SheetId, ValidationError};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum DefinedNameScope {
#[default]
Workbook,
Sheet(SheetId),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DefinedName {
name: Box<str>,
lookup_key: Box<str>,
scope: DefinedNameScope,
formula: FormulaText,
hidden: bool,
}
impl DefinedName {
pub fn new(
name: impl Into<String>,
scope: DefinedNameScope,
formula: FormulaText,
hidden: bool,
) -> Result<Self, ValidationError> {
let name = name.into();
if name.is_empty() {
return Err(ValidationError::DefinedNameEmpty);
}
let utf16_len = name.encode_utf16().count();
if utf16_len > 255 {
return Err(ValidationError::DefinedNameTooLong { utf16_len });
}
if let Some(character) = name.chars().find(|character| character.is_control()) {
return Err(ValidationError::DefinedNameControlCharacter { character });
}
let lookup_key = case_insensitive_key(&name).into_boxed_str();
Ok(Self {
name: name.into_boxed_str(),
lookup_key,
scope,
formula,
hidden,
})
}
pub fn name(&self) -> &str {
&self.name
}
pub const fn scope(&self) -> DefinedNameScope {
self.scope
}
pub const fn formula(&self) -> &FormulaText {
&self.formula
}
pub const fn hidden(&self) -> bool {
self.hidden
}
pub(crate) fn lookup_key(&self) -> &str {
&self.lookup_key
}
}
fn case_insensitive_key(value: &str) -> String {
value.chars().flat_map(char::to_lowercase).collect()
}