Skip to main content

xls_rs/excel/
chart.rs

1use anyhow::Result;
2
3use super::reader::ExcelHandler;
4
5/// Chart type for visualization
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub enum DataChartType {
8    Bar,
9    Column,
10    Line,
11    Area,
12    Pie,
13    Scatter,
14    Doughnut,
15}
16
17impl DataChartType {
18    pub fn from_str(s: &str) -> Result<Self> {
19        match s.to_lowercase().as_str() {
20            "bar" => Ok(DataChartType::Bar),
21            "column" => Ok(DataChartType::Column),
22            "line" => Ok(DataChartType::Line),
23            "area" => Ok(DataChartType::Area),
24            "pie" => Ok(DataChartType::Pie),
25            "scatter" => Ok(DataChartType::Scatter),
26            "doughnut" | "donut" => Ok(DataChartType::Doughnut),
27            _ => anyhow::bail!(
28                "Unknown chart type: {}. Use: bar, column, line, area, pie, scatter, doughnut",
29                s
30            ),
31        }
32    }
33}
34
35/// Chart configuration
36#[derive(Debug, Clone)]
37pub struct ChartConfig {
38    pub chart_type: DataChartType,
39    pub title: Option<String>,
40    pub x_axis_title: Option<String>,
41    pub y_axis_title: Option<String>,
42    pub category_column: usize,
43    pub value_columns: Vec<usize>,
44    pub width: u32,
45    pub height: u32,
46    pub show_legend: bool,
47    pub colors: Option<Vec<String>>,
48}
49
50impl Default for ChartConfig {
51    fn default() -> Self {
52        Self {
53            chart_type: DataChartType::Column,
54            title: None,
55            x_axis_title: None,
56            y_axis_title: None,
57            category_column: 0,
58            value_columns: vec![1],
59            width: 600,
60            height: 400,
61            show_legend: true,
62            colors: None,
63        }
64    }
65}
66
67impl ExcelHandler {
68    /// Write data with an embedded chart to an XLSX file
69    pub fn write_with_chart(
70        &self,
71        path: &str,
72        data: &[Vec<String>],
73        chart_config: &ChartConfig,
74    ) -> Result<()> {
75        use super::xlsx_writer::XlsxWriter;
76        use super::types::WriteOptions;
77
78        let options = WriteOptions::default();
79        let mut writer = XlsxWriter::with_options(options);
80        let sheet_name = "Sheet1";
81        writer.add_sheet(sheet_name)?;
82        writer.add_data(data);
83        writer.set_chart(chart_config.clone(), data.to_vec());
84
85        let file = std::fs::File::create(path)?;
86        let buf = std::io::BufWriter::new(file);
87        writer.save(buf)?;
88        Ok(())
89    }
90
91    /// Add a chart to existing data and write to an XLSX file
92    pub fn add_chart_to_data(
93        &self,
94        data: &[Vec<String>],
95        chart_config: &ChartConfig,
96        output_path: &str,
97    ) -> Result<()> {
98        self.write_with_chart(output_path, data, chart_config)
99    }
100}