ppt_rs/parts/
vba_macro.rs1use super::base::{Part, PartType, ContentType};
7use crate::exc::PptxError;
8
9#[derive(Debug, Clone)]
11pub struct VbaProjectPart {
12 path: String,
13 data: Vec<u8>,
14 modules: Vec<VbaModule>,
15}
16
17#[derive(Debug, Clone)]
19pub struct VbaModule {
20 pub name: String,
21 pub code: String,
22 pub module_type: VbaModuleType,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum VbaModuleType {
28 Standard,
29 Class,
30 Form,
31 Document,
32}
33
34impl VbaModule {
35 pub fn new(name: impl Into<String>, code: impl Into<String>) -> Self {
37 VbaModule {
38 name: name.into(),
39 code: code.into(),
40 module_type: VbaModuleType::Standard,
41 }
42 }
43
44 pub fn class(name: impl Into<String>, code: impl Into<String>) -> Self {
46 VbaModule {
47 name: name.into(),
48 code: code.into(),
49 module_type: VbaModuleType::Class,
50 }
51 }
52
53 pub fn module_type(mut self, module_type: VbaModuleType) -> Self {
55 self.module_type = module_type;
56 self
57 }
58}
59
60impl VbaProjectPart {
61 pub fn new() -> Self {
63 VbaProjectPart {
64 path: "ppt/vbaProject.bin".to_string(),
65 data: vec![],
66 modules: vec![],
67 }
68 }
69
70 pub fn from_data(data: Vec<u8>) -> Self {
72 VbaProjectPart {
73 path: "ppt/vbaProject.bin".to_string(),
74 data,
75 modules: vec![],
76 }
77 }
78
79 pub fn add_module(mut self, module: VbaModule) -> Self {
81 self.modules.push(module);
82 self
83 }
84
85 pub fn modules(&self) -> &[VbaModule] {
87 &self.modules
88 }
89
90 pub fn data(&self) -> &[u8] {
92 &self.data
93 }
94
95 pub fn is_macro_enabled(&self) -> bool {
97 !self.data.is_empty() || !self.modules.is_empty()
98 }
99
100 pub fn macro_content_type() -> &'static str {
102 "application/vnd.ms-office.vbaProject"
103 }
104
105 pub fn macro_extension() -> &'static str {
107 "pptm"
108 }
109}
110
111impl Default for VbaProjectPart {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117impl Part for VbaProjectPart {
118 fn path(&self) -> &str {
119 &self.path
120 }
121
122 fn part_type(&self) -> PartType {
123 PartType::Relationships }
125
126 fn content_type(&self) -> ContentType {
127 ContentType::Xml }
129
130 fn to_xml(&self) -> Result<String, PptxError> {
131 Err(PptxError::InvalidOperation("VBA projects are binary, not XML".to_string()))
133 }
134
135 fn from_xml(_xml: &str) -> Result<Self, PptxError> {
136 Err(PptxError::InvalidOperation("VBA projects cannot be created from XML".to_string()))
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
142pub enum MacroSecurity {
143 #[default]
144 DisableAll,
145 DisableWithNotification,
146 DisableExceptDigitallySigned,
147 EnableAll,
148}
149
150impl MacroSecurity {
151 pub fn as_str(&self) -> &'static str {
152 match self {
153 MacroSecurity::DisableAll => "DisableAll",
154 MacroSecurity::DisableWithNotification => "DisableWithNotification",
155 MacroSecurity::DisableExceptDigitallySigned => "DisableExceptDigitallySigned",
156 MacroSecurity::EnableAll => "EnableAll",
157 }
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 fn test_vba_project_new() {
167 let project = VbaProjectPart::new();
168 assert_eq!(project.path(), "ppt/vbaProject.bin");
169 assert!(!project.is_macro_enabled());
170 }
171
172 #[test]
173 fn test_vba_module_new() {
174 let module = VbaModule::new("Module1", "Sub Test()\nEnd Sub");
175 assert_eq!(module.name, "Module1");
176 assert_eq!(module.module_type, VbaModuleType::Standard);
177 }
178
179 #[test]
180 fn test_vba_module_class() {
181 let module = VbaModule::class("MyClass", "Private x As Integer");
182 assert_eq!(module.module_type, VbaModuleType::Class);
183 }
184
185 #[test]
186 fn test_vba_project_add_module() {
187 let project = VbaProjectPart::new()
188 .add_module(VbaModule::new("Module1", "Sub Test()\nEnd Sub"))
189 .add_module(VbaModule::class("Class1", ""));
190 assert_eq!(project.modules().len(), 2);
191 assert!(project.is_macro_enabled());
192 }
193
194 #[test]
195 fn test_vba_from_data() {
196 let project = VbaProjectPart::from_data(vec![0x00, 0x01, 0x02]);
197 assert!(project.is_macro_enabled());
198 assert_eq!(project.data().len(), 3);
199 }
200
201 #[test]
202 fn test_macro_extension() {
203 assert_eq!(VbaProjectPart::macro_extension(), "pptm");
204 }
205}