use crate::{
format::Format,
identifier::{ByIdentifier, HasIdentifier, Identifier},
- output::pivot::{Axis3, Dimension, Group, PivotTable, Value as PivotValue},
+ output::pivot::{
+ Axis3, Dimension, Footnote, Footnotes, Group, PivotTable, Value as PivotValue,
+ },
+ settings::Show,
sys::raw::{Alignment, CategoryLabels, Measure, MissingValues, RawString, VarType},
};
///
/// The operation fails if the dictionary already contains a variable with
/// the same name (or a variant with different case), or if `variable`'s
- /// encoding differs from the dictionary's
+ /// encoding differs from the dictionary's.
pub fn add_var(&mut self, variable: Variable) -> Result<DictIndex, AddVarError> {
if variable.encoding != self.encoding {
Err(AddVarError::WrongEncoding {
}
let mut values = Group::new("Variable Value").with_label_shown();
+ let mut footnotes = Footnotes::new();
+ let missing_footnote = footnotes.push(Footnote::new("User-missing value"));
for variable in &self.dictionary.variables {
let mut group = Group::new(&**variable);
let mut values = variable.value_labels.iter().collect::<Vec<_>>();
values.sort();
for (value, label) in values {
- let value = PivotValue::new_variable(variable);
+ let value = PivotValue::new_variable_value(variable, value)
+ .with_show_value_label(Some(Show::Value));
//group.push();
todo!()
}
}
}
pub fn new_variable_value(variable: &Variable, value: &DataValue) -> Self {
- todo!()
+ let var_name = Some(variable.name.as_str().into());
+ let value_label = variable.value_labels.get(value).cloned();
+ match value {
+ DataValue::Number(number) => Self::new(ValueInner::Number(NumberValue {
+ show: None,
+ format: match variable.print_format.var_type() {
+ VarType::Numeric => variable.print_format,
+ VarType::String => {
+ #[cfg(debug_assertions)]
+ panic!("cannot create numeric pivot value with string format");
+
+ #[cfg(not(debug_assertions))]
+ Format::F8_2
+ }
+ },
+ honor_small: false,
+ value: *number,
+ var_name,
+ value_label,
+ })),
+ DataValue::String(string) => Self::new(ValueInner::String(StringValue {
+ show: None,
+ hex: variable.print_format.type_() == Type::AHex,
+ s: string.decode(variable.encoding).into_owned(),
+ var_name,
+ value_label,
+ })),
+ }
}
pub fn new_number(x: Option<f64>) -> Self {
Self::new_number_with_format(x, Format::F8_2)
}))
}
pub fn with_footnote(mut self, footnote: &Arc<Footnote>) -> Self {
+ self.add_footnote(footnote);
+ self
+ }
+ pub fn add_footnote(&mut self, footnote: &Arc<Footnote>) {
let footnotes = &mut self.styling.get_or_insert_default().footnotes;
footnotes.push(footnote.clone());
footnotes.sort_by_key(|f| f.index);
+ }
+ pub fn with_show_value_label(mut self, show: Option<Show>) -> Self {
+ match &mut self.inner {
+ ValueInner::Number(number_value) => {
+ number_value.show = show;
+ }
+ ValueInner::String(string_value) => {
+ string_value.show = show;
+ }
+ _ => (),
+ }
+ self
+ }
+ pub fn with_show_variable_label(mut self, show: Option<Show>) -> Self {
+ if let ValueInner::Variable(variable_value) = &mut self.inner {
+ variable_value.show = show;
+ }
self
}
pub const fn empty() -> Self {
self.values.is_empty() && self.range.is_none()
}
+ pub fn contains(&self, value: &Value) -> bool {
+ if self.values.contains(value) {
+ return true;
+ }
+
+ match value {
+ Value::Number(Some(number)) => self.range.is_some_and(|range| range.contains(*number)),
+ _ => false,
+ }
+ }
+
fn read<R: Read + Seek>(
r: &mut R,
offset: u64,
MissingValueRange::From { .. } => None,
}
}
+
+ pub fn contains(&self, number: f64) -> bool {
+ match self {
+ MissingValueRange::In { low, high } => (*low..*high).contains(&number),
+ MissingValueRange::From { low } => number >= *low,
+ MissingValueRange::To { high } => number <= *high,
+ }
+ }
}
impl Display for MissingValueRange {