use pptx_rs::oxml::chart::{ChartCategory, ChartData, ChartSeries, ChartType};
use pptx_rs::{Inches, Presentation};
fn make_column_data() -> ChartData {
ChartData {
categories: vec![
ChartCategory::new("Q1"),
ChartCategory::new("Q2"),
ChartCategory::new("Q3"),
ChartCategory::new("Q4"),
],
series: vec![
ChartSeries::new("Sales", vec![10.0, 20.0, 15.0, 25.0]),
ChartSeries::new("Cost", vec![5.0, 8.0, 7.0, 10.0]),
],
title: Some("季度销售对比".to_string()),
data_labels: None,
..Default::default()
}
}
#[test]
fn chart_column_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let _col = slide
.shapes_mut()
.add_chart(
ChartType::Column,
make_column_data(),
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Column failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_bar_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let _bar = slide
.shapes_mut()
.add_chart(
ChartType::Bar,
make_column_data(),
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Bar failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_line_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let line_data = ChartData {
categories: vec![
ChartCategory::new("Jan"),
ChartCategory::new("Feb"),
ChartCategory::new("Mar"),
ChartCategory::new("Apr"),
ChartCategory::new("May"),
],
series: vec![ChartSeries::new(
"Temperature",
vec![5.0, 8.0, 12.0, 18.0, 22.0],
)],
title: Some("月度温度趋势".to_string()),
data_labels: None,
..Default::default()
};
let _line = slide
.shapes_mut()
.add_chart(
ChartType::Line,
line_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Line failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_pie_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let pie_data = ChartData {
categories: vec![
ChartCategory::new("Product A"),
ChartCategory::new("Product B"),
ChartCategory::new("Product C"),
],
series: vec![ChartSeries::new("Share", vec![40.0, 35.0, 25.0])],
title: Some("市场份额".to_string()),
data_labels: None,
..Default::default()
};
let _pie = slide
.shapes_mut()
.add_chart(
ChartType::Pie,
pie_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Pie failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_scatter_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let scatter_data = ChartData {
categories: vec![],
series: vec![ChartSeries::new_scatter(
"实验数据",
vec![1.0, 2.0, 3.0, 4.0, 5.0],
vec![2.1, 3.9, 6.2, 7.8, 10.1],
)],
title: Some("散点图:X-Y 关系".to_string()),
data_labels: None,
..Default::default()
};
let _scatter = slide
.shapes_mut()
.add_chart(
ChartType::Scatter,
scatter_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Scatter failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_area_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let area_data = ChartData {
categories: vec![
ChartCategory::new("2019"),
ChartCategory::new("2020"),
ChartCategory::new("2021"),
ChartCategory::new("2022"),
ChartCategory::new("2023"),
],
series: vec![
ChartSeries::new("Revenue", vec![100.0, 120.0, 150.0, 180.0, 210.0]),
ChartSeries::new("Profit", vec![20.0, 28.0, 40.0, 55.0, 70.0]),
],
title: Some("年度营收面积图".to_string()),
data_labels: None,
..Default::default()
};
let _area = slide
.shapes_mut()
.add_chart(
ChartType::Area,
area_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Area failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn mixed_charts_in_one_slide_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let _col = slide
.shapes_mut()
.add_chart(
ChartType::Column,
make_column_data(),
Inches(0.5),
Inches(0.5),
Inches(4.5),
Inches(3.0),
)
.expect("add_chart Column failed");
let line_data = ChartData {
categories: vec![ChartCategory::new("A"), ChartCategory::new("B")],
series: vec![ChartSeries::new("S1", vec![1.0, 2.0])],
title: None,
data_labels: None,
..Default::default()
};
let _line = slide
.shapes_mut()
.add_chart(
ChartType::Line,
line_data,
Inches(5.2),
Inches(0.5),
Inches(4.5),
Inches(3.0),
)
.expect("add_chart Line failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn multiple_slides_with_different_charts() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide1 = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide 1 failed");
slide1
.shapes_mut()
.add_chart(
ChartType::Column,
make_column_data(),
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Column failed");
let counter = prs.id_counter();
let slide2 = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide 2 failed");
let pie_data = ChartData {
categories: vec![ChartCategory::new("X"), ChartCategory::new("Y")],
series: vec![ChartSeries::new("S", vec![60.0, 40.0])],
title: None,
data_labels: None,
..Default::default()
};
slide2
.shapes_mut()
.add_chart(
ChartType::Pie,
pie_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Pie failed");
assert_eq!(prs.slides().len(), 2);
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(
prs2.slides().len(),
2,
"slide count preserved after round-trip"
);
}
#[test]
fn chart_radar_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let radar_data = ChartData {
categories: vec![
ChartCategory::new("速度"),
ChartCategory::new("功耗"),
ChartCategory::new("价格"),
ChartCategory::new("容量"),
],
series: vec![
ChartSeries::new("产品A", vec![7.0, 8.0, 6.0, 9.0]),
ChartSeries::new("产品B", vec![5.0, 9.0, 7.0, 8.0]),
],
title: Some("产品对比雷达图".to_string()),
data_labels: None,
..Default::default()
};
let _radar = slide
.shapes_mut()
.add_chart(
ChartType::Radar,
radar_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Radar failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_bubble_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let bubble_data = ChartData {
categories: vec![],
series: vec![ChartSeries::new_bubble(
"样本",
vec![1.0, 2.0, 3.0, 4.0],
vec![10.0, 20.0, 30.0, 40.0],
vec![5.0, 8.0, 12.0, 15.0],
)],
title: Some("气泡图示例".to_string()),
data_labels: None,
..Default::default()
};
let _bubble = slide
.shapes_mut()
.add_chart(
ChartType::Bubble,
bubble_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Bubble failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1);
}
#[test]
fn chart_combo_round_trip() {
let mut prs = Presentation::new().expect("Presentation::new failed");
let counter = prs.id_counter();
let slide = prs
.slides_mut()
.add_slide(counter)
.expect("add_slide failed");
let mut s1 = ChartSeries::new("Sales", vec![10.0, 20.0, 15.0, 25.0]);
s1.secondary_axis = false;
let mut s2 = ChartSeries::new("Growth", vec![5.0, 12.0, 8.0, 18.0]);
s2.secondary_axis = true;
let combo_data = ChartData {
categories: vec![
ChartCategory::new("Q1"),
ChartCategory::new("Q2"),
ChartCategory::new("Q3"),
ChartCategory::new("Q4"),
],
series: vec![s1, s2],
title: Some("销量 vs 增长率(组合图)".to_string()),
data_labels: None,
secondary_chart_type: Some(ChartType::Line),
..Default::default()
};
let _combo = slide
.shapes_mut()
.add_chart(
ChartType::Column,
combo_data,
Inches(1.0),
Inches(1.0),
Inches(8.0),
Inches(4.0),
)
.expect("add_chart Combo failed");
let bytes = prs.to_bytes().expect("to_bytes failed");
let prs2 = Presentation::load_bytes(&bytes).expect("load_bytes failed");
assert_eq!(prs2.slides().len(), 1, "slide count preserved");
}