1use serde::{Deserialize, Serialize};
6
7use crate::namespaces;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(rename = "chartSpace")]
12pub struct ChartSpace {
13 #[serde(rename = "@xmlns:c")]
14 pub xmlns_c: String,
15
16 #[serde(rename = "@xmlns:a")]
17 pub xmlns_a: String,
18
19 #[serde(rename = "@xmlns:r")]
20 pub xmlns_r: String,
21
22 #[serde(rename = "c:chart")]
23 pub chart: Chart,
24}
25
26impl Default for ChartSpace {
27 fn default() -> Self {
28 Self {
29 xmlns_c: namespaces::DRAWING_ML_CHART.to_string(),
30 xmlns_a: namespaces::DRAWING_ML.to_string(),
31 xmlns_r: namespaces::RELATIONSHIPS.to_string(),
32 chart: Chart::default(),
33 }
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
39pub struct Chart {
40 #[serde(rename = "c:title", skip_serializing_if = "Option::is_none")]
41 pub title: Option<ChartTitle>,
42
43 #[serde(rename = "c:view3D", skip_serializing_if = "Option::is_none")]
44 pub view_3d: Option<View3D>,
45
46 #[serde(rename = "c:plotArea")]
47 pub plot_area: PlotArea,
48
49 #[serde(rename = "c:legend", skip_serializing_if = "Option::is_none")]
50 pub legend: Option<Legend>,
51
52 #[serde(rename = "c:plotVisOnly", skip_serializing_if = "Option::is_none")]
53 pub plot_vis_only: Option<BoolVal>,
54}
55
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub struct ChartTitle {
59 #[serde(rename = "c:tx")]
60 pub tx: TitleTx,
61}
62
63#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
65pub struct TitleTx {
66 #[serde(rename = "c:rich")]
67 pub rich: RichText,
68}
69
70#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
72pub struct RichText {
73 #[serde(rename = "a:bodyPr")]
74 pub body_pr: BodyPr,
75
76 #[serde(rename = "a:p")]
77 pub paragraphs: Vec<Paragraph>,
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub struct BodyPr {}
83
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
86pub struct Paragraph {
87 #[serde(rename = "a:r", default)]
88 pub runs: Vec<Run>,
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
93pub struct Run {
94 #[serde(rename = "a:t")]
95 pub t: String,
96}
97
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
100pub struct PlotArea {
101 #[serde(rename = "c:layout", skip_serializing_if = "Option::is_none")]
102 pub layout: Option<Layout>,
103
104 #[serde(rename = "c:barChart", skip_serializing_if = "Option::is_none")]
105 pub bar_chart: Option<BarChart>,
106
107 #[serde(rename = "c:bar3DChart", skip_serializing_if = "Option::is_none")]
108 pub bar_3d_chart: Option<Bar3DChart>,
109
110 #[serde(rename = "c:lineChart", skip_serializing_if = "Option::is_none")]
111 pub line_chart: Option<LineChart>,
112
113 #[serde(rename = "c:line3DChart", skip_serializing_if = "Option::is_none")]
114 pub line_3d_chart: Option<Line3DChart>,
115
116 #[serde(rename = "c:pieChart", skip_serializing_if = "Option::is_none")]
117 pub pie_chart: Option<PieChart>,
118
119 #[serde(rename = "c:pie3DChart", skip_serializing_if = "Option::is_none")]
120 pub pie_3d_chart: Option<Pie3DChart>,
121
122 #[serde(rename = "c:doughnutChart", skip_serializing_if = "Option::is_none")]
123 pub doughnut_chart: Option<DoughnutChart>,
124
125 #[serde(rename = "c:areaChart", skip_serializing_if = "Option::is_none")]
126 pub area_chart: Option<AreaChart>,
127
128 #[serde(rename = "c:area3DChart", skip_serializing_if = "Option::is_none")]
129 pub area_3d_chart: Option<Area3DChart>,
130
131 #[serde(rename = "c:scatterChart", skip_serializing_if = "Option::is_none")]
132 pub scatter_chart: Option<ScatterChart>,
133
134 #[serde(rename = "c:bubbleChart", skip_serializing_if = "Option::is_none")]
135 pub bubble_chart: Option<BubbleChart>,
136
137 #[serde(rename = "c:radarChart", skip_serializing_if = "Option::is_none")]
138 pub radar_chart: Option<RadarChart>,
139
140 #[serde(rename = "c:stockChart", skip_serializing_if = "Option::is_none")]
141 pub stock_chart: Option<StockChart>,
142
143 #[serde(rename = "c:surfaceChart", skip_serializing_if = "Option::is_none")]
144 pub surface_chart: Option<SurfaceChart>,
145
146 #[serde(rename = "c:surface3DChart", skip_serializing_if = "Option::is_none")]
147 pub surface_3d_chart: Option<Surface3DChart>,
148
149 #[serde(rename = "c:ofPieChart", skip_serializing_if = "Option::is_none")]
150 pub of_pie_chart: Option<OfPieChart>,
151
152 #[serde(rename = "c:catAx", skip_serializing_if = "Option::is_none")]
153 pub cat_ax: Option<CatAx>,
154
155 #[serde(rename = "c:valAx", skip_serializing_if = "Option::is_none")]
156 pub val_ax: Option<ValAx>,
157
158 #[serde(rename = "c:serAx", skip_serializing_if = "Option::is_none")]
159 pub ser_ax: Option<SerAx>,
160}
161
162#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
164pub struct Layout {}
165
166#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
168pub struct BarChart {
169 #[serde(rename = "c:barDir")]
170 pub bar_dir: StringVal,
171
172 #[serde(rename = "c:grouping")]
173 pub grouping: StringVal,
174
175 #[serde(rename = "c:ser", default)]
176 pub series: Vec<Series>,
177
178 #[serde(rename = "c:axId", default)]
179 pub ax_ids: Vec<UintVal>,
180}
181
182#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184pub struct Bar3DChart {
185 #[serde(rename = "c:barDir")]
186 pub bar_dir: StringVal,
187
188 #[serde(rename = "c:grouping")]
189 pub grouping: StringVal,
190
191 #[serde(rename = "c:ser", default)]
192 pub series: Vec<Series>,
193
194 #[serde(rename = "c:shape", skip_serializing_if = "Option::is_none")]
195 pub shape: Option<StringVal>,
196
197 #[serde(rename = "c:axId", default)]
198 pub ax_ids: Vec<UintVal>,
199}
200
201#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
203pub struct LineChart {
204 #[serde(rename = "c:grouping")]
205 pub grouping: StringVal,
206
207 #[serde(rename = "c:ser", default)]
208 pub series: Vec<Series>,
209
210 #[serde(rename = "c:axId", default)]
211 pub ax_ids: Vec<UintVal>,
212}
213
214#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216pub struct Line3DChart {
217 #[serde(rename = "c:grouping")]
218 pub grouping: StringVal,
219
220 #[serde(rename = "c:ser", default)]
221 pub series: Vec<Series>,
222
223 #[serde(rename = "c:axId", default)]
224 pub ax_ids: Vec<UintVal>,
225}
226
227#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
229pub struct PieChart {
230 #[serde(rename = "c:ser", default)]
231 pub series: Vec<Series>,
232}
233
234#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
236pub struct Pie3DChart {
237 #[serde(rename = "c:ser", default)]
238 pub series: Vec<Series>,
239}
240
241#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243pub struct DoughnutChart {
244 #[serde(rename = "c:ser", default)]
245 pub series: Vec<Series>,
246
247 #[serde(rename = "c:holeSize", skip_serializing_if = "Option::is_none")]
248 pub hole_size: Option<UintVal>,
249}
250
251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
253pub struct AreaChart {
254 #[serde(rename = "c:grouping")]
255 pub grouping: StringVal,
256
257 #[serde(rename = "c:ser", default)]
258 pub series: Vec<Series>,
259
260 #[serde(rename = "c:axId", default)]
261 pub ax_ids: Vec<UintVal>,
262}
263
264#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266pub struct Area3DChart {
267 #[serde(rename = "c:grouping")]
268 pub grouping: StringVal,
269
270 #[serde(rename = "c:ser", default)]
271 pub series: Vec<Series>,
272
273 #[serde(rename = "c:axId", default)]
274 pub ax_ids: Vec<UintVal>,
275}
276
277#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
279pub struct ScatterChart {
280 #[serde(rename = "c:scatterStyle")]
281 pub scatter_style: StringVal,
282
283 #[serde(rename = "c:ser", default)]
284 pub series: Vec<ScatterSeries>,
285
286 #[serde(rename = "c:axId", default)]
287 pub ax_ids: Vec<UintVal>,
288}
289
290#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
292pub struct ScatterSeries {
293 #[serde(rename = "c:idx")]
294 pub idx: UintVal,
295
296 #[serde(rename = "c:order")]
297 pub order: UintVal,
298
299 #[serde(rename = "c:tx", skip_serializing_if = "Option::is_none")]
300 pub tx: Option<SeriesText>,
301
302 #[serde(rename = "c:xVal", skip_serializing_if = "Option::is_none")]
303 pub x_val: Option<CategoryRef>,
304
305 #[serde(rename = "c:yVal", skip_serializing_if = "Option::is_none")]
306 pub y_val: Option<ValueRef>,
307}
308
309#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
311pub struct BubbleChart {
312 #[serde(rename = "c:ser", default)]
313 pub series: Vec<BubbleSeries>,
314
315 #[serde(rename = "c:axId", default)]
316 pub ax_ids: Vec<UintVal>,
317}
318
319#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
321pub struct BubbleSeries {
322 #[serde(rename = "c:idx")]
323 pub idx: UintVal,
324
325 #[serde(rename = "c:order")]
326 pub order: UintVal,
327
328 #[serde(rename = "c:tx", skip_serializing_if = "Option::is_none")]
329 pub tx: Option<SeriesText>,
330
331 #[serde(rename = "c:xVal", skip_serializing_if = "Option::is_none")]
332 pub x_val: Option<CategoryRef>,
333
334 #[serde(rename = "c:yVal", skip_serializing_if = "Option::is_none")]
335 pub y_val: Option<ValueRef>,
336
337 #[serde(rename = "c:bubbleSize", skip_serializing_if = "Option::is_none")]
338 pub bubble_size: Option<ValueRef>,
339
340 #[serde(rename = "c:bubble3D", skip_serializing_if = "Option::is_none")]
341 pub bubble_3d: Option<BoolVal>,
342}
343
344#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
346pub struct RadarChart {
347 #[serde(rename = "c:radarStyle")]
348 pub radar_style: StringVal,
349
350 #[serde(rename = "c:ser", default)]
351 pub series: Vec<Series>,
352
353 #[serde(rename = "c:axId", default)]
354 pub ax_ids: Vec<UintVal>,
355}
356
357#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
359pub struct StockChart {
360 #[serde(rename = "c:ser", default)]
361 pub series: Vec<Series>,
362
363 #[serde(rename = "c:axId", default)]
364 pub ax_ids: Vec<UintVal>,
365}
366
367#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
369pub struct SurfaceChart {
370 #[serde(rename = "c:wireframe", skip_serializing_if = "Option::is_none")]
371 pub wireframe: Option<BoolVal>,
372
373 #[serde(rename = "c:ser", default)]
374 pub series: Vec<Series>,
375
376 #[serde(rename = "c:axId", default)]
377 pub ax_ids: Vec<UintVal>,
378}
379
380#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
382pub struct Surface3DChart {
383 #[serde(rename = "c:wireframe", skip_serializing_if = "Option::is_none")]
384 pub wireframe: Option<BoolVal>,
385
386 #[serde(rename = "c:ser", default)]
387 pub series: Vec<Series>,
388
389 #[serde(rename = "c:axId", default)]
390 pub ax_ids: Vec<UintVal>,
391}
392
393#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
395pub struct OfPieChart {
396 #[serde(rename = "c:ofPieType")]
397 pub of_pie_type: StringVal,
398
399 #[serde(rename = "c:ser", default)]
400 pub series: Vec<Series>,
401
402 #[serde(rename = "c:serLines", skip_serializing_if = "Option::is_none")]
403 pub ser_lines: Option<SerLines>,
404}
405
406#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
408pub struct SerLines {}
409
410#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
412pub struct Series {
413 #[serde(rename = "c:idx")]
414 pub idx: UintVal,
415
416 #[serde(rename = "c:order")]
417 pub order: UintVal,
418
419 #[serde(rename = "c:tx", skip_serializing_if = "Option::is_none")]
420 pub tx: Option<SeriesText>,
421
422 #[serde(rename = "c:cat", skip_serializing_if = "Option::is_none")]
423 pub cat: Option<CategoryRef>,
424
425 #[serde(rename = "c:val", skip_serializing_if = "Option::is_none")]
426 pub val: Option<ValueRef>,
427}
428
429#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
431pub struct SeriesText {
432 #[serde(rename = "c:strRef", skip_serializing_if = "Option::is_none")]
433 pub str_ref: Option<StrRef>,
434
435 #[serde(rename = "c:v", skip_serializing_if = "Option::is_none")]
436 pub v: Option<String>,
437}
438
439#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
441pub struct StrRef {
442 #[serde(rename = "c:f")]
443 pub f: String,
444}
445
446#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
448pub struct CategoryRef {
449 #[serde(rename = "c:strRef", skip_serializing_if = "Option::is_none")]
450 pub str_ref: Option<StrRef>,
451
452 #[serde(rename = "c:numRef", skip_serializing_if = "Option::is_none")]
453 pub num_ref: Option<NumRef>,
454}
455
456#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
458pub struct ValueRef {
459 #[serde(rename = "c:numRef", skip_serializing_if = "Option::is_none")]
460 pub num_ref: Option<NumRef>,
461}
462
463#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
465pub struct NumRef {
466 #[serde(rename = "c:f")]
467 pub f: String,
468}
469
470#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
472pub struct Legend {
473 #[serde(rename = "c:legendPos")]
474 pub legend_pos: StringVal,
475}
476
477#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
479pub struct CatAx {
480 #[serde(rename = "c:axId")]
481 pub ax_id: UintVal,
482
483 #[serde(rename = "c:scaling")]
484 pub scaling: Scaling,
485
486 #[serde(rename = "c:delete")]
487 pub delete: BoolVal,
488
489 #[serde(rename = "c:axPos")]
490 pub ax_pos: StringVal,
491
492 #[serde(rename = "c:crossAx")]
493 pub cross_ax: UintVal,
494}
495
496#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
498pub struct ValAx {
499 #[serde(rename = "c:axId")]
500 pub ax_id: UintVal,
501
502 #[serde(rename = "c:scaling")]
503 pub scaling: Scaling,
504
505 #[serde(rename = "c:delete")]
506 pub delete: BoolVal,
507
508 #[serde(rename = "c:axPos")]
509 pub ax_pos: StringVal,
510
511 #[serde(rename = "c:crossAx")]
512 pub cross_ax: UintVal,
513}
514
515#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
517pub struct SerAx {
518 #[serde(rename = "c:axId")]
519 pub ax_id: UintVal,
520
521 #[serde(rename = "c:scaling")]
522 pub scaling: Scaling,
523
524 #[serde(rename = "c:delete")]
525 pub delete: BoolVal,
526
527 #[serde(rename = "c:axPos")]
528 pub ax_pos: StringVal,
529
530 #[serde(rename = "c:crossAx")]
531 pub cross_ax: UintVal,
532}
533
534#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
536pub struct View3D {
537 #[serde(rename = "c:rotX", skip_serializing_if = "Option::is_none")]
538 pub rot_x: Option<IntVal>,
539
540 #[serde(rename = "c:rotY", skip_serializing_if = "Option::is_none")]
541 pub rot_y: Option<IntVal>,
542
543 #[serde(rename = "c:depthPercent", skip_serializing_if = "Option::is_none")]
544 pub depth_percent: Option<UintVal>,
545
546 #[serde(rename = "c:rAngAx", skip_serializing_if = "Option::is_none")]
547 pub r_ang_ax: Option<BoolVal>,
548
549 #[serde(rename = "c:perspective", skip_serializing_if = "Option::is_none")]
550 pub perspective: Option<UintVal>,
551}
552
553#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
555pub struct Scaling {
556 #[serde(rename = "c:orientation")]
557 pub orientation: StringVal,
558}
559
560#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
562pub struct StringVal {
563 #[serde(rename = "@val")]
564 pub val: String,
565}
566
567#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
569pub struct UintVal {
570 #[serde(rename = "@val")]
571 pub val: u32,
572}
573
574#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
576pub struct IntVal {
577 #[serde(rename = "@val")]
578 pub val: i32,
579}
580
581#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
583pub struct BoolVal {
584 #[serde(rename = "@val")]
585 pub val: bool,
586}
587
588#[cfg(test)]
589mod tests {
590 use super::*;
591
592 #[test]
593 fn test_chart_space_default() {
594 let cs = ChartSpace::default();
595 assert_eq!(cs.xmlns_c, namespaces::DRAWING_ML_CHART);
596 assert_eq!(cs.xmlns_a, namespaces::DRAWING_ML);
597 assert_eq!(cs.xmlns_r, namespaces::RELATIONSHIPS);
598 }
599
600 #[test]
601 fn test_string_val_serialize() {
602 let sv = StringVal {
603 val: "col".to_string(),
604 };
605 let xml = quick_xml::se::to_string(&sv).unwrap();
606 assert!(xml.contains("val=\"col\""));
607 }
608
609 #[test]
610 fn test_uint_val_serialize() {
611 let uv = UintVal { val: 42 };
612 let xml = quick_xml::se::to_string(&uv).unwrap();
613 assert!(xml.contains("val=\"42\""));
614 }
615
616 #[test]
617 fn test_int_val_serialize() {
618 let iv = IntVal { val: -15 };
619 let xml = quick_xml::se::to_string(&iv).unwrap();
620 assert!(xml.contains("val=\"-15\""));
621 }
622
623 #[test]
624 fn test_bool_val_serialize() {
625 let bv = BoolVal { val: true };
626 let xml = quick_xml::se::to_string(&bv).unwrap();
627 assert!(xml.contains("val=\"true\""));
628 }
629
630 #[test]
631 fn test_series_serialize() {
632 let series = Series {
633 idx: UintVal { val: 0 },
634 order: UintVal { val: 0 },
635 tx: Some(SeriesText {
636 str_ref: None,
637 v: Some("Sales".to_string()),
638 }),
639 cat: Some(CategoryRef {
640 str_ref: Some(StrRef {
641 f: "Sheet1!$A$2:$A$6".to_string(),
642 }),
643 num_ref: None,
644 }),
645 val: Some(ValueRef {
646 num_ref: Some(NumRef {
647 f: "Sheet1!$B$2:$B$6".to_string(),
648 }),
649 }),
650 };
651 let xml = quick_xml::se::to_string(&series).unwrap();
652 assert!(xml.contains("Sheet1!$A$2:$A$6"));
653 assert!(xml.contains("Sheet1!$B$2:$B$6"));
654 }
655
656 #[test]
657 fn test_bar_chart_serialize() {
658 let bar = BarChart {
659 bar_dir: StringVal {
660 val: "col".to_string(),
661 },
662 grouping: StringVal {
663 val: "clustered".to_string(),
664 },
665 series: vec![],
666 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
667 };
668 let xml = quick_xml::se::to_string(&bar).unwrap();
669 assert!(xml.contains("col"));
670 assert!(xml.contains("clustered"));
671 }
672
673 #[test]
674 fn test_bar_3d_chart_serialize() {
675 let bar = Bar3DChart {
676 bar_dir: StringVal {
677 val: "col".to_string(),
678 },
679 grouping: StringVal {
680 val: "clustered".to_string(),
681 },
682 series: vec![],
683 shape: None,
684 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
685 };
686 let xml = quick_xml::se::to_string(&bar).unwrap();
687 assert!(xml.contains("col"));
688 assert!(xml.contains("clustered"));
689 }
690
691 #[test]
692 fn test_area_chart_serialize() {
693 let area = AreaChart {
694 grouping: StringVal {
695 val: "standard".to_string(),
696 },
697 series: vec![],
698 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
699 };
700 let xml = quick_xml::se::to_string(&area).unwrap();
701 assert!(xml.contains("standard"));
702 }
703
704 #[test]
705 fn test_scatter_chart_serialize() {
706 let scatter = ScatterChart {
707 scatter_style: StringVal {
708 val: "lineMarker".to_string(),
709 },
710 series: vec![ScatterSeries {
711 idx: UintVal { val: 0 },
712 order: UintVal { val: 0 },
713 tx: None,
714 x_val: Some(CategoryRef {
715 str_ref: None,
716 num_ref: Some(NumRef {
717 f: "Sheet1!$A$2:$A$6".to_string(),
718 }),
719 }),
720 y_val: Some(ValueRef {
721 num_ref: Some(NumRef {
722 f: "Sheet1!$B$2:$B$6".to_string(),
723 }),
724 }),
725 }],
726 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
727 };
728 let xml = quick_xml::se::to_string(&scatter).unwrap();
729 assert!(xml.contains("lineMarker"));
730 assert!(xml.contains("Sheet1!$A$2:$A$6"));
731 assert!(xml.contains("Sheet1!$B$2:$B$6"));
732 }
733
734 #[test]
735 fn test_bubble_chart_serialize() {
736 let bubble = BubbleChart {
737 series: vec![BubbleSeries {
738 idx: UintVal { val: 0 },
739 order: UintVal { val: 0 },
740 tx: None,
741 x_val: None,
742 y_val: None,
743 bubble_size: Some(ValueRef {
744 num_ref: Some(NumRef {
745 f: "Sheet1!$C$2:$C$6".to_string(),
746 }),
747 }),
748 bubble_3d: None,
749 }],
750 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
751 };
752 let xml = quick_xml::se::to_string(&bubble).unwrap();
753 assert!(xml.contains("Sheet1!$C$2:$C$6"));
754 }
755
756 #[test]
757 fn test_radar_chart_serialize() {
758 let radar = RadarChart {
759 radar_style: StringVal {
760 val: "marker".to_string(),
761 },
762 series: vec![],
763 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
764 };
765 let xml = quick_xml::se::to_string(&radar).unwrap();
766 assert!(xml.contains("marker"));
767 }
768
769 #[test]
770 fn test_surface_chart_serialize() {
771 let surface = SurfaceChart {
772 wireframe: Some(BoolVal { val: true }),
773 series: vec![],
774 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }, UintVal { val: 3 }],
775 };
776 let xml = quick_xml::se::to_string(&surface).unwrap();
777 assert!(xml.contains("val=\"true\""));
778 }
779
780 #[test]
781 fn test_view_3d_serialize() {
782 let view = View3D {
783 rot_x: Some(IntVal { val: 15 }),
784 rot_y: Some(IntVal { val: 20 }),
785 depth_percent: Some(UintVal { val: 150 }),
786 r_ang_ax: Some(BoolVal { val: true }),
787 perspective: Some(UintVal { val: 30 }),
788 };
789 let xml = quick_xml::se::to_string(&view).unwrap();
790 assert!(xml.contains("val=\"15\""));
791 assert!(xml.contains("val=\"20\""));
792 assert!(xml.contains("val=\"150\""));
793 }
794
795 #[test]
796 fn test_ser_ax_serialize() {
797 let ser_ax = SerAx {
798 ax_id: UintVal { val: 3 },
799 scaling: Scaling {
800 orientation: StringVal {
801 val: "minMax".to_string(),
802 },
803 },
804 delete: BoolVal { val: false },
805 ax_pos: StringVal {
806 val: "b".to_string(),
807 },
808 cross_ax: UintVal { val: 1 },
809 };
810 let xml = quick_xml::se::to_string(&ser_ax).unwrap();
811 assert!(xml.contains("val=\"3\""));
812 assert!(xml.contains("minMax"));
813 }
814
815 #[test]
816 fn test_legend_serialize() {
817 let legend = Legend {
818 legend_pos: StringVal {
819 val: "b".to_string(),
820 },
821 };
822 let xml = quick_xml::se::to_string(&legend).unwrap();
823 assert!(xml.contains("val=\"b\""));
824 }
825
826 #[test]
827 fn test_chart_title_serialize() {
828 let title = ChartTitle {
829 tx: TitleTx {
830 rich: RichText {
831 body_pr: BodyPr {},
832 paragraphs: vec![Paragraph {
833 runs: vec![Run {
834 t: "My Chart".to_string(),
835 }],
836 }],
837 },
838 },
839 };
840 let xml = quick_xml::se::to_string(&title).unwrap();
841 assert!(xml.contains("My Chart"));
842 }
843
844 #[test]
845 fn test_num_ref_serialize() {
846 let num_ref = NumRef {
847 f: "Sheet1!$B$1:$B$5".to_string(),
848 };
849 let xml = quick_xml::se::to_string(&num_ref).unwrap();
850 assert!(xml.contains("Sheet1!$B$1:$B$5"));
851 }
852
853 #[test]
854 fn test_str_ref_serialize() {
855 let str_ref = StrRef {
856 f: "Sheet1!$A$1".to_string(),
857 };
858 let xml = quick_xml::se::to_string(&str_ref).unwrap();
859 assert!(xml.contains("Sheet1!$A$1"));
860 }
861
862 #[test]
863 fn test_plot_area_default_all_none() {
864 let pa = PlotArea::default();
865 assert!(pa.layout.is_none());
866 assert!(pa.bar_chart.is_none());
867 assert!(pa.bar_3d_chart.is_none());
868 assert!(pa.line_chart.is_none());
869 assert!(pa.line_3d_chart.is_none());
870 assert!(pa.pie_chart.is_none());
871 assert!(pa.pie_3d_chart.is_none());
872 assert!(pa.doughnut_chart.is_none());
873 assert!(pa.area_chart.is_none());
874 assert!(pa.area_3d_chart.is_none());
875 assert!(pa.scatter_chart.is_none());
876 assert!(pa.bubble_chart.is_none());
877 assert!(pa.radar_chart.is_none());
878 assert!(pa.stock_chart.is_none());
879 assert!(pa.surface_chart.is_none());
880 assert!(pa.surface_3d_chart.is_none());
881 assert!(pa.of_pie_chart.is_none());
882 assert!(pa.cat_ax.is_none());
883 assert!(pa.val_ax.is_none());
884 assert!(pa.ser_ax.is_none());
885 }
886
887 #[test]
888 fn test_chart_with_view_3d() {
889 let chart = Chart {
890 title: None,
891 view_3d: Some(View3D {
892 rot_x: Some(IntVal { val: 15 }),
893 rot_y: Some(IntVal { val: 20 }),
894 depth_percent: None,
895 r_ang_ax: Some(BoolVal { val: true }),
896 perspective: None,
897 }),
898 plot_area: PlotArea::default(),
899 legend: None,
900 plot_vis_only: None,
901 };
902 let xml = quick_xml::se::to_string(&chart).unwrap();
903 assert!(xml.contains("val=\"15\""));
904 assert!(xml.contains("val=\"20\""));
905 }
906
907 #[test]
908 fn test_doughnut_chart_serialize() {
909 let doughnut = DoughnutChart {
910 series: vec![],
911 hole_size: Some(UintVal { val: 50 }),
912 };
913 let xml = quick_xml::se::to_string(&doughnut).unwrap();
914 assert!(xml.contains("val=\"50\""));
915 }
916
917 #[test]
918 fn test_bar_3d_chart_with_shape() {
919 let bar = Bar3DChart {
920 bar_dir: StringVal {
921 val: "col".to_string(),
922 },
923 grouping: StringVal {
924 val: "clustered".to_string(),
925 },
926 series: vec![],
927 shape: Some(StringVal {
928 val: "cone".to_string(),
929 }),
930 ax_ids: vec![UintVal { val: 1 }, UintVal { val: 2 }],
931 };
932 let xml = quick_xml::se::to_string(&bar).unwrap();
933 assert!(xml.contains("cone"));
934 }
935
936 #[test]
937 fn test_of_pie_chart_serialize() {
938 let of_pie = OfPieChart {
939 of_pie_type: StringVal {
940 val: "pie".to_string(),
941 },
942 series: vec![Series {
943 idx: UintVal { val: 0 },
944 order: UintVal { val: 0 },
945 tx: None,
946 cat: None,
947 val: None,
948 }],
949 ser_lines: Some(SerLines {}),
950 };
951 let xml = quick_xml::se::to_string(&of_pie).unwrap();
952 assert!(xml.contains("val=\"pie\""));
953 assert!(xml.contains("serLines"));
954 }
955
956 #[test]
957 fn test_bubble_series_with_bubble_3d() {
958 let bs = BubbleSeries {
959 idx: UintVal { val: 0 },
960 order: UintVal { val: 0 },
961 tx: None,
962 x_val: None,
963 y_val: None,
964 bubble_size: None,
965 bubble_3d: Some(BoolVal { val: true }),
966 };
967 let xml = quick_xml::se::to_string(&bs).unwrap();
968 assert!(xml.contains("bubble3D"));
969 assert!(xml.contains("val=\"true\""));
970 }
971}